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