* src/SDCCicode.c (geniCodePreInc, geniCodePreDec, ast2iCode):
[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 (ul != (TYPE_UWORD) ul)
1098                 werror (W_INT_OVL);
1099             }
1100           else /* signed int */
1101             {
1102               /* signed int is handled here in order to detect overflow */
1103               TYPE_DWORD l = (TYPE_WORD) operandLitValue (left) *
1104                              (TYPE_WORD) operandLitValue (right);
1105
1106               retval = operandFromValue (valCastLiteral (type, (TYPE_WORD) l));
1107               if (l != (TYPE_WORD) l)
1108                 werror (W_INT_OVL);
1109             }
1110         }
1111       else
1112         /* all others go here: */
1113         retval = operandFromValue (valCastLiteral (type,
1114                                                    operandLitValue (left) *
1115                                                    operandLitValue (right)));
1116       break;
1117     case '/':
1118       if ((TYPE_UDWORD) operandLitValue (right) == 0)
1119         {
1120           werror (E_DIVIDE_BY_ZERO);
1121           retval = right;
1122
1123         }
1124       else
1125         retval = operandFromValue (valCastLiteral (type,
1126                                                    operandLitValue (left) /
1127                                                    operandLitValue (right)));
1128       break;
1129     case '%':
1130       if ((TYPE_UDWORD) operandLitValue (right) == 0) {
1131           werror (E_DIVIDE_BY_ZERO);
1132           retval = right;
1133       }
1134       else
1135         {
1136           if (SPEC_USIGN(let) || SPEC_USIGN(ret))
1137             /* one of the operands is unsigned */
1138             retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) %
1139                                      (TYPE_UDWORD) operandLitValue (right));
1140           else
1141             /* both operands are signed */
1142             retval = operandFromLit ((TYPE_DWORD) operandLitValue (left) %
1143                                      (TYPE_DWORD) operandLitValue (right));
1144         }
1145       break;
1146     case LEFT_OP:
1147       /* The number of left shifts is always unsigned. Signed doesn't make
1148          sense here. Shifting by a negative number is impossible. */
1149       retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) <<
1150                                (TYPE_UDWORD) operandLitValue (right));
1151       break;
1152     case RIGHT_OP:
1153       /* The number of right shifts is always unsigned. Signed doesn't make
1154          sense here. Shifting by a negative number is impossible. */
1155       if (SPEC_USIGN(let))
1156         /* unsigned: logic shift right */
1157         retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) >>
1158                                  (TYPE_UDWORD) operandLitValue (right));
1159       else
1160         /* signed: arithmetic shift right */
1161         retval = operandFromLit ((TYPE_DWORD ) operandLitValue (left) >>
1162                                  (TYPE_UDWORD) operandLitValue (right));
1163       break;
1164     case EQ_OP:
1165       /* this op doesn't care about signedness */
1166       {
1167         TYPE_UDWORD l, r;
1168
1169         l = (TYPE_UDWORD) operandLitValue (left);
1170         if (SPEC_NOUN(OP_VALUE(left)->type) == V_CHAR)
1171           l &= 0xff;
1172         else if (!SPEC_LONG (OP_VALUE(left)->type))
1173           l &= 0xffff;
1174         r = (TYPE_UDWORD) operandLitValue (right);
1175         if (SPEC_NOUN(OP_VALUE(right)->type) == V_CHAR)
1176           r &= 0xff;
1177         else if (!SPEC_LONG (OP_VALUE(right)->type))
1178           r &= 0xffff;
1179         retval = operandFromLit (l == r);
1180       }
1181       break;
1182     case '<':
1183       retval = operandFromLit (operandLitValue (left) <
1184                                operandLitValue (right));
1185       break;
1186     case LE_OP:
1187       retval = operandFromLit (operandLitValue (left) <=
1188                                operandLitValue (right));
1189       break;
1190     case NE_OP:
1191       retval = operandFromLit (operandLitValue (left) !=
1192                                operandLitValue (right));
1193       break;
1194     case '>':
1195       retval = operandFromLit (operandLitValue (left) >
1196                                operandLitValue (right));
1197       break;
1198     case GE_OP:
1199       retval = operandFromLit (operandLitValue (left) >=
1200                                operandLitValue (right));
1201       break;
1202     case BITWISEAND:
1203       retval = operandFromValue (valCastLiteral (type,
1204                                                  (TYPE_UDWORD)operandLitValue(left) &
1205                                                  (TYPE_UDWORD)operandLitValue(right)));
1206       break;
1207     case '|':
1208       retval = operandFromValue (valCastLiteral (type,
1209                                                  (TYPE_UDWORD)operandLitValue(left) |
1210                                                  (TYPE_UDWORD)operandLitValue(right)));
1211       break;
1212     case '^':
1213       retval = operandFromValue (valCastLiteral (type,
1214                                                  (TYPE_UDWORD)operandLitValue(left) ^
1215                                                  (TYPE_UDWORD)operandLitValue(right)));
1216       break;
1217     case AND_OP:
1218       retval = operandFromLit (operandLitValue (left) &&
1219                                operandLitValue (right));
1220       break;
1221     case OR_OP:
1222       retval = operandFromLit (operandLitValue (left) ||
1223                                operandLitValue (right));
1224       break;
1225     case RRC:
1226       {
1227         TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
1228
1229         retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
1230                                  (i << 1));
1231       }
1232       break;
1233     case RLC:
1234       {
1235         TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
1236
1237         retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
1238                                  (i >> 1));
1239       }
1240       break;
1241
1242     case UNARYMINUS:
1243       retval = operandFromValue (valCastLiteral (type,
1244                                                  -1 * operandLitValue (left)));
1245       break;
1246
1247     case '~':
1248       retval = operandFromLit (~((TYPE_UDWORD) operandLitValue (left)));
1249       break;
1250
1251     case '!':
1252       retval = operandFromLit (!operandLitValue (left));
1253       break;
1254
1255     default:
1256       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1257               " operandOperation invalid operator ");
1258       assert (0);
1259     }
1260
1261   return retval;
1262 }
1263
1264
1265 /*-----------------------------------------------------------------*/
1266 /* isOperandEqual - compares two operand & return 1 if they r =    */
1267 /*-----------------------------------------------------------------*/
1268 int
1269 isOperandEqual (operand * left, operand * right)
1270 {
1271   /* if the pointers are equal then they are equal */
1272   if (left == right)
1273     return 1;
1274
1275   /* if either of them null then false */
1276   if (!left || !right)
1277     return 0;
1278
1279   if (left->type != right->type)
1280     return 0;
1281
1282   if (IS_SYMOP (left) && IS_SYMOP (right))
1283     return left->key == right->key;
1284
1285   /* if types are the same */
1286   switch (left->type)
1287     {
1288     case SYMBOL:
1289       return isSymbolEqual (left->operand.symOperand,
1290                             right->operand.symOperand);
1291     case VALUE:
1292       return (floatFromVal (left->operand.valOperand) ==
1293               floatFromVal (right->operand.valOperand));
1294     case TYPE:
1295       if (compareType (left->operand.typeOperand,
1296                      right->operand.typeOperand) == 1)
1297         return 1;
1298     }
1299
1300   return 0;
1301 }
1302
1303 /*-------------------------------------------------------------------*/
1304 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1305 /*-------------------------------------------------------------------*/
1306 int 
1307 isiCodeEqual (iCode * left, iCode * right)
1308 {
1309   /* if the same pointer */
1310   if (left == right)
1311     return 1;
1312
1313   /* if either of them null */
1314   if (!left || !right)
1315     return 0;
1316
1317   /* if operand are the same */
1318   if (left->op == right->op)
1319     {
1320
1321       /* compare all the elements depending on type */
1322       if (left->op != IFX)
1323         {
1324           if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1325             return 0;
1326           if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1327             return 0;
1328
1329         }
1330       else
1331         {
1332           if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1333             return 0;
1334           if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1335             return 0;
1336           if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1337             return 0;
1338         }
1339       
1340       return 1;
1341     }
1342   return 0;
1343 }
1344
1345 /*-----------------------------------------------------------------*/
1346 /* newiTempFromOp - create a temp Operand with same attributes     */
1347 /*-----------------------------------------------------------------*/
1348 operand *
1349 newiTempFromOp (operand * op)
1350 {
1351   operand *nop;
1352
1353   if (!op)
1354     return NULL;
1355
1356   if (!IS_ITEMP (op))
1357     return op;
1358
1359   nop = newiTempOperand (operandType (op), TRUE);
1360   nop->isaddr = op->isaddr;
1361   nop->isvolatile = op->isvolatile;
1362   nop->isGlobal = op->isGlobal;
1363   nop->isLiteral = op->isLiteral;
1364   nop->usesDefs = op->usesDefs;
1365   nop->isParm = op->isParm;
1366   return nop;
1367 }
1368
1369 /*-----------------------------------------------------------------*/
1370 /* operand from operand - creates an operand holder for the type   */
1371 /*-----------------------------------------------------------------*/
1372 operand *
1373 operandFromOperand (operand * op)
1374 {
1375   operand *nop;
1376
1377   if (!op)
1378     return NULL;
1379   nop = newOperand ();
1380   nop->type = op->type;
1381   nop->isaddr = op->isaddr;
1382   nop->key = op->key;
1383   nop->isvolatile = op->isvolatile;
1384   nop->isGlobal = op->isGlobal;
1385   nop->isLiteral = op->isLiteral;
1386   nop->usesDefs = op->usesDefs;
1387   nop->isParm = op->isParm;
1388
1389   switch (nop->type)
1390     {
1391     case SYMBOL:
1392       nop->operand.symOperand = op->operand.symOperand;
1393       break;
1394     case VALUE:
1395       nop->operand.valOperand = op->operand.valOperand;
1396       break;
1397     case TYPE:
1398       nop->operand.typeOperand = op->operand.typeOperand;
1399       break;
1400     }
1401
1402   return nop;
1403 }
1404
1405 /*-----------------------------------------------------------------*/
1406 /* opFromOpWithDU - makes a copy of the operand and DU chains      */
1407 /*-----------------------------------------------------------------*/
1408 operand *
1409 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1410 {
1411   operand *nop = operandFromOperand (op);
1412
1413   if (nop->type == SYMBOL)
1414     {
1415       OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1416       OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1417     }
1418
1419   return nop;
1420 }
1421
1422 /*-----------------------------------------------------------------*/
1423 /* operandFromSymbol - creates an operand from a symbol            */
1424 /*-----------------------------------------------------------------*/
1425 operand *
1426 operandFromSymbol (symbol * sym)
1427 {
1428   operand *op;
1429   iCode *ic;
1430   int ok = 1;
1431   /* if the symbol's type is a literal */
1432   /* then it is an enumerator type     */
1433   if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1434     return operandFromValue (valFromType (sym->etype));
1435
1436   if (!sym->key)
1437     sym->key = ++operandKey;
1438
1439   /* if this an implicit variable, means struct/union */
1440   /* member so just return it                         */
1441   if (sym->implicit || IS_FUNC (sym->type))
1442     {
1443       op = newOperand ();
1444       op->type = SYMBOL;
1445       op->operand.symOperand = sym;
1446       op->key = sym->key;
1447       op->isvolatile = isOperandVolatile (op, TRUE);
1448       op->isGlobal = isOperandGlobal (op);
1449       return op;
1450     }
1451
1452   /* under the following conditions create a
1453      register equivalent for a local symbol */
1454   if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1455       (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1456       (!(options.model == MODEL_FLAT24)) ) &&
1457       options.stackAuto == 0)
1458     ok = 0;
1459
1460   if (!IS_AGGREGATE (sym->type) &&      /* not an aggregate */
1461       !IS_FUNC (sym->type) &&   /* not a function   */
1462       !sym->_isparm &&          /* not a parameter  */
1463       sym->level &&             /* is a local variable */
1464       !sym->addrtaken &&        /* whose address has not been taken */
1465       !sym->reqv &&             /* does not already have a reg equivalence */
1466       !IS_VOLATILE (sym->etype) &&      /* not declared as volatile */
1467       !IS_STATIC (sym->etype) &&        /* and not declared static  */
1468       !sym->islbl &&            /* not a label */
1469       ok &&                     /* farspace check */
1470       !IS_BITVAR (sym->etype)   /* not a bit variable */
1471     )
1472     {                                   
1473
1474       /* we will use it after all optimizations
1475          and before liveRange calculation */
1476       sym->reqv = newiTempOperand (sym->type, 0);
1477       sym->reqv->key = sym->key;
1478       OP_SYMBOL (sym->reqv)->key = sym->key;
1479       OP_SYMBOL (sym->reqv)->isreqv = 1;
1480       OP_SYMBOL (sym->reqv)->islocal = 1;
1481       OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
1482       SPIL_LOC (sym->reqv) = sym;
1483     }
1484
1485   if (!IS_AGGREGATE (sym->type))
1486     {
1487       op = newOperand ();
1488       op->type = SYMBOL;
1489       op->operand.symOperand = sym;
1490       op->isaddr = 1;
1491       op->key = sym->key;
1492       op->isvolatile = isOperandVolatile (op, TRUE);
1493       op->isGlobal = isOperandGlobal (op);
1494       op->isPtr = IS_PTR (operandType (op));
1495       op->isParm = sym->_isparm;
1496       return op;
1497     }
1498
1499   /* create :-                     */
1500   /*    itemp = &[_symbol]         */
1501
1502   ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1503   IC_LEFT (ic)->type = SYMBOL;
1504   IC_LEFT (ic)->operand.symOperand = sym;
1505   IC_LEFT (ic)->key = sym->key;
1506   (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1507   (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1508   IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1509
1510   /* create result */
1511   IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1512   if (IS_ARRAY (sym->type))
1513     {
1514       IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1515       IC_RESULT (ic)->isaddr = 0;
1516     }
1517   else
1518     IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1519
1520   ADDTOCHAIN (ic);
1521
1522   return IC_RESULT (ic);
1523 }
1524
1525 /*-----------------------------------------------------------------*/
1526 /* operandFromValue - creates an operand from value                */
1527 /*-----------------------------------------------------------------*/
1528 operand *
1529 operandFromValue (value * val)
1530 {
1531   operand *op;
1532
1533   /* if this is a symbol then do the symbol thing */
1534   if (val->sym)
1535     return operandFromSymbol (val->sym);
1536
1537   /* this is not a symbol */
1538   op = newOperand ();
1539   op->type = VALUE;
1540   op->operand.valOperand = val;
1541   op->isLiteral = isOperandLiteral (op);
1542   return op;
1543 }
1544
1545 /*-----------------------------------------------------------------*/
1546 /* operandFromLink - operand from typeChain                        */
1547 /*-----------------------------------------------------------------*/
1548 operand *
1549 operandFromLink (sym_link * type)
1550 {
1551   operand *op;
1552
1553   /* operand from sym_link */
1554   if (!type)
1555     return NULL;
1556
1557   op = newOperand ();
1558   op->type = TYPE;
1559   op->operand.typeOperand = copyLinkChain (type);
1560   return op;
1561 }
1562
1563 /*-----------------------------------------------------------------*/
1564 /* operandFromLit - makes an operand from a literal value          */
1565 /*-----------------------------------------------------------------*/
1566 operand *
1567 operandFromLit (double i)
1568 {
1569   return operandFromValue (valueFromLit (i));
1570 }
1571
1572 /*-----------------------------------------------------------------*/
1573 /* operandFromAst - creates an operand from an ast                 */
1574 /*-----------------------------------------------------------------*/
1575 operand *
1576 operandFromAst (ast * tree,int lvl)
1577 {
1578
1579   if (!tree)
1580     return NULL;
1581
1582   /* depending on type do */
1583   switch (tree->type)
1584     {
1585     case EX_OP:
1586       return ast2iCode (tree,lvl+1);
1587       break;
1588
1589     case EX_VALUE:
1590       return operandFromValue (tree->opval.val);
1591       break;
1592
1593     case EX_LINK:
1594       return operandFromLink (tree->opval.lnk);
1595       break;
1596
1597     default:
1598       assert (0);
1599     }
1600   
1601   /*  Just to keep the compiler happy */
1602   return (operand *) 0;
1603 }
1604
1605 /*-----------------------------------------------------------------*/
1606 /* setOperandType - sets the operand's type to the given type      */
1607 /*-----------------------------------------------------------------*/
1608 void 
1609 setOperandType (operand * op, sym_link * type)
1610 {
1611   /* depending on the type of operand */
1612   switch (op->type)
1613     {
1614
1615     case VALUE:
1616       op->operand.valOperand->etype =
1617         getSpec (op->operand.valOperand->type =
1618                  copyLinkChain (type));
1619       return;
1620
1621     case SYMBOL:
1622       if (op->operand.symOperand->isitmp)
1623         op->operand.symOperand->etype =
1624           getSpec (op->operand.symOperand->type =
1625                    copyLinkChain (type));
1626       else
1627         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1628                 "attempt to modify type of source");
1629       return;
1630
1631     case TYPE:
1632       op->operand.typeOperand = copyLinkChain (type);
1633       return;
1634     }
1635
1636 }
1637 /*-----------------------------------------------------------------*/
1638 /* Get size in byte of ptr need to access an array                 */
1639 /*-----------------------------------------------------------------*/
1640 int
1641 getArraySizePtr (operand * op)
1642 {
1643   sym_link *ltype = operandType(op);
1644
1645   if(IS_PTR(ltype))
1646     {
1647       int size = getSize(ltype);
1648       return(IS_GENPTR(ltype)?(size-1):size);
1649     }
1650
1651   if(IS_ARRAY(ltype))
1652     {
1653       sym_link *letype = getSpec(ltype);
1654       switch (PTR_TYPE (SPEC_OCLS (letype)))
1655         {
1656         case IPOINTER:
1657         case PPOINTER:
1658         case POINTER:
1659           return (PTRSIZE);
1660         case EEPPOINTER:
1661         case FPOINTER:
1662         case CPOINTER:
1663         case FUNCTION:
1664           return (FPTRSIZE);
1665         case GPOINTER:
1666           return (GPTRSIZE-1);
1667
1668         default:
1669           return (FPTRSIZE);
1670         }
1671     }
1672   return (FPTRSIZE);
1673 }
1674
1675 /*-----------------------------------------------------------------*/
1676 /* perform "usual unary conversions"                               */
1677 /*-----------------------------------------------------------------*/
1678 operand *
1679 usualUnaryConversions (operand * op)
1680 {
1681   if (IS_INTEGRAL (operandType (op)))
1682     {
1683       if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1684         {
1685           /* Widen to int. */
1686           return geniCodeCast (INTTYPE, op, TRUE);
1687         }
1688     }
1689   return op;
1690 }
1691
1692 /*-----------------------------------------------------------------*/
1693 /* perform "usual binary conversions"                              */
1694 /*-----------------------------------------------------------------*/
1695 sym_link *
1696 usualBinaryConversions (operand ** op1, operand ** op2)
1697 {
1698   sym_link *ctype;
1699   sym_link *rtype = operandType (*op2);
1700   sym_link *ltype = operandType (*op1);
1701   
1702   ctype = computeType (ltype, rtype);
1703
1704   *op1 = geniCodeCast (ctype, *op1, TRUE);
1705   *op2 = geniCodeCast (ctype, *op2, TRUE);
1706   
1707   return ctype;
1708 }
1709
1710 /*-----------------------------------------------------------------*/
1711 /* geniCodeValueAtAddress - generate intermeditate code for value  */
1712 /*                          at address                             */
1713 /*-----------------------------------------------------------------*/
1714 operand *
1715 geniCodeRValue (operand * op, bool force)
1716 {
1717   iCode *ic;
1718   sym_link *type = operandType (op);
1719   sym_link *etype = getSpec (type);
1720
1721   /* if this is an array & already */
1722   /* an address then return this   */
1723   if (IS_AGGREGATE (type) ||
1724       (IS_PTR (type) && !force && !op->isaddr))
1725     return operandFromOperand (op);
1726
1727   /* if this is not an address then must be */
1728   /* rvalue already so return this one      */
1729   if (!op->isaddr)
1730     return op;
1731
1732   /* if this is not a temp symbol then */
1733   if (!IS_ITEMP (op) &&
1734       !force &&
1735       !IN_FARSPACE (SPEC_OCLS (etype)))
1736     {
1737       op = operandFromOperand (op);
1738       op->isaddr = 0;
1739       return op;
1740     }
1741
1742   if (IS_SPEC (type) &&
1743       IS_TRUE_SYMOP (op) &&
1744       (!IN_FARSPACE (SPEC_OCLS (etype)) ||
1745       (options.model == MODEL_FLAT24) ))
1746     {
1747       op = operandFromOperand (op);
1748       op->isaddr = 0;
1749       return op;
1750     }
1751
1752   ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1753   if (IS_PTR (type) && op->isaddr && force)
1754     type = type->next;
1755
1756   type = copyLinkChain (type);
1757
1758   IC_RESULT (ic) = newiTempOperand (type, 1);
1759   IC_RESULT (ic)->isaddr = 0;
1760
1761 /*     ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1762
1763   ADDTOCHAIN (ic);
1764
1765   return IC_RESULT (ic);
1766 }
1767
1768 /*-----------------------------------------------------------------*/
1769 /* geniCodeCast - changes the value from one type to another       */
1770 /*-----------------------------------------------------------------*/
1771 operand *
1772 geniCodeCast (sym_link * type, operand * op, bool implicit)
1773 {
1774   iCode *ic;
1775   sym_link *optype;
1776   sym_link *opetype = getSpec (optype = operandType (op));
1777   sym_link *restype;
1778   int errors=0;
1779
1780   /* one of them has size zero then error */
1781   if (IS_VOID (optype))
1782     {
1783       werror (E_CAST_ZERO);
1784       return op;
1785     }
1786
1787   /* if the operand is already the desired type then do nothing */
1788   if (compareType (type, optype) == 1)
1789     return op;
1790
1791   /* if this is a literal then just change the type & return */
1792   if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1793     return operandFromValue (valCastLiteral (type,
1794                                              operandLitValue (op)));
1795
1796   /* if casting to/from pointers, do some checking */
1797   if (IS_PTR(type)) { // to a pointer
1798     if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1799       if (IS_INTEGRAL(optype)) { 
1800         // maybe this is NULL, than it's ok. 
1801         if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1802           if (port->s.gptr_size > port->s.fptr_size && IS_GENPTR(type)) {
1803             // no way to set the storage
1804             if (IS_LITERAL(optype)) {
1805               werror(E_LITERAL_GENERIC);
1806               errors++;
1807             } else {
1808               werror(E_NONPTR2_GENPTR);
1809               errors++;
1810             }
1811           } else if (implicit) {
1812             werror(W_INTEGRAL2PTR_NOCAST);
1813             errors++;
1814           }
1815         }
1816       } else { 
1817         // shouldn't do that with float, array or structure unless to void
1818         if (!IS_VOID(getSpec(type)) && 
1819             !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1820           werror(E_INCOMPAT_TYPES);
1821           errors++;
1822         }
1823       }
1824     } else { // from a pointer to a pointer
1825       if (port->s.gptr_size > port->s.fptr_size /*!TARGET_IS_Z80 && !TARGET_IS_GBZ80*/) {
1826         // if not a pointer to a function
1827         if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1828           if (implicit) { // if not to generic, they have to match 
1829             if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1830               werror(E_INCOMPAT_PTYPES);
1831               errors++;
1832             }
1833           }
1834         }
1835       }
1836     }
1837   } else { // to a non pointer
1838     if (IS_PTR(optype)) { // from a pointer
1839       if (implicit) { // sneaky
1840         if (IS_INTEGRAL(type)) {
1841           werror(W_PTR2INTEGRAL_NOCAST);
1842           errors++;
1843         } else { // shouldn't do that with float, array or structure
1844           werror(E_INCOMPAT_TYPES);
1845           errors++;
1846         }
1847       }
1848     }
1849   }
1850   if (errors) {
1851     printFromToType (optype, type);
1852   }
1853
1854   /* if they are the same size create an assignment */
1855   if (getSize (type) == getSize (optype) &&
1856       !IS_BITFIELD (type) &&
1857       !IS_FLOAT (type) &&
1858       !IS_FLOAT (optype) &&
1859       ((IS_SPEC (type) && IS_SPEC (optype)) ||
1860        (!IS_SPEC (type) && !IS_SPEC (optype))))
1861     {
1862
1863       ic = newiCode ('=', NULL, op);
1864       IC_RESULT (ic) = newiTempOperand (type, 0);
1865       SPIL_LOC (IC_RESULT (ic)) =
1866         (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1867       IC_RESULT (ic)->isaddr = 0;
1868     }
1869   else
1870     {
1871       ic = newiCode (CAST, operandFromLink (type),
1872                      geniCodeRValue (op, FALSE));
1873
1874       IC_RESULT (ic) = newiTempOperand (type, 0);
1875     }
1876
1877   /* preserve the storage class & output class */
1878   /* of the original variable                  */
1879   restype = getSpec (operandType (IC_RESULT (ic)));
1880   if (!IS_LITERAL(opetype))
1881       SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1882   SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1883
1884   ADDTOCHAIN (ic);
1885   return IC_RESULT (ic);
1886 }
1887
1888 /*-----------------------------------------------------------------*/
1889 /* geniCodeLabel - will create a Label                             */
1890 /*-----------------------------------------------------------------*/
1891 void 
1892 geniCodeLabel (symbol * label)
1893 {
1894   iCode *ic;
1895
1896   ic = newiCodeLabelGoto (LABEL, label);
1897   ADDTOCHAIN (ic);
1898 }
1899
1900 /*-----------------------------------------------------------------*/
1901 /* geniCodeGoto  - will create a Goto                              */
1902 /*-----------------------------------------------------------------*/
1903 void 
1904 geniCodeGoto (symbol * label)
1905 {
1906   iCode *ic;
1907
1908   ic = newiCodeLabelGoto (GOTO, label);
1909   ADDTOCHAIN (ic);
1910 }
1911
1912 /*-----------------------------------------------------------------*/
1913 /* geniCodeMultiply - gen intermediate code for multiplication     */
1914 /*-----------------------------------------------------------------*/
1915 operand *
1916 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1917 {
1918   iCode *ic;
1919   int p2 = 0;
1920   sym_link *resType;
1921   LRTYPE;
1922
1923   /* if they are both literal then we know the result */
1924   if (IS_LITERAL (letype) && IS_LITERAL (retype))
1925     return operandFromValue (valMult (left->operand.valOperand,
1926                                       right->operand.valOperand));
1927
1928   if (IS_LITERAL(retype)) {
1929     p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1930   }
1931
1932   resType = usualBinaryConversions (&left, &right);
1933 #if 1
1934   rtype = operandType (right);
1935   retype = getSpec (rtype);
1936   ltype = operandType (left);
1937   letype = getSpec (ltype);
1938 #endif
1939   if (resultIsInt)
1940     {
1941       SPEC_NOUN(getSpec(resType))=V_INT;
1942     }
1943
1944   /* if the right is a literal & power of 2 */
1945   /* then make it a left shift              */
1946   /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
1947      efficient in most cases than 2 bytes result = 2 bytes << literal
1948      if port has 1 byte muldiv */
1949   if (p2 && !IS_FLOAT (letype) &&
1950       !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
1951         (port->support.muldiv == 1)))
1952     {
1953       if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1954         {
1955           /* LEFT_OP need same size for left and result, */
1956           left = geniCodeCast (resType, left, TRUE);
1957           ltype = operandType (left);
1958         }
1959       ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1960     }
1961   else
1962     {
1963       ic = newiCode ('*', left, right);         /* normal multiplication */
1964       /* if the size left or right > 1 then support routine */
1965       if (getSize (ltype) > 1 || getSize (rtype) > 1)
1966         ic->supportRtn = 1;
1967
1968     }
1969   IC_RESULT (ic) = newiTempOperand (resType, 1);
1970
1971   ADDTOCHAIN (ic);
1972   return IC_RESULT (ic);
1973 }
1974
1975 /*-----------------------------------------------------------------*/
1976 /* geniCodeDivision - gen intermediate code for division           */
1977 /*-----------------------------------------------------------------*/
1978 operand *
1979 geniCodeDivision (operand * left, operand * right)
1980 {
1981   iCode *ic;
1982   int p2 = 0;
1983   sym_link *resType;
1984   sym_link *rtype = operandType (right);
1985   sym_link *retype = getSpec (rtype);
1986   sym_link *ltype = operandType (left);
1987   sym_link *letype = getSpec (ltype);
1988
1989   resType = usualBinaryConversions (&left, &right);
1990
1991   /* if the right is a literal & power of 2
1992      and left is unsigned then make it a
1993      right shift */
1994   if (IS_LITERAL (retype) &&
1995       !IS_FLOAT (letype) &&
1996       SPEC_USIGN(letype) &&
1997       (p2 = powof2 ((unsigned long)
1998                     floatFromVal (right->operand.valOperand)))) {
1999     ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
2000   }
2001   else
2002     {
2003       ic = newiCode ('/', left, right);         /* normal division */
2004       /* if the size left or right > 1 then support routine */
2005       if (getSize (ltype) > 1 || getSize (rtype) > 1)
2006         ic->supportRtn = 1;
2007     }
2008   IC_RESULT (ic) = newiTempOperand (resType, 0);
2009
2010   ADDTOCHAIN (ic);
2011   return IC_RESULT (ic);
2012 }
2013 /*-----------------------------------------------------------------*/
2014 /* geniCodeModulus  - gen intermediate code for modulus            */
2015 /*-----------------------------------------------------------------*/
2016 operand *
2017 geniCodeModulus (operand * left, operand * right)
2018 {
2019   iCode *ic;
2020   sym_link *resType;
2021   LRTYPE;
2022
2023   /* if they are both literal then we know the result */
2024   if (IS_LITERAL (letype) && IS_LITERAL (retype))
2025     return operandFromValue (valMod (left->operand.valOperand,
2026                                      right->operand.valOperand));
2027
2028   resType = usualBinaryConversions (&left, &right);
2029
2030   /* now they are the same size */
2031   ic = newiCode ('%', left, right);
2032
2033   /* if the size left or right > 1 then support routine */
2034   if (getSize (ltype) > 1 || getSize (rtype) > 1)
2035     ic->supportRtn = 1;
2036   IC_RESULT (ic) = newiTempOperand (resType, 0);
2037
2038   ADDTOCHAIN (ic);
2039   return IC_RESULT (ic);
2040 }
2041
2042 /*-----------------------------------------------------------------*/
2043 /* geniCodePtrPtrSubtract - subtracts pointer from pointer         */
2044 /*-----------------------------------------------------------------*/
2045 operand *
2046 geniCodePtrPtrSubtract (operand * left, operand * right)
2047 {
2048   iCode *ic;
2049   operand *result;
2050   LRTYPE;
2051
2052   /* if they are both literals then */
2053   if (IS_LITERAL (letype) && IS_LITERAL (retype))
2054     {
2055       result = operandFromValue (valMinus (left->operand.valOperand,
2056                                            right->operand.valOperand));
2057       goto subtractExit;
2058     }
2059
2060   ic = newiCode ('-', left, right);
2061
2062   IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
2063   ADDTOCHAIN (ic);
2064
2065 subtractExit:
2066   if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
2067     return result;
2068   }
2069
2070   // should we really do this? is this ANSI?
2071   return geniCodeDivision (result,
2072                            operandFromLit (getSize (ltype->next)));
2073 }
2074
2075 /*-----------------------------------------------------------------*/
2076 /* geniCodeSubtract - generates code for subtraction               */
2077 /*-----------------------------------------------------------------*/
2078 operand *
2079 geniCodeSubtract (operand * left, operand * right)
2080 {
2081   iCode *ic;
2082   int isarray = 0;
2083   sym_link *resType;
2084   LRTYPE;
2085
2086   /* if they both pointers then */
2087   if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
2088       (IS_PTR (rtype) || IS_ARRAY (rtype)))
2089     return geniCodePtrPtrSubtract (left, right);
2090
2091   /* if they are both literal then we know the result */
2092   if (IS_LITERAL (letype) && IS_LITERAL (retype)
2093       && left->isLiteral && right->isLiteral)
2094     return operandFromValue (valMinus (left->operand.valOperand,
2095                                        right->operand.valOperand));
2096
2097   /* if left is an array or pointer */
2098   if (IS_PTR (ltype) || IS_ARRAY (ltype))
2099     {
2100       isarray = left->isaddr;
2101       right = geniCodeMultiply (right,
2102                                 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2103       resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2104     }
2105   else
2106     {                           /* make them the same size */
2107       resType = usualBinaryConversions (&left, &right);
2108     }
2109
2110   ic = newiCode ('-', left, right);
2111
2112   IC_RESULT (ic) = newiTempOperand (resType, 1);
2113   IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2114
2115   /* if left or right is a float */
2116   if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2117     ic->supportRtn = 1;
2118
2119   ADDTOCHAIN (ic);
2120   return IC_RESULT (ic);
2121 }
2122
2123 /*-----------------------------------------------------------------*/
2124 /* geniCodeAdd - generates iCode for addition                      */
2125 /*-----------------------------------------------------------------*/
2126 operand *
2127 geniCodeAdd (operand * left, operand * right, int lvl)
2128 {
2129   iCode *ic;
2130   sym_link *resType;
2131   operand *size;
2132   int isarray = 0;
2133   LRTYPE;
2134
2135   /* if the right side is LITERAL zero */
2136   /* return the left side              */
2137   if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
2138     return left;
2139
2140   /* if left is literal zero return right */
2141   if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
2142     return right;
2143
2144   /* if left is a pointer then size */
2145   if (IS_PTR (ltype) || IS_ARRAY(ltype))
2146     {
2147       isarray = left->isaddr;
2148       // there is no need to multiply with 1
2149       if (getSize(ltype->next)!=1) {
2150         size  = operandFromLit (getSize (ltype->next));
2151         right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
2152       }
2153       resType = copyLinkChain (ltype);
2154     }
2155   else
2156     { // make them the same size
2157       resType = usualBinaryConversions (&left, &right);
2158     }
2159
2160   /* if they are both literals then we know */
2161   if (IS_LITERAL (letype) && IS_LITERAL (retype)
2162       && left->isLiteral && right->isLiteral)
2163     return operandFromValue (valPlus (valFromType (letype),
2164                                       valFromType (retype)));
2165
2166   ic = newiCode ('+', left, right);
2167
2168   IC_RESULT (ic) = newiTempOperand (resType, 1);
2169   IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2170
2171   /* if left or right is a float then support
2172      routine */
2173   if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2174     ic->supportRtn = 1;
2175
2176   ADDTOCHAIN (ic);
2177
2178   return IC_RESULT (ic);
2179
2180 }
2181
2182 /*-----------------------------------------------------------------*/
2183 /* aggrToPtr - changes an aggregate to pointer to an aggregate     */
2184 /*-----------------------------------------------------------------*/
2185 sym_link *
2186 aggrToPtr (sym_link * type, bool force)
2187 {
2188   sym_link *etype;
2189   sym_link *ptype;
2190
2191   if (IS_PTR (type) && !force)
2192     return type;
2193
2194   etype = getSpec (type);
2195   ptype = newLink (DECLARATOR);
2196
2197   ptype->next = type;
2198
2199   /* set the pointer depending on the storage class */
2200   DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype));
2201   return ptype;
2202 }
2203
2204 /*-----------------------------------------------------------------*/
2205 /* geniCodeArray2Ptr - array to pointer                            */
2206 /*-----------------------------------------------------------------*/
2207 operand *
2208 geniCodeArray2Ptr (operand * op)
2209 {
2210   sym_link *optype = operandType (op);
2211   sym_link *opetype = getSpec (optype);
2212
2213   /* set the pointer depending on the storage class */
2214   DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype));
2215
2216   op->isaddr = 0;
2217   return op;
2218 }
2219
2220
2221 /*-----------------------------------------------------------------*/
2222 /* geniCodeArray - array access                                    */
2223 /*-----------------------------------------------------------------*/
2224 operand *
2225 geniCodeArray (operand * left, operand * right,int lvl)
2226 {
2227   iCode *ic;
2228   sym_link *ltype = operandType (left);
2229   
2230   if (IS_PTR (ltype))
2231     {
2232       if (IS_PTR (ltype->next) && left->isaddr)
2233         {
2234           left = geniCodeRValue (left, FALSE);
2235         }
2236       return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
2237     }
2238
2239   right = geniCodeMultiply (right,
2240                             operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2241
2242   /* we can check for limits here */
2243   if (isOperandLiteral (right) &&
2244       IS_ARRAY (ltype) &&
2245       DCL_ELEM (ltype) &&
2246       (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2247     {
2248       werror (E_ARRAY_BOUND);
2249       right = operandFromLit (0);
2250     }
2251
2252   ic = newiCode ('+', left, right);
2253
2254   IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2255                                       !IS_AGGREGATE (ltype->next) &&
2256                                       !IS_PTR (ltype->next))
2257                                      ? ltype : ltype->next), 0);
2258
2259   IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2260   ADDTOCHAIN (ic);
2261   
2262   return IC_RESULT (ic);
2263 }
2264
2265 /*-----------------------------------------------------------------*/
2266 /* geniCodeStruct - generates intermediate code for structres      */
2267 /*-----------------------------------------------------------------*/
2268 operand *
2269 geniCodeStruct (operand * left, operand * right, bool islval)
2270 {
2271   iCode *ic;
2272   sym_link *type = operandType (left);
2273   sym_link *etype = getSpec (type);
2274   sym_link *retype;
2275   symbol *element = getStructElement (SPEC_STRUCT (etype),
2276                                       right->operand.symOperand);
2277
2278   wassert(IS_SYMOP(right));
2279     
2280   /* add the offset */
2281   ic = newiCode ('+', left, operandFromLit (element->offset));
2282
2283   IC_RESULT (ic) = newiTempOperand (element->type, 0);
2284
2285   /* preserve the storage & output class of the struct */
2286   /* as well as the volatile attribute */
2287   retype = getSpec (operandType (IC_RESULT (ic)));
2288   SPEC_SCLS (retype) = SPEC_SCLS (etype);
2289   SPEC_OCLS (retype) = SPEC_OCLS (etype);
2290   SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2291   SPEC_CONST (retype) |= SPEC_CONST (etype);
2292   
2293   if (IS_PTR (element->type))
2294     setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2295   
2296   IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2297
2298   ADDTOCHAIN (ic);
2299   return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2300 }
2301
2302 /*-----------------------------------------------------------------*/
2303 /* geniCodePostInc - generate int code for Post increment          */
2304 /*-----------------------------------------------------------------*/
2305 operand *
2306 geniCodePostInc (operand * op)
2307 {
2308   iCode *ic;
2309   operand *rOp;
2310   sym_link *optype = operandType (op);
2311   operand *result;
2312   operand *rv = (IS_ITEMP (op) ?
2313                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2314                  op);
2315   sym_link *rvtype = operandType (rv);
2316   int size = 0;
2317
2318   /* if this is not an address we have trouble */
2319   if (!op->isaddr)
2320     {
2321       werror (E_LVALUE_REQUIRED, "++");
2322       return op;
2323     }
2324
2325   rOp = newiTempOperand (rvtype, 0);
2326   OP_SYMBOL(rOp)->noSpilLoc = 1;
2327
2328   if (IS_ITEMP (rv))
2329     OP_SYMBOL(rv)->noSpilLoc = 1;
2330
2331   geniCodeAssign (rOp, rv, 0);
2332
2333   size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2334   if (IS_FLOAT (rvtype))
2335     ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2336   else
2337     ic = newiCode ('+', rv, operandFromLit (size));
2338
2339   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2340   ADDTOCHAIN (ic);
2341
2342   geniCodeAssign (op, result, 0);
2343
2344   return rOp;
2345
2346 }
2347
2348 /*-----------------------------------------------------------------*/
2349 /* geniCodePreInc - generate code for preIncrement                 */
2350 /*-----------------------------------------------------------------*/
2351 operand *
2352 geniCodePreInc (operand * op, bool lvalue)
2353 {
2354   iCode *ic;
2355   sym_link *optype = operandType (op);
2356   operand *rop = (IS_ITEMP (op) ?
2357                   geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2358                   op);
2359   sym_link *roptype = operandType (rop);
2360   operand *result;
2361   int size = 0;
2362
2363   if (!op->isaddr)
2364     {
2365       werror (E_LVALUE_REQUIRED, "++");
2366       return op;
2367     }
2368
2369
2370   size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2371   if (IS_FLOAT (roptype))
2372     ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2373   else
2374     ic = newiCode ('+', rop, operandFromLit (size));
2375   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2376   ADDTOCHAIN (ic);
2377
2378   (void) geniCodeAssign (op, result, 0);
2379   if (lvalue)
2380     return op;
2381   else
2382     return result;
2383 }
2384
2385 /*-----------------------------------------------------------------*/
2386 /* geniCodePostDec - generates code for Post decrement             */
2387 /*-----------------------------------------------------------------*/
2388 operand *
2389 geniCodePostDec (operand * op)
2390 {
2391   iCode *ic;
2392   operand *rOp;
2393   sym_link *optype = operandType (op);
2394   operand *result;
2395   operand *rv = (IS_ITEMP (op) ?
2396                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2397                  op);
2398   sym_link *rvtype = operandType (rv);
2399   int size = 0;
2400
2401   /* if this is not an address we have trouble */
2402   if (!op->isaddr)
2403     {
2404       werror (E_LVALUE_REQUIRED, "--");
2405       return op;
2406     }
2407
2408   rOp = newiTempOperand (rvtype, 0);
2409   OP_SYMBOL(rOp)->noSpilLoc = 1;
2410
2411   if (IS_ITEMP (rv))
2412     OP_SYMBOL(rv)->noSpilLoc = 1;
2413
2414   geniCodeAssign (rOp, rv, 0);
2415
2416   size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2417   if (IS_FLOAT (rvtype))
2418     ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2419   else
2420     ic = newiCode ('-', rv, operandFromLit (size));
2421
2422   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2423   ADDTOCHAIN (ic);
2424
2425   geniCodeAssign (op, result, 0);
2426
2427   return rOp;
2428
2429 }
2430
2431 /*-----------------------------------------------------------------*/
2432 /* geniCodePreDec - generate code for pre  decrement               */
2433 /*-----------------------------------------------------------------*/
2434 operand *
2435 geniCodePreDec (operand * op, bool lvalue)
2436 {
2437   iCode *ic;
2438   sym_link *optype = operandType (op);
2439   operand *rop = (IS_ITEMP (op) ?
2440                   geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2441                   op);
2442   sym_link *roptype = operandType (rop);
2443   operand *result;
2444   int size = 0;
2445
2446   if (!op->isaddr)
2447     {
2448       werror (E_LVALUE_REQUIRED, "--");
2449       return op;
2450     }
2451
2452
2453   size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2454   if (IS_FLOAT (roptype))
2455     ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2456   else
2457     ic = newiCode ('-', rop, operandFromLit (size));
2458   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2459   ADDTOCHAIN (ic);
2460
2461   (void) geniCodeAssign (op, result, 0);
2462   if (lvalue)
2463     return op;
2464   else
2465     return result;
2466 }
2467
2468
2469 /*-----------------------------------------------------------------*/
2470 /* geniCodeBitwise - gen int code for bitWise  operators           */
2471 /*-----------------------------------------------------------------*/
2472 operand *
2473 geniCodeBitwise (operand * left, operand * right,
2474                  int oper, sym_link * resType)
2475 {
2476   iCode *ic;
2477
2478   left = geniCodeCast (resType, left, TRUE);
2479   right = geniCodeCast (resType, right, TRUE);
2480
2481   ic = newiCode (oper, left, right);
2482   IC_RESULT (ic) = newiTempOperand (resType, 0);
2483
2484   ADDTOCHAIN (ic);
2485   return IC_RESULT (ic);
2486 }
2487
2488 /*-----------------------------------------------------------------*/
2489 /* geniCodeAddressOf - gens icode for '&' address of operator      */
2490 /*-----------------------------------------------------------------*/
2491 operand *
2492 geniCodeAddressOf (operand * op)
2493 {
2494   iCode *ic;
2495   sym_link *p;
2496   sym_link *optype = operandType (op);
2497   sym_link *opetype = getSpec (optype);
2498
2499   /* lvalue check already done in decorateType */
2500   /* this must be a lvalue */
2501 /*     if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2502 /*  werror (E_LVALUE_REQUIRED,"&"); */
2503 /*  return op; */
2504 /*     } */
2505
2506   p = newLink (DECLARATOR);
2507
2508   /* set the pointer depending on the storage class */
2509   DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
2510
2511   p->next = copyLinkChain (optype);
2512
2513   /* if already a temp */
2514   if (IS_ITEMP (op))
2515     {
2516       setOperandType (op, p);
2517       op->isaddr = 0;
2518       return op;
2519     }
2520
2521   /* other wise make this of the type coming in */
2522   ic = newiCode (ADDRESS_OF, op, NULL);
2523   IC_RESULT (ic) = newiTempOperand (p, 1);
2524   IC_RESULT (ic)->isaddr = 0;
2525   ADDTOCHAIN (ic);
2526   return IC_RESULT (ic);
2527 }
2528 /*-----------------------------------------------------------------*/
2529 /* setOClass - sets the output class depending on the pointer type */
2530 /*-----------------------------------------------------------------*/
2531 void 
2532 setOClass (sym_link * ptr, sym_link * spec)
2533 {
2534   switch (DCL_TYPE (ptr))
2535     {
2536     case POINTER:
2537       SPEC_OCLS (spec) = data;
2538       break;
2539
2540     case GPOINTER:
2541       SPEC_OCLS (spec) = generic;
2542       break;
2543
2544     case FPOINTER:
2545       SPEC_OCLS (spec) = xdata;
2546       break;
2547
2548     case CPOINTER:
2549       SPEC_OCLS (spec) = code;
2550       break;
2551
2552     case IPOINTER:
2553       SPEC_OCLS (spec) = idata;
2554       break;
2555
2556     case PPOINTER:
2557       SPEC_OCLS (spec) = xstack;
2558       break;
2559
2560     case EEPPOINTER:
2561       SPEC_OCLS (spec) = eeprom;
2562       break;
2563
2564     default:
2565       break;
2566
2567     }
2568 }
2569
2570 /*-----------------------------------------------------------------*/
2571 /* geniCodeDerefPtr - dereference pointer with '*'                 */
2572 /*-----------------------------------------------------------------*/
2573 operand *
2574 geniCodeDerefPtr (operand * op,int lvl)
2575 {
2576   sym_link *rtype, *retype;
2577   sym_link *optype = operandType (op);
2578
2579   // if this is an array then array access
2580   if (IS_ARRAY (optype)) {
2581     // don't worry, this will be optimized out later
2582     return geniCodeArray (op, operandFromLit (0), lvl);
2583   }
2584
2585   // just in case someone screws up
2586   wassert (IS_PTR (optype));
2587
2588   if (IS_TRUE_SYMOP (op))
2589     {
2590       op->isaddr = 1;
2591       op = geniCodeRValue (op, TRUE);
2592     }
2593
2594   /* now get rid of the pointer part */
2595   if (isLvaluereq(lvl) && IS_ITEMP (op))
2596     {
2597       retype = getSpec (rtype = copyLinkChain (optype));
2598     }
2599   else
2600     {
2601       retype = getSpec (rtype = copyLinkChain (optype->next));
2602       /* outputclass needs 2b updated */
2603       setOClass (optype, retype);
2604     }
2605   
2606   op->isGptr = IS_GENPTR (optype);
2607
2608   op->isaddr = (IS_PTR (rtype) ||
2609                 IS_STRUCT (rtype) ||
2610                 IS_INT (rtype) ||
2611                 IS_CHAR (rtype) ||
2612                 IS_FLOAT (rtype));
2613
2614   if (!isLvaluereq(lvl))
2615     op = geniCodeRValue (op, TRUE);
2616
2617   setOperandType (op, rtype);
2618
2619   return op;
2620 }
2621
2622 /*-----------------------------------------------------------------*/
2623 /* geniCodeUnaryMinus - does a unary minus of the operand          */
2624 /*-----------------------------------------------------------------*/
2625 operand *
2626 geniCodeUnaryMinus (operand * op)
2627 {
2628   iCode *ic;
2629   sym_link *optype = operandType (op);
2630
2631   if (IS_LITERAL (optype))
2632     return operandFromLit (-floatFromVal (op->operand.valOperand));
2633
2634   ic = newiCode (UNARYMINUS, op, NULL);
2635   IC_RESULT (ic) = newiTempOperand (optype, 0);
2636   ADDTOCHAIN (ic);
2637   return IC_RESULT (ic);
2638 }
2639
2640 /*-----------------------------------------------------------------*/
2641 /* geniCodeLeftShift - gen i code for left shift                   */
2642 /*-----------------------------------------------------------------*/
2643 operand *
2644 geniCodeLeftShift (operand * left, operand * right)
2645 {
2646   iCode *ic;
2647
2648   ic = newiCode (LEFT_OP, left, right);
2649   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2650   ADDTOCHAIN (ic);
2651   return IC_RESULT (ic);
2652 }
2653
2654 /*-----------------------------------------------------------------*/
2655 /* geniCodeRightShift - gen i code for right shift                 */
2656 /*-----------------------------------------------------------------*/
2657 operand *
2658 geniCodeRightShift (operand * left, operand * right)
2659 {
2660   iCode *ic;
2661
2662   ic = newiCode (RIGHT_OP, left, right);
2663   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2664   ADDTOCHAIN (ic);
2665   return IC_RESULT (ic);
2666 }
2667
2668 /*-----------------------------------------------------------------*/
2669 /* geniCodeLogic- logic code                                       */
2670 /*-----------------------------------------------------------------*/
2671 operand *
2672 geniCodeLogic (operand * left, operand * right, int op)
2673 {
2674   iCode *ic;
2675   sym_link *ctype;
2676   sym_link *rtype = operandType (right);
2677   sym_link *ltype = operandType (left);
2678
2679   /* left is integral type and right is literal then
2680      check if the literal value is within bounds */
2681   if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2682     {
2683       checkConstantRange(ltype,
2684                          OP_VALUE(right), "compare operation", 1);
2685     }
2686
2687   /* if one operand is a pointer and the other is a literal generic void pointer,
2688      change the type of the literal generic void pointer to match the other pointer */
2689   if (IS_GENPTR (ltype) && IS_VOID (ltype->next) && IS_ITEMP (left)
2690       && IS_PTR (rtype) && !IS_GENPTR(rtype))
2691     {
2692       /* find left's definition */
2693       ic = (iCode *) setFirstItem (iCodeChain);
2694       while (ic)
2695         {
2696           if (((ic->op == CAST) || (ic->op == '='))
2697               && isOperandEqual(left, IC_RESULT (ic)))
2698             break;
2699           else
2700             ic = setNextItem (iCodeChain);
2701         }
2702       /* if casting literal to generic pointer, then cast to rtype instead */
2703       if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic))) 
2704         {
2705           left = operandFromValue (valCastLiteral (rtype, operandLitValue (IC_RIGHT (ic))));
2706           ltype = operandType(left);
2707         }
2708     }
2709   if (IS_GENPTR (rtype) && IS_VOID (rtype->next) && IS_ITEMP (right)
2710       && IS_PTR (ltype) && !IS_GENPTR(ltype))
2711     {
2712       /* find right's definition */
2713       ic = (iCode *) setFirstItem (iCodeChain);
2714       while (ic)
2715         {
2716           if (((ic->op == CAST) || (ic->op == '='))
2717               && isOperandEqual(right, IC_RESULT (ic)))
2718             break;
2719           else
2720             ic = setNextItem (iCodeChain);
2721         }
2722       /* if casting literal to generic pointer, then cast to rtype instead */
2723       if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic))) 
2724         {
2725           right = operandFromValue (valCastLiteral (ltype, operandLitValue (IC_RIGHT (ic))));
2726           rtype = operandType(right);
2727         }
2728     }
2729
2730   ctype = usualBinaryConversions (&left, &right);
2731
2732   ic = newiCode (op, left, right);
2733   IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2734
2735   /* if comparing float
2736      and not a '==' || '!=' || '&&' || '||' (these
2737      will be inlined */
2738   if (IS_FLOAT(ctype) &&
2739       op != EQ_OP &&
2740       op != NE_OP &&
2741       op != AND_OP &&
2742       op != OR_OP)
2743     ic->supportRtn = 1;
2744
2745   ADDTOCHAIN (ic);
2746   return IC_RESULT (ic);
2747 }
2748
2749 /*-----------------------------------------------------------------*/
2750 /* geniCodeUnary - for a a generic unary operation                 */
2751 /*-----------------------------------------------------------------*/
2752 operand *
2753 geniCodeUnary (operand * op, int oper)
2754 {
2755   iCode *ic = newiCode (oper, op, NULL);
2756
2757   IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2758   ADDTOCHAIN (ic);
2759   return IC_RESULT (ic);
2760 }
2761
2762 /*-----------------------------------------------------------------*/
2763 /* geniCodeConditional - geniCode for '?' ':' operation            */
2764 /*-----------------------------------------------------------------*/
2765 operand *
2766 geniCodeConditional (ast * tree,int lvl)
2767 {
2768   iCode *ic;
2769   symbol *falseLabel = newiTempLabel (NULL);
2770   symbol *exitLabel = newiTempLabel (NULL);
2771   operand *cond = ast2iCode (tree->left,lvl+1);
2772   operand *true, *false, *result;
2773
2774   ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2775                           NULL, falseLabel);
2776   ADDTOCHAIN (ic);
2777
2778   true = ast2iCode (tree->right->left,lvl+1);
2779
2780   /* move the value to a new Operand */
2781   result = newiTempOperand (tree->right->ftype, 0);
2782   geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2783
2784   /* generate an unconditional goto */
2785   geniCodeGoto (exitLabel);
2786
2787   /* now for the right side */
2788   geniCodeLabel (falseLabel);
2789
2790   false = ast2iCode (tree->right->right,lvl+1);
2791   geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2792
2793   /* create the exit label */
2794   geniCodeLabel (exitLabel);
2795
2796   return result;
2797 }
2798
2799 /*-----------------------------------------------------------------*/
2800 /* geniCodeAssign - generate code for assignment                   */
2801 /*-----------------------------------------------------------------*/
2802 operand *
2803 geniCodeAssign (operand * left, operand * right, int nosupdate)
2804 {
2805   iCode *ic;
2806   sym_link *ltype = operandType (left);
2807   sym_link *rtype = operandType (right);
2808
2809   if (!left->isaddr && !IS_ITEMP (left))
2810     {
2811       werror (E_LVALUE_REQUIRED, "assignment");
2812       return left;
2813     }
2814
2815   /* left is integral type and right is literal then
2816      check if the literal value is within bounds */
2817   if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2818     {
2819       checkConstantRange(ltype, 
2820                          OP_VALUE(right), "= operation", 0);
2821     }
2822
2823   /* if the left & right type don't exactly match */
2824   /* if pointer set then make sure the check is
2825      done with the type & not the pointer */
2826   /* then cast rights type to left */
2827
2828   /* first check the type for pointer assignement */
2829   if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2830       compareType (ltype, rtype) <= 0)
2831     {
2832       if (compareType (ltype->next, rtype) < 0)
2833         right = geniCodeCast (ltype->next, right, TRUE);
2834     }
2835   else if (compareType (ltype, rtype) < 0)
2836     right = geniCodeCast (ltype, right, TRUE);
2837
2838   /* if left is a true symbol & ! volatile
2839      create an assignment to temporary for
2840      the right & then assign this temporary
2841      to the symbol this is SSA . isn't it simple
2842      and folks have published mountains of paper on it */
2843   if (IS_TRUE_SYMOP (left) &&
2844       !isOperandVolatile (left, FALSE) &&
2845       isOperandGlobal (left))
2846     {
2847       symbol *sym = NULL;
2848
2849       if (IS_TRUE_SYMOP (right))
2850         sym = OP_SYMBOL (right);
2851       ic = newiCode ('=', NULL, right);
2852       IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2853       SPIL_LOC (right) = sym;
2854       ADDTOCHAIN (ic);
2855     }
2856
2857   ic = newiCode ('=', NULL, right);
2858   IC_RESULT (ic) = left;
2859   ADDTOCHAIN (ic);
2860
2861   /* if left isgptr flag is set then support
2862      routine will be required */
2863   if (left->isGptr)
2864     ic->supportRtn = 1;
2865
2866   ic->nosupdate = nosupdate;
2867   return left;
2868 }
2869
2870 /*-----------------------------------------------------------------*/
2871 /* geniCodeDummyRead - generate code for dummy read                */
2872 /*-----------------------------------------------------------------*/
2873 static void
2874 geniCodeDummyRead (operand * op)
2875 {
2876   iCode *ic;
2877   sym_link *type = operandType (op);
2878
2879   if (!IS_VOLATILE(type))
2880     return;
2881     
2882   ic = newiCode (DUMMY_READ_VOLATILE, NULL, op);
2883   ADDTOCHAIN (ic);
2884
2885   ic->nosupdate = 1;
2886 }
2887
2888 /*-----------------------------------------------------------------*/
2889 /* geniCodeSEParms - generate code for side effecting fcalls       */
2890 /*-----------------------------------------------------------------*/
2891 static void 
2892 geniCodeSEParms (ast * parms,int lvl)
2893 {
2894   if (!parms)
2895     return;
2896
2897   if (parms->type == EX_OP && parms->opval.op == PARAM)
2898     {
2899       geniCodeSEParms (parms->left,lvl);
2900       geniCodeSEParms (parms->right,lvl);
2901       return;
2902     }
2903
2904   /* hack don't like this but too lazy to think of
2905      something better */
2906   if (IS_ADDRESS_OF_OP (parms))
2907     parms->left->lvalue = 1;
2908
2909   if (IS_CAST_OP (parms) &&
2910       IS_PTR (parms->ftype) &&
2911       IS_ADDRESS_OF_OP (parms->right))
2912     parms->right->left->lvalue = 1;
2913
2914   parms->opval.oprnd = 
2915     geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2916                 
2917   parms->type = EX_OPERAND;
2918   AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
2919                 SPEC_ARGREG(parms->ftype);
2920 }
2921
2922 /*-----------------------------------------------------------------*/
2923 /* geniCodeParms - generates parameters                            */
2924 /*-----------------------------------------------------------------*/
2925 value *
2926 geniCodeParms (ast * parms, value *argVals, int *stack, 
2927                sym_link * fetype, symbol * func,int lvl)
2928 {
2929   iCode *ic;
2930   operand *pval;
2931
2932   if (!parms)
2933     return argVals;
2934
2935   if (argVals==NULL) {
2936     // first argument
2937     argVals=FUNC_ARGS(func->type);
2938   }
2939
2940   /* if this is a param node then do the left & right */
2941   if (parms->type == EX_OP && parms->opval.op == PARAM)
2942     {
2943       argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
2944       argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
2945       return argVals;
2946     }
2947
2948   /* get the parameter value */
2949   if (parms->type == EX_OPERAND)
2950     pval = parms->opval.oprnd;
2951   else
2952     {
2953       /* maybe this else should go away ?? */
2954       /* hack don't like this but too lazy to think of
2955          something better */
2956       if (IS_ADDRESS_OF_OP (parms))
2957         parms->left->lvalue = 1;
2958
2959       if (IS_CAST_OP (parms) &&
2960           IS_PTR (parms->ftype) &&
2961           IS_ADDRESS_OF_OP (parms->right))
2962         parms->right->left->lvalue = 1;
2963
2964       pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2965     }
2966
2967   /* if register parm then make it a send */
2968   if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
2969       IFFUNC_ISBUILTIN(func->type))
2970     {
2971       ic = newiCode (SEND, pval, NULL);
2972       ic->argreg = SPEC_ARGREG(parms->etype);
2973       ic->builtinSEND = FUNC_ISBUILTIN(func->type);
2974       ADDTOCHAIN (ic);
2975     }
2976   else
2977     {
2978       /* now decide whether to push or assign */
2979       if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
2980         {
2981
2982           /* assign */
2983           operand *top = operandFromSymbol (argVals->sym);
2984           /* clear useDef and other bitVectors */
2985           OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
2986           geniCodeAssign (top, pval, 1);
2987         }
2988       else
2989         {
2990           sym_link *p = operandType (pval);
2991           /* push */
2992           ic = newiCode (IPUSH, pval, NULL);
2993           ic->parmPush = 1;
2994           /* update the stack adjustment */
2995           *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2996           ADDTOCHAIN (ic);
2997         }
2998     }
2999
3000   argVals=argVals->next;
3001   return argVals;
3002 }
3003
3004 /*-----------------------------------------------------------------*/
3005 /* geniCodeCall - generates temp code for calling                  */
3006 /*-----------------------------------------------------------------*/
3007 operand *
3008 geniCodeCall (operand * left, ast * parms,int lvl)
3009 {
3010   iCode *ic;
3011   operand *result;
3012   sym_link *type, *etype;
3013   int stack = 0;
3014
3015   if (!IS_FUNC(OP_SYMBOL(left)->type) && 
3016       !IS_CODEPTR(OP_SYMBOL(left)->type)) {
3017     werror (E_FUNCTION_EXPECTED);
3018     return NULL;
3019   }
3020
3021   /* take care of parameters with side-effecting
3022      function calls in them, this is required to take care
3023      of overlaying function parameters */
3024   geniCodeSEParms (parms,lvl);
3025
3026   /* first the parameters */
3027   geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
3028
3029   /* now call : if symbol then pcall */
3030   if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
3031     ic = newiCode (PCALL, left, NULL);
3032   } else {
3033     ic = newiCode (CALL, left, NULL);
3034   }
3035
3036   type = copyLinkChain (operandType (left)->next);
3037   etype = getSpec (type);
3038   SPEC_EXTR (etype) = 0;
3039   IC_RESULT (ic) = result = newiTempOperand (type, 1);
3040
3041   ADDTOCHAIN (ic);
3042
3043   /* stack adjustment after call */
3044   ic->parmBytes = stack;
3045
3046   return result;
3047 }
3048
3049 /*-----------------------------------------------------------------*/
3050 /* geniCodeReceive - generate intermediate code for "receive"      */
3051 /*-----------------------------------------------------------------*/
3052 static void 
3053 geniCodeReceive (value * args)
3054 {
3055   /* for all arguments that are passed in registers */
3056   while (args)
3057     {
3058       int first = 1;
3059       if (IS_REGPARM (args->etype))
3060         {
3061           operand *opr = operandFromValue (args);
3062           operand *opl;
3063           symbol *sym = OP_SYMBOL (opr);
3064           iCode *ic;
3065
3066           /* we will use it after all optimizations
3067              and before liveRange calculation */
3068           if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
3069             {
3070
3071               if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
3072                   options.stackAuto == 0 &&
3073                   (!(options.model == MODEL_FLAT24)) )
3074                 {
3075                 }
3076               else
3077                 {
3078                   opl = newiTempOperand (args->type, 0);
3079                   sym->reqv = opl;
3080                   sym->reqv->key = sym->key;
3081                   OP_SYMBOL (sym->reqv)->key = sym->key;
3082                   OP_SYMBOL (sym->reqv)->isreqv = 1;
3083                   OP_SYMBOL (sym->reqv)->islocal = 0;
3084                   SPIL_LOC (sym->reqv) = sym;
3085                 }
3086             }
3087
3088           ic = newiCode (RECEIVE, NULL, NULL);    
3089           ic->argreg = SPEC_ARGREG(args->etype);
3090           if (first) {
3091               currFunc->recvSize = getSize (sym->type);
3092               first = 0;
3093           }
3094           IC_RESULT (ic) = opr;
3095           ADDTOCHAIN (ic);
3096         }
3097
3098       args = args->next;
3099     }
3100 }
3101
3102 /*-----------------------------------------------------------------*/
3103 /* geniCodeFunctionBody - create the function body                 */
3104 /*-----------------------------------------------------------------*/
3105 void 
3106 geniCodeFunctionBody (ast * tree,int lvl)
3107 {
3108   iCode *ic;
3109   operand *func;
3110   sym_link *fetype;
3111   int savelineno;
3112
3113   /* reset the auto generation */
3114   /* numbers */
3115   iTempNum = 0;
3116   iTempLblNum = 0;
3117   operandKey = 0;
3118   iCodeKey = 0;
3119   func = ast2iCode (tree->left,lvl+1);
3120   fetype = getSpec (operandType (func));
3121
3122   savelineno = lineno;
3123   lineno = OP_SYMBOL (func)->lineDef;
3124   /* create an entry label */
3125   geniCodeLabel (entryLabel);
3126   lineno = savelineno;
3127
3128   /* create a proc icode */
3129   ic = newiCode (FUNCTION, func, NULL);
3130   lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3131
3132   ADDTOCHAIN (ic);
3133
3134   /* for all parameters that are passed
3135      on registers add a "receive" */
3136   geniCodeReceive (tree->values.args);
3137
3138   /* generate code for the body */
3139   ast2iCode (tree->right,lvl+1);
3140
3141   /* create a label for return */
3142   geniCodeLabel (returnLabel);
3143
3144   /* now generate the end proc */
3145   ic = newiCode (ENDFUNCTION, func, NULL);
3146   ADDTOCHAIN (ic);
3147   return;
3148 }
3149
3150 /*-----------------------------------------------------------------*/
3151 /* geniCodeReturn - gen icode for 'return' statement               */
3152 /*-----------------------------------------------------------------*/
3153 void 
3154 geniCodeReturn (operand * op)
3155 {
3156   iCode *ic;
3157
3158   /* if the operand is present force an rvalue */
3159   if (op)
3160     op = geniCodeRValue (op, FALSE);
3161
3162   ic = newiCode (RETURN, op, NULL);
3163   ADDTOCHAIN (ic);
3164 }
3165
3166 /*-----------------------------------------------------------------*/
3167 /* geniCodeIfx - generates code for extended if statement          */
3168 /*-----------------------------------------------------------------*/
3169 void 
3170 geniCodeIfx (ast * tree,int lvl)
3171 {
3172   iCode *ic;
3173   operand *condition = ast2iCode (tree->left,lvl+1);
3174   sym_link *cetype;
3175
3176   /* if condition is null then exit */
3177   if (!condition)
3178     goto exit;
3179   else
3180     condition = geniCodeRValue (condition, FALSE);
3181
3182   cetype = getSpec (operandType (condition));
3183   /* if the condition is a literal */
3184   if (IS_LITERAL (cetype))
3185     {
3186       if (floatFromVal (condition->operand.valOperand))
3187         {
3188           if (tree->trueLabel)
3189             geniCodeGoto (tree->trueLabel);
3190           else
3191             assert (0);
3192         }
3193       else
3194         {
3195           if (tree->falseLabel)
3196             geniCodeGoto (tree->falseLabel);
3197           else
3198             assert (0);
3199         }
3200       goto exit;
3201     }
3202
3203   if (tree->trueLabel)
3204     {
3205       ic = newiCodeCondition (condition,
3206                               tree->trueLabel,
3207                               NULL);
3208       ADDTOCHAIN (ic);
3209
3210       if (tree->falseLabel)
3211         geniCodeGoto (tree->falseLabel);
3212     }
3213   else
3214     {
3215       ic = newiCodeCondition (condition,
3216                               NULL,
3217                               tree->falseLabel);
3218       ADDTOCHAIN (ic);
3219     }
3220
3221 exit:
3222   ast2iCode (tree->right,lvl+1);
3223 }
3224
3225 /*-----------------------------------------------------------------*/
3226 /* geniCodeJumpTable - tries to create a jump table for switch     */
3227 /*-----------------------------------------------------------------*/
3228 int 
3229 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3230 {
3231   int min = 0, max = 0, t, cnt = 0;
3232   value *vch;
3233   iCode *ic;
3234   operand *boundary;
3235   symbol *falseLabel;
3236   set *labels = NULL;
3237   int needRangeCheck = !optimize.noJTabBoundary
3238                        || tree->values.switchVals.swDefault;
3239
3240   if (!tree || !caseVals)
3241     return 0;
3242
3243   /* the criteria for creating a jump table is */
3244   /* all integer numbers between the maximum & minimum must */
3245   /* be present , the maximum value should not exceed 255 */
3246   min = max = (int) floatFromVal (vch = caseVals);
3247   SNPRINTF (buffer, sizeof(buffer), 
3248             "_case_%d_%d",
3249            tree->values.switchVals.swNum,
3250            min);
3251   addSet (&labels, newiTempLabel (buffer));
3252
3253   /* if there is only one case value then no need */
3254   if (!(vch = vch->next))
3255     return 0;
3256
3257   while (vch)
3258     {
3259       if (((t = (int) floatFromVal (vch)) - max) != 1)
3260         return 0;
3261       SNPRINTF (buffer, sizeof(buffer), 
3262                 "_case_%d_%d",
3263                tree->values.switchVals.swNum,
3264                t);
3265       addSet (&labels, newiTempLabel (buffer));
3266       max = t;
3267       cnt++;
3268       vch = vch->next;
3269     }
3270
3271   /* if the number of case statements <= 2 then */
3272   /* it is not economical to create the jump table */
3273   /* since two compares are needed for boundary conditions */
3274   if ((needRangeCheck && cnt <= 2) || max > (255 / 3))
3275     return 0;
3276
3277   if (tree->values.switchVals.swDefault)
3278     {
3279         SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3280     }
3281   else
3282     {
3283         SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3284     }
3285     
3286
3287   falseLabel = newiTempLabel (buffer);
3288
3289   /* so we can create a jumptable */
3290   /* first we rule out the boundary conditions */
3291   /* if only optimization says so */
3292   if (needRangeCheck)
3293     {
3294       sym_link *cetype = getSpec (operandType (cond));
3295       /* no need to check the lower bound if
3296          the condition is unsigned & minimum value is zero */
3297       if (!(min == 0 && SPEC_USIGN (cetype)))
3298         {
3299           boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3300           ic = newiCodeCondition (boundary, falseLabel, NULL);
3301           ADDTOCHAIN (ic);
3302         }
3303
3304       /* now for upper bounds */
3305       boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3306       ic = newiCodeCondition (boundary, falseLabel, NULL);
3307       ADDTOCHAIN (ic);
3308     }
3309
3310   /* if the min is not zero then we no make it zero */
3311   if (min)
3312     {
3313       cond = geniCodeSubtract (cond, operandFromLit (min));
3314       if (!IS_LITERAL(getSpec(operandType(cond))))
3315         setOperandType (cond, UCHARTYPE);
3316     }
3317
3318   /* now create the jumptable */
3319   ic = newiCode (JUMPTABLE, NULL, NULL);
3320   IC_JTCOND (ic) = cond;
3321   IC_JTLABELS (ic) = labels;
3322   ADDTOCHAIN (ic);
3323   return 1;
3324 }
3325
3326 /*-----------------------------------------------------------------*/
3327 /* geniCodeSwitch - changes a switch to a if statement             */
3328 /*-----------------------------------------------------------------*/
3329 void
3330 geniCodeSwitch (ast * tree,int lvl)
3331 {
3332   iCode *ic;
3333   operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3334   value *caseVals = tree->values.switchVals.swVals;
3335   symbol *trueLabel, *falseLabel;
3336       
3337   /* If the condition is a literal, then just jump to the */
3338   /* appropriate case label. */
3339   if (IS_LITERAL(getSpec(operandType(cond))))
3340     {
3341       int switchVal, caseVal;
3342       
3343       switchVal = (int) floatFromVal (cond->operand.valOperand);
3344       while (caseVals)
3345         {
3346           caseVal = (int) floatFromVal (caseVals);
3347           if (caseVal == switchVal)
3348             {
3349               SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3350                         tree->values.switchVals.swNum, caseVal);
3351               trueLabel = newiTempLabel (buffer);
3352               geniCodeGoto (trueLabel);
3353               goto jumpTable;
3354             }
3355           caseVals = caseVals->next;
3356         }
3357       goto defaultOrBreak;
3358     }
3359
3360   /* if we can make this a jump table */
3361   if (geniCodeJumpTable (cond, caseVals, tree))
3362     goto jumpTable;             /* no need for the comparison */
3363
3364   /* for the cases defined do */
3365   while (caseVals)
3366     {
3367
3368       operand *compare = geniCodeLogic (cond,
3369                                         operandFromValue (caseVals),
3370                                         EQ_OP);
3371
3372       SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3373                tree->values.switchVals.swNum,
3374                (int) floatFromVal (caseVals));
3375       trueLabel = newiTempLabel (buffer);
3376
3377       ic = newiCodeCondition (compare, trueLabel, NULL);
3378       ADDTOCHAIN (ic);
3379       caseVals = caseVals->next;
3380     }
3381
3382
3383 defaultOrBreak:
3384   /* if default is present then goto break else break */
3385   if (tree->values.switchVals.swDefault)
3386     {
3387         SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3388     }
3389   else
3390     {
3391         SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3392     }
3393
3394   falseLabel = newiTempLabel (buffer);
3395   geniCodeGoto (falseLabel);
3396
3397 jumpTable:
3398   ast2iCode (tree->right,lvl+1);
3399 }
3400
3401 /*-----------------------------------------------------------------*/
3402 /* geniCodeInline - intermediate code for inline assembler         */
3403 /*-----------------------------------------------------------------*/
3404 static void 
3405 geniCodeInline (ast * tree)
3406 {
3407   iCode *ic;
3408
3409   ic = newiCode (INLINEASM, NULL, NULL);
3410   IC_INLINE (ic) = tree->values.inlineasm;
3411   ADDTOCHAIN (ic);
3412 }
3413
3414 /*-----------------------------------------------------------------*/
3415 /* geniCodeArrayInit - intermediate code for array initializer     */
3416 /*-----------------------------------------------------------------*/
3417 static void 
3418 geniCodeArrayInit (ast * tree, operand *array)
3419 {
3420   iCode *ic;
3421
3422   if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3423     ic = newiCode (ARRAYINIT, array, NULL);
3424     IC_ARRAYILIST (ic) = tree->values.constlist;
3425   } else {
3426     operand *left=newOperand(), *right=newOperand();
3427     left->type=right->type=SYMBOL;
3428     OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3429     OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3430     ic = newiCode (ARRAYINIT, left, right);
3431   }
3432   ADDTOCHAIN (ic);
3433 }
3434
3435 /*-----------------------------------------------------------------*/
3436 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some      */
3437 /* particular case. Ie : assigning or dereferencing array or ptr   */
3438 /*-----------------------------------------------------------------*/
3439 set * lvaluereqSet = NULL;
3440 typedef struct lvalItem
3441   {
3442     int req;
3443     int lvl;
3444   }
3445 lvalItem;
3446
3447 /*-----------------------------------------------------------------*/
3448 /* addLvaluereq - add a flag for lvalreq for current ast level     */
3449 /*-----------------------------------------------------------------*/
3450 void addLvaluereq(int lvl)
3451 {
3452   lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3453   lpItem->req=1;
3454   lpItem->lvl=lvl;
3455   addSetHead(&lvaluereqSet,lpItem);
3456
3457 }
3458 /*-----------------------------------------------------------------*/
3459 /* delLvaluereq - del a flag for lvalreq for current ast level     */
3460 /*-----------------------------------------------------------------*/
3461 void delLvaluereq()
3462 {
3463   lvalItem * lpItem;
3464   lpItem = getSet(&lvaluereqSet);
3465   if(lpItem) Safe_free(lpItem);
3466 }
3467 /*-----------------------------------------------------------------*/
3468 /* clearLvaluereq - clear lvalreq flag                             */
3469 /*-----------------------------------------------------------------*/
3470 void clearLvaluereq()
3471 {
3472   lvalItem * lpItem;
3473   lpItem = peekSet(lvaluereqSet);
3474   if(lpItem) lpItem->req = 0;
3475 }
3476 /*-----------------------------------------------------------------*/
3477 /* getLvaluereq - get the last lvalreq level                       */
3478 /*-----------------------------------------------------------------*/
3479 int getLvaluereqLvl()
3480 {
3481   lvalItem * lpItem;
3482   lpItem = peekSet(lvaluereqSet);
3483   if(lpItem) return lpItem->lvl;
3484   return 0;
3485 }
3486 /*-----------------------------------------------------------------*/
3487 /* isLvaluereq - is lvalreq valid for this level ?                 */
3488 /*-----------------------------------------------------------------*/
3489 int isLvaluereq(int lvl)
3490 {
3491   lvalItem * lpItem;
3492   lpItem = peekSet(lvaluereqSet);
3493   if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3494   return 0;
3495 }
3496
3497 /*-----------------------------------------------------------------*/
3498 /* ast2iCode - creates an icodeList from an ast                    */
3499 /*-----------------------------------------------------------------*/
3500 operand *
3501 ast2iCode (ast * tree,int lvl)
3502 {
3503   operand *left = NULL;
3504   operand *right = NULL;
3505   if (!tree)
3506     return NULL;
3507
3508   /* set the global variables for filename & line number */
3509   if (tree->filename)
3510     filename = tree->filename;
3511   if (tree->lineno)
3512     lineno = tree->lineno;
3513   if (tree->block)
3514     block = tree->block;
3515   if (tree->level)
3516     scopeLevel = tree->level;
3517
3518   if (tree->type == EX_VALUE)
3519     return operandFromValue (tree->opval.val);
3520
3521   if (tree->type == EX_LINK)
3522     return operandFromLink (tree->opval.lnk);
3523
3524   /* if we find a nullop */
3525   if (tree->type == EX_OP &&
3526      (tree->opval.op == NULLOP ||
3527      tree->opval.op == BLOCK))
3528     {
3529       if (tree->left && tree->left->type == EX_VALUE)
3530         geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
3531       else
3532         ast2iCode (tree->left,lvl+1);
3533       if (tree->right && tree->right->type == EX_VALUE)
3534         geniCodeDummyRead (ast2iCode (tree->right,lvl+1));
3535       else
3536         ast2iCode (tree->right,lvl+1);
3537       return NULL;
3538     }
3539
3540   /* special cases for not evaluating */
3541   if (tree->opval.op != ':' &&
3542       tree->opval.op != '?' &&
3543       tree->opval.op != CALL &&
3544       tree->opval.op != IFX &&
3545       tree->opval.op != LABEL &&
3546       tree->opval.op != GOTO &&
3547       tree->opval.op != SWITCH &&
3548       tree->opval.op != FUNCTION &&
3549       tree->opval.op != INLINEASM)
3550     {
3551
3552         if (IS_ASSIGN_OP (tree->opval.op) ||
3553            IS_DEREF_OP (tree) ||
3554            (tree->opval.op == '&' && !tree->right) ||
3555            tree->opval.op == PTR_OP)
3556           {
3557             addLvaluereq(lvl);
3558             if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3559                (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3560               clearLvaluereq();
3561
3562             left = operandFromAst (tree->left,lvl);
3563             delLvaluereq();
3564             if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3565               left = geniCodeRValue (left, TRUE);
3566           }
3567         else
3568           {
3569             left = operandFromAst (tree->left,lvl);
3570           }
3571         if (tree->opval.op == INC_OP ||
3572             tree->opval.op == DEC_OP)
3573           {
3574             addLvaluereq(lvl);
3575             right = operandFromAst (tree->right,lvl);
3576             delLvaluereq();
3577           }
3578         else
3579           {
3580             right = operandFromAst (tree->right,lvl);
3581           }
3582       }
3583
3584   /* now depending on the type of operand */
3585   /* this will be a biggy                 */
3586   switch (tree->opval.op)
3587     {
3588
3589     case '[':                   /* array operation */
3590       {
3591         //sym_link *ltype = operandType (left);
3592         //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3593         left = geniCodeRValue (left, FALSE);
3594         right = geniCodeRValue (right, TRUE);
3595       }
3596
3597       return geniCodeArray (left, right,lvl);
3598
3599     case '.':                   /* structure dereference */
3600       if (IS_PTR (operandType (left)))
3601         left = geniCodeRValue (left, TRUE);
3602       else
3603         left = geniCodeRValue (left, FALSE);
3604
3605       return geniCodeStruct (left, right, tree->lvalue);
3606
3607     case PTR_OP:                /* structure pointer dereference */
3608       {
3609         sym_link *pType;
3610         pType = operandType (left);
3611         left = geniCodeRValue (left, TRUE);
3612
3613         setOClass (pType, getSpec (operandType (left)));
3614       }
3615
3616       return geniCodeStruct (left, right, tree->lvalue);
3617
3618     case INC_OP:                /* increment operator */
3619       if (left)
3620         return geniCodePostInc (left);
3621       else
3622         return geniCodePreInc (right, tree->lvalue);
3623
3624     case DEC_OP:                /* decrement operator */
3625       if (left)
3626         return geniCodePostDec (left);
3627       else
3628         return geniCodePreDec (right, tree->lvalue);
3629
3630     case '&':                   /* bitwise and or address of operator */
3631       if (right)
3632         {                       /* this is a bitwise operator   */
3633           left = geniCodeRValue (left, FALSE);
3634           right = geniCodeRValue (right, FALSE);
3635           return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3636         }
3637       else
3638         return geniCodeAddressOf (left);
3639
3640     case '|':                   /* bitwise or & xor */
3641     case '^':
3642       return geniCodeBitwise (geniCodeRValue (left, FALSE),
3643                               geniCodeRValue (right, FALSE),
3644                               tree->opval.op,
3645                               tree->ftype);
3646
3647     case '/':
3648       return geniCodeDivision (geniCodeRValue (left, FALSE),
3649                                geniCodeRValue (right, FALSE));
3650
3651     case '%':
3652       return geniCodeModulus (geniCodeRValue (left, FALSE),
3653                               geniCodeRValue (right, FALSE));
3654     case '*':
3655       if (right)
3656         return geniCodeMultiply (geniCodeRValue (left, FALSE),
3657                                  geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3658       else
3659         return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3660
3661     case '-':
3662       if (right)
3663         return geniCodeSubtract (geniCodeRValue (left, FALSE),
3664                                  geniCodeRValue (right, FALSE));
3665       else
3666         return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3667
3668     case '+':
3669       if (right)
3670         return geniCodeAdd (geniCodeRValue (left, FALSE),
3671                             geniCodeRValue (right, FALSE),lvl);
3672       else
3673         return geniCodeRValue (left, FALSE);    /* unary '+' has no meaning */
3674
3675     case LEFT_OP:
3676       return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3677                                 geniCodeRValue (right, FALSE));
3678
3679     case RIGHT_OP:
3680       return geniCodeRightShift (geniCodeRValue (left, FALSE),
3681                                  geniCodeRValue (right, FALSE));
3682     case CAST: 
3683 #if 0 // this indeed needs a second thought
3684       {
3685         operand *op;
3686         
3687         // let's keep this simple: get the rvalue we need
3688         op=geniCodeRValue (right, FALSE);
3689         // now cast it to whatever we want
3690         op=geniCodeCast (operandType(left), op, FALSE);
3691         // if this is going to be used as an lvalue, make it so
3692         if (tree->lvalue) {
3693           op->isaddr=1;
3694         }
3695         return op;
3696       }
3697 #else // bug #604575, is it a bug ????
3698       return geniCodeCast (operandType (left),
3699                            geniCodeRValue (right, FALSE), FALSE);
3700 #endif
3701
3702     case '~':
3703     case RRC:
3704     case RLC:
3705       return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3706
3707     case '!':
3708     case GETHBIT:
3709       {
3710         operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3711         setOperandType (op, UCHARTYPE);
3712         return op;
3713       }
3714     case '>':
3715     case '<':
3716     case LE_OP:
3717     case GE_OP:
3718     case EQ_OP:
3719     case NE_OP:
3720     case AND_OP:
3721     case OR_OP:
3722       /* different compilers (even different gccs) evaluate
3723          the two calls in a different order. to get the same
3724          result on all machines we've to specify a clear sequence.
3725       return geniCodeLogic (geniCodeRValue (left, FALSE),
3726                             geniCodeRValue (right, FALSE),
3727                             tree->opval.op);
3728       */
3729       {
3730         operand *leftOp, *rightOp;
3731
3732         rightOp = geniCodeRValue (right, FALSE);
3733         leftOp  = geniCodeRValue (left , FALSE);
3734
3735         return geniCodeLogic (leftOp, rightOp, tree->opval.op);
3736       }
3737     case '?':
3738       return geniCodeConditional (tree,lvl);
3739
3740     case SIZEOF:
3741       return operandFromLit (getSize (tree->right->ftype));
3742
3743     case '=':
3744       {
3745         sym_link *rtype = operandType (right);
3746         sym_link *ltype = operandType (left);
3747         if (IS_PTR (rtype) && IS_ITEMP (right)
3748             && right->isaddr && compareType (rtype->next, ltype) == 1)
3749           right = geniCodeRValue (right, TRUE);
3750         else
3751           right = geniCodeRValue (right, FALSE);
3752
3753         geniCodeAssign (left, right, 0);
3754         return right;
3755       }
3756     case MUL_ASSIGN:
3757       return
3758         geniCodeAssign (left,
3759                 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3760                                                   FALSE),
3761                                   geniCodeRValue (right, FALSE),FALSE), 0);
3762
3763     case DIV_ASSIGN:
3764       return
3765         geniCodeAssign (left,
3766                 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3767                                                   FALSE),
3768                                   geniCodeRValue (right, FALSE)), 0);
3769     case MOD_ASSIGN:
3770       return
3771         geniCodeAssign (left,
3772                  geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3773                                                   FALSE),
3774                                   geniCodeRValue (right, FALSE)), 0);
3775     case ADD_ASSIGN:
3776       {
3777         sym_link *rtype = operandType (right);
3778         sym_link *ltype = operandType (left);
3779         if (IS_PTR (rtype) && IS_ITEMP (right)
3780             && right->isaddr && compareType (rtype->next, ltype) == 1)
3781           right = geniCodeRValue (right, TRUE);
3782         else
3783           right = geniCodeRValue (right, FALSE);
3784
3785
3786         return geniCodeAssign (left,
3787                      geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3788                                                   FALSE),
3789                                   right,lvl), 0);
3790       }
3791     case SUB_ASSIGN:
3792       {
3793         sym_link *rtype = operandType (right);
3794         sym_link *ltype = operandType (left);
3795         if (IS_PTR (rtype) && IS_ITEMP (right)
3796             && right->isaddr && compareType (rtype->next, ltype) == 1)
3797           {
3798             right = geniCodeRValue (right, TRUE);
3799           }
3800         else
3801           {
3802             right = geniCodeRValue (right, FALSE);
3803           }
3804         return
3805           geniCodeAssign (left,
3806                 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3807                                                   FALSE),
3808                                   right), 0);
3809       }
3810     case LEFT_ASSIGN:
3811       return
3812         geniCodeAssign (left,
3813                 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3814                                                    ,FALSE),
3815                                    geniCodeRValue (right, FALSE)), 0);
3816     case RIGHT_ASSIGN:
3817       return
3818         geniCodeAssign (left,
3819                geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3820                                                    ,FALSE),
3821                                    geniCodeRValue (right, FALSE)), 0);
3822     case AND_ASSIGN:
3823       return
3824         geniCodeAssign (left,
3825                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3826                                                   FALSE),
3827                                   geniCodeRValue (right, FALSE),
3828                                   BITWISEAND,
3829                                   operandType (left)), 0);
3830     case XOR_ASSIGN:
3831       return
3832         geniCodeAssign (left,
3833                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3834                                                   FALSE),
3835                                   geniCodeRValue (right, FALSE),
3836                                   '^',
3837                                   operandType (left)), 0);
3838     case OR_ASSIGN:
3839       return
3840         geniCodeAssign (left,
3841                   geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3842                                                    ,FALSE),
3843                                    geniCodeRValue (right, FALSE),
3844                                    '|',
3845                                    operandType (left)), 0);
3846     case ',':
3847       return geniCodeRValue (right, FALSE);
3848
3849     case CALL:
3850       return geniCodeCall (ast2iCode (tree->left,lvl+1),
3851                            tree->right,lvl);
3852     case LABEL:
3853       geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3854       return ast2iCode (tree->right,lvl+1);
3855
3856     case GOTO:
3857       geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3858       return ast2iCode (tree->right,lvl+1);
3859
3860     case FUNCTION:
3861       geniCodeFunctionBody (tree,lvl);
3862       return NULL;
3863
3864     case RETURN:
3865       geniCodeReturn (right);
3866       return NULL;
3867
3868     case IFX:
3869       geniCodeIfx (tree,lvl);
3870       return NULL;
3871
3872     case SWITCH:
3873       geniCodeSwitch (tree,lvl);
3874       return NULL;
3875
3876     case INLINEASM:
3877       geniCodeInline (tree);
3878       return NULL;
3879         
3880     case ARRAYINIT:
3881         geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3882         return NULL;
3883     }
3884
3885   return NULL;
3886 }
3887
3888 /*-----------------------------------------------------------------*/
3889 /* reverseICChain - gets from the list and creates a linkedlist    */
3890 /*-----------------------------------------------------------------*/
3891 iCode *
3892 reverseiCChain ()
3893 {
3894   iCode *loop = NULL;
3895   iCode *prev = NULL;
3896
3897   while ((loop = getSet (&iCodeChain)))
3898     {
3899       loop->next = prev;
3900       if (prev)
3901         prev->prev = loop;
3902       prev = loop;
3903     }
3904
3905   return prev;
3906 }
3907
3908
3909 /*-----------------------------------------------------------------*/
3910 /* iCodeFromAst - given an ast will convert it to iCode            */
3911 /*-----------------------------------------------------------------*/
3912 iCode *
3913 iCodeFromAst (ast * tree)
3914 {
3915   returnLabel = newiTempLabel ("_return");
3916   entryLabel = newiTempLabel ("_entry");
3917   ast2iCode (tree,0);
3918   return reverseiCChain ();
3919 }
3920
3921 static const char *opTypeToStr(OPTYPE op)
3922 {
3923     switch(op)
3924     {
3925       case SYMBOL: return "symbol";
3926       case VALUE: return "value";
3927       case TYPE: return "type";
3928     }
3929     return "undefined type";    
3930 }
3931
3932
3933 operand *validateOpType(operand         *op, 
3934                         const char      *macro,
3935                         const char      *args,
3936                         OPTYPE          type,
3937                         const char      *file, 
3938                         unsigned        line)
3939 {    
3940     if (op && op->type == type)
3941     {
3942         return op;
3943     }
3944     fprintf(stderr, 
3945             "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
3946             " expected %s, got %s\n",
3947             macro, args, file, line, 
3948             opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
3949     exit(-1);
3950     return op; // never reached, makes compiler happy.
3951 }