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