* support/regression/tests/bug1198642.c: new test
[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 (compareType (left->operand.valOperand->type,
1432                            right->operand.valOperand->type) &&
1433               (floatFromVal (left->operand.valOperand) ==
1434                floatFromVal (right->operand.valOperand)))
1435     case TYPE:
1436       if (compareType (left->operand.typeOperand,
1437                      right->operand.typeOperand) == 1)
1438         return 1;
1439     }
1440
1441   return 0;
1442 }
1443
1444 /*-------------------------------------------------------------------*/
1445 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1446 /*-------------------------------------------------------------------*/
1447 int 
1448 isiCodeEqual (iCode * left, iCode * right)
1449 {
1450   /* if the same pointer */
1451   if (left == right)
1452     return 1;
1453
1454   /* if either of them null */
1455   if (!left || !right)
1456     return 0;
1457
1458   /* if operand are the same */
1459   if (left->op == right->op)
1460     {
1461
1462       /* compare all the elements depending on type */
1463       if (left->op != IFX)
1464         {
1465           if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1466             return 0;
1467           if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1468             return 0;
1469
1470         }
1471       else
1472         {
1473           if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1474             return 0;
1475           if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1476             return 0;
1477           if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1478             return 0;
1479         }
1480       
1481       return 1;
1482     }
1483   return 0;
1484 }
1485
1486 /*-----------------------------------------------------------------*/
1487 /* newiTempFromOp - create a temp Operand with same attributes     */
1488 /*-----------------------------------------------------------------*/
1489 operand *
1490 newiTempFromOp (operand * op)
1491 {
1492   operand *nop;
1493
1494   if (!op)
1495     return NULL;
1496
1497   if (!IS_ITEMP (op))
1498     return op;
1499
1500   nop = newiTempOperand (operandType (op), TRUE);
1501   nop->isaddr = op->isaddr;
1502   nop->isvolatile = op->isvolatile;
1503   nop->isGlobal = op->isGlobal;
1504   nop->isLiteral = op->isLiteral;
1505   nop->usesDefs = op->usesDefs;
1506   nop->isParm = op->isParm;
1507   return nop;
1508 }
1509
1510 /*-----------------------------------------------------------------*/
1511 /* operand from operand - creates an operand holder for the type   */
1512 /*-----------------------------------------------------------------*/
1513 operand *
1514 operandFromOperand (operand * op)
1515 {
1516   operand *nop;
1517
1518   if (!op)
1519     return NULL;
1520   nop = newOperand ();
1521   nop->type = op->type;
1522   nop->isaddr = op->isaddr;
1523   nop->key = op->key;
1524   nop->isvolatile = op->isvolatile;
1525   nop->isGlobal = op->isGlobal;
1526   nop->isLiteral = op->isLiteral;
1527   nop->usesDefs = op->usesDefs;
1528   nop->isParm = op->isParm;
1529   
1530   switch (nop->type)
1531     {
1532     case SYMBOL:
1533       nop->operand.symOperand = op->operand.symOperand;
1534       break;
1535     case VALUE:
1536       nop->operand.valOperand = op->operand.valOperand;
1537       break;
1538     case TYPE:
1539       nop->operand.typeOperand = op->operand.typeOperand;
1540       break;
1541     }
1542
1543   return nop;
1544 }
1545
1546 /*-----------------------------------------------------------------*/
1547 /* opFromOpWithDU - makes a copy of the operand and DU chains      */
1548 /*-----------------------------------------------------------------*/
1549 operand *
1550 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1551 {
1552   operand *nop = operandFromOperand (op);
1553
1554   if (nop->type == SYMBOL)
1555     {
1556       OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1557       OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1558     }
1559
1560   return nop;
1561 }
1562
1563 /*-----------------------------------------------------------------*/
1564 /* operandFromSymbol - creates an operand from a symbol            */
1565 /*-----------------------------------------------------------------*/
1566 operand *
1567 operandFromSymbol (symbol * sym)
1568 {
1569   operand *op;
1570   iCode *ic;
1571   int ok = 1;
1572   /* if the symbol's type is a literal */
1573   /* then it is an enumerator type     */
1574   if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1575     return operandFromValue (valFromType (sym->etype));
1576
1577   if (!sym->key)
1578     sym->key = ++operandKey;
1579
1580   /* if this an implicit variable, means struct/union */
1581   /* member so just return it                         */
1582   if (sym->implicit || IS_FUNC (sym->type))
1583     {
1584       op = newOperand ();
1585       op->type = SYMBOL;
1586       op->operand.symOperand = sym;
1587       op->key = sym->key;
1588       op->isvolatile = isOperandVolatile (op, TRUE);
1589       op->isGlobal = isOperandGlobal (op);
1590       return op;
1591     }
1592
1593   /* under the following conditions create a
1594      register equivalent for a local symbol */
1595   if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1596       (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1597       !TARGET_IS_HC08 &&
1598       (!(options.model == MODEL_FLAT24)) ) &&
1599       options.stackAuto == 0)
1600     ok = 0;
1601
1602   if (!IS_AGGREGATE (sym->type) &&      /* not an aggregate */
1603       !IS_FUNC (sym->type) &&           /* not a function   */
1604       !sym->_isparm &&                  /* not a parameter  */
1605       IS_AUTO (sym) &&                  /* is a local auto variable */
1606       !sym->addrtaken &&                /* whose address has not been taken */
1607       !sym->reqv &&                     /* does not already have a reg equivalence */
1608       !IS_VOLATILE (sym->etype) &&      /* not declared as volatile */
1609       !sym->islbl &&                    /* not a label */
1610       ok &&                             /* farspace check */
1611       !IS_BITVAR (sym->etype)           /* not a bit variable */
1612     )
1613     {                                   
1614
1615       /* we will use it after all optimizations
1616          and before liveRange calculation */
1617       sym->reqv = newiTempOperand (sym->type, 0);
1618       sym->reqv->key = sym->key;
1619       OP_SYMBOL (sym->reqv)->prereqv = sym;
1620       OP_SYMBOL (sym->reqv)->key = sym->key;
1621       OP_SYMBOL (sym->reqv)->isreqv = 1;
1622       OP_SYMBOL (sym->reqv)->islocal = 1;
1623       OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
1624       SPIL_LOC (sym->reqv) = sym;
1625     }
1626
1627   if (!IS_AGGREGATE (sym->type))
1628     {
1629       op = newOperand ();
1630       op->type = SYMBOL;
1631       op->operand.symOperand = sym;
1632       op->isaddr = 1;
1633       op->key = sym->key;
1634       op->isvolatile = isOperandVolatile (op, TRUE);
1635       op->isGlobal = isOperandGlobal (op);
1636       op->isPtr = IS_PTR (operandType (op));
1637       op->isParm = sym->_isparm;
1638       return op;
1639     }
1640
1641   /* create :-                     */
1642   /*    itemp = &[_symbol]         */
1643
1644   ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1645   IC_LEFT (ic)->type = SYMBOL;
1646   IC_LEFT (ic)->operand.symOperand = sym;
1647   IC_LEFT (ic)->key = sym->key;
1648   (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1649   (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1650   IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1651
1652   /* create result */
1653   IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1654   if (IS_ARRAY (sym->type))
1655     {
1656       IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1657       IC_RESULT (ic)->isaddr = 0;
1658     }
1659   else
1660     IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1661
1662   ADDTOCHAIN (ic);
1663
1664   return IC_RESULT (ic);
1665 }
1666
1667 /*-----------------------------------------------------------------*/
1668 /* operandFromValue - creates an operand from value                */
1669 /*-----------------------------------------------------------------*/
1670 operand *
1671 operandFromValue (value * val)
1672 {
1673   operand *op;
1674
1675   /* if this is a symbol then do the symbol thing */
1676   if (val->sym)
1677     return operandFromSymbol (val->sym);
1678
1679   /* this is not a symbol */
1680   op = newOperand ();
1681   op->type = VALUE;
1682   op->operand.valOperand = val;
1683   op->isLiteral = isOperandLiteral (op);
1684   return op;
1685 }
1686
1687 /*-----------------------------------------------------------------*/
1688 /* operandFromLink - operand from typeChain                        */
1689 /*-----------------------------------------------------------------*/
1690 operand *
1691 operandFromLink (sym_link * type)
1692 {
1693   operand *op;
1694
1695   /* operand from sym_link */
1696   if (!type)
1697     return NULL;
1698
1699   op = newOperand ();
1700   op->type = TYPE;
1701   op->operand.typeOperand = copyLinkChain (type);
1702   return op;
1703 }
1704
1705 /*-----------------------------------------------------------------*/
1706 /* operandFromLit - makes an operand from a literal value          */
1707 /*-----------------------------------------------------------------*/
1708 operand *
1709 operandFromLit (double i)
1710 {
1711   return operandFromValue (valueFromLit (i));
1712 }
1713
1714 /*-----------------------------------------------------------------*/
1715 /* operandFromAst - creates an operand from an ast                 */
1716 /*-----------------------------------------------------------------*/
1717 operand *
1718 operandFromAst (ast * tree,int lvl)
1719 {
1720
1721   if (!tree)
1722     return NULL;
1723
1724   /* depending on type do */
1725   switch (tree->type)
1726     {
1727     case EX_OP:
1728       return ast2iCode (tree,lvl+1);
1729       break;
1730
1731     case EX_VALUE:
1732       return operandFromValue (tree->opval.val);
1733       break;
1734
1735     case EX_LINK:
1736       return operandFromLink (tree->opval.lnk);
1737       break;
1738
1739     default:
1740       assert (0);
1741     }
1742   
1743   /*  Just to keep the compiler happy */
1744   return (operand *) 0;
1745 }
1746
1747 /*-----------------------------------------------------------------*/
1748 /* setOperandType - sets the operand's type to the given type      */
1749 /*-----------------------------------------------------------------*/
1750 void 
1751 setOperandType (operand * op, sym_link * type)
1752 {
1753   /* depending on the type of operand */
1754   switch (op->type)
1755     {
1756
1757     case VALUE:
1758       op->operand.valOperand->etype =
1759         getSpec (op->operand.valOperand->type =
1760                  copyLinkChain (type));
1761       return;
1762
1763     case SYMBOL:
1764       if (op->operand.symOperand->isitmp)
1765         op->operand.symOperand->etype =
1766           getSpec (op->operand.symOperand->type =
1767                    copyLinkChain (type));
1768       else
1769         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1770                 "attempt to modify type of source");
1771       return;
1772
1773     case TYPE:
1774       op->operand.typeOperand = copyLinkChain (type);
1775       return;
1776     }
1777
1778 }
1779
1780 /*-----------------------------------------------------------------*/
1781 /* Get size in byte of ptr need to access an array                 */
1782 /*-----------------------------------------------------------------*/
1783 static int
1784 getArraySizePtr (operand * op)
1785 {
1786   sym_link *ltype = operandType(op);
1787
1788   if(IS_PTR(ltype))
1789     {
1790       int size = getSize(ltype);
1791       return((IS_GENPTR(ltype) && GPTRSIZE > FPTRSIZE) ? (size-1) : size);
1792     }
1793
1794   if(IS_ARRAY(ltype))
1795     {
1796       sym_link *letype = getSpec(ltype);
1797       switch (PTR_TYPE (SPEC_OCLS (letype)))
1798         {
1799         case IPOINTER:
1800         case PPOINTER:
1801         case POINTER:
1802           return (PTRSIZE);
1803         case EEPPOINTER:
1804         case FPOINTER:
1805         case CPOINTER:
1806         case FUNCTION:
1807           return (FPTRSIZE);
1808         case GPOINTER:
1809           if (GPTRSIZE > FPTRSIZE)
1810             return (GPTRSIZE-1);
1811           else
1812             return (FPTRSIZE);
1813
1814         default:
1815           return (FPTRSIZE);
1816         }
1817     }
1818   return (FPTRSIZE);
1819 }
1820
1821 /*-----------------------------------------------------------------*/
1822 /* perform "usual unary conversions"                               */
1823 /*-----------------------------------------------------------------*/
1824 #if 0
1825 static operand *
1826 usualUnaryConversions (operand * op)
1827 {
1828   if (IS_INTEGRAL (operandType (op)))
1829     {
1830       if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1831         {
1832           /* Widen to int. */
1833           return geniCodeCast (INTTYPE, op, TRUE);
1834         }
1835     }
1836   return op;
1837 }
1838 #endif
1839
1840 /*-----------------------------------------------------------------*/
1841 /* perform "usual binary conversions"                              */
1842 /*-----------------------------------------------------------------*/
1843
1844 static sym_link *
1845 usualBinaryConversions (operand ** op1, operand ** op2,
1846                         RESULT_TYPE resultType, int op)
1847 {
1848   sym_link *ctype;
1849   sym_link *rtype = operandType (*op2);
1850   sym_link *ltype = operandType (*op1);
1851
1852   ctype = computeType (ltype, rtype, resultType, op);
1853
1854   switch (op)
1855     {
1856       case '*':
1857       case '/':
1858       case '%':
1859         if (IS_CHAR (getSpec (ltype)) && IS_CHAR (getSpec (rtype)))
1860           {
1861             /* one byte operations: keep signedness for code generator */
1862             return ctype;
1863           }
1864         break;
1865       default:
1866         break;
1867     }
1868
1869   *op1 = geniCodeCast (ctype, *op1, TRUE);
1870   *op2 = geniCodeCast (ctype, *op2, TRUE);
1871         
1872   return ctype;
1873 }
1874
1875 /*-----------------------------------------------------------------*/
1876 /* geniCodeValueAtAddress - generate intermeditate code for value  */
1877 /*                          at address                             */
1878 /*-----------------------------------------------------------------*/
1879 operand *
1880 geniCodeRValue (operand * op, bool force)
1881 {
1882   iCode *ic;
1883   sym_link *type = operandType (op);
1884   sym_link *etype = getSpec (type);
1885
1886   /* if this is an array & already */
1887   /* an address then return this   */
1888   if (IS_AGGREGATE (type) ||
1889       (IS_PTR (type) && !force && !op->isaddr))
1890     return operandFromOperand (op);
1891
1892   /* if this is not an address then must be */
1893   /* rvalue already so return this one      */
1894   if (!op->isaddr)
1895     return op;
1896
1897   /* if this is not a temp symbol then */
1898   if (!IS_ITEMP (op) &&
1899       !force &&
1900       !(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08))
1901     {
1902       op = operandFromOperand (op);
1903       op->isaddr = 0;
1904       return op;
1905     }
1906
1907   if (IS_SPEC (type) &&
1908       IS_TRUE_SYMOP (op) &&
1909       (!(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08) ||
1910       (options.model == MODEL_FLAT24) ))
1911     {
1912       op = operandFromOperand (op);
1913       op->isaddr = 0;
1914       return op;
1915     }
1916
1917   ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1918   if (IS_PTR (type) && op->isaddr && force)
1919     type = type->next;
1920
1921   type = copyLinkChain (type);
1922
1923   IC_RESULT (ic) = newiTempOperand (type, 1);
1924   IC_RESULT (ic)->isaddr = 0;
1925
1926 /*     ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1927
1928   ADDTOCHAIN (ic);
1929
1930   return IC_RESULT (ic);
1931 }
1932
1933 /*-----------------------------------------------------------------*/
1934 /* geniCodeCast - changes the value from one type to another       */
1935 /*-----------------------------------------------------------------*/
1936 static operand *
1937 geniCodeCast (sym_link * type, operand * op, bool implicit)
1938 {
1939   iCode *ic;
1940   sym_link *optype;
1941   sym_link *opetype = getSpec (optype = operandType (op));
1942   sym_link *restype;
1943   int errors=0;
1944
1945   /* one of them has size zero then error */
1946   if (IS_VOID (optype))
1947     {
1948       werror (E_CAST_ZERO);
1949       return op;
1950     }
1951
1952   if (IS_ITEMP (op) && IS_ARRAY (OP_SYMBOL (op)->type))
1953     {
1954       geniCodeArray2Ptr (op);
1955       op->isaddr = 0;
1956     }
1957     
1958   /* if the operand is already the desired type then do nothing */
1959   if (compareType (type, optype) == 1)
1960     return op;
1961
1962   /* if this is a literal then just change the type & return */
1963   if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1964     {
1965       return operandFromValue (valCastLiteral (type,
1966                                                operandLitValue (op)));
1967     }
1968
1969   /* if casting to/from pointers, do some checking */
1970   if (IS_PTR(type)) { // to a pointer
1971     if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1972       if (IS_INTEGRAL(optype)) {
1973         // maybe this is NULL, than it's ok.
1974         if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1975           if (port->s.gptr_size > port->s.fptr_size && IS_GENPTR(type)) {
1976             // no way to set the storage
1977             if (IS_LITERAL(optype)) {
1978               werror(E_LITERAL_GENERIC);
1979               errors++;
1980             } else {
1981               werror(E_NONPTR2_GENPTR);
1982               errors++;
1983             }
1984           } else if (implicit) {
1985             werror(W_INTEGRAL2PTR_NOCAST);
1986             errors++;
1987           }
1988         }
1989       } else {
1990         // shouldn't do that with float, array or structure unless to void
1991         if (!IS_VOID(getSpec(type)) &&
1992             !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1993           werror(E_INCOMPAT_TYPES);
1994           errors++;
1995         }
1996       }
1997     } else { // from a pointer to a pointer
1998       if (IS_GENPTR(type) && IS_VOID(type->next))
1999         { // cast to void* is always allowed
2000         }
2001       else if (IS_GENPTR(optype) && IS_VOID(optype->next))
2002         { // cast from void* is always allowed
2003         }
2004       else if (port->s.gptr_size > port->s.fptr_size /*!TARGET_IS_Z80 && !TARGET_IS_GBZ80*/) {
2005         // if not a pointer to a function
2006         if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
2007           if (implicit) { // if not to generic, they have to match
2008             if (!IS_GENPTR(type) &&
2009                 !((DCL_TYPE(optype) == DCL_TYPE(type)) ||
2010                   ((DCL_TYPE(optype) == POINTER) && (DCL_TYPE(type) == IPOINTER))
2011                  )
2012                )
2013             {
2014               werror(E_INCOMPAT_PTYPES);
2015               errors++;
2016             }
2017           }
2018         }
2019       }
2020     }
2021   } else { // to a non pointer
2022     if (IS_PTR(optype)) { // from a pointer
2023       if (implicit) { // sneaky
2024         if (IS_INTEGRAL(type)) {
2025           werror(W_PTR2INTEGRAL_NOCAST);
2026           errors++;
2027         } else { // shouldn't do that with float, array or structure
2028           werror(E_INCOMPAT_TYPES);
2029           errors++;
2030         }
2031       }
2032     }
2033   }
2034   if (errors) {
2035     printFromToType (optype, type);
2036   }
2037
2038   /* if they are the same size create an assignment */
2039   
2040   /* This seems very dangerous to me, since there are several */
2041   /* optimizations (for example, gcse) that don't notice the  */
2042   /* cast hidden in this assignement and may simplify an      */
2043   /* iCode to use the original (uncasted) operand.            */
2044   /* Unfortunately, other things break when this cast is      */
2045   /* made explicit. Need to fix this someday.                 */
2046   /* -- EEP, 2004/01/21                                       */
2047   if (getSize (type) == getSize (optype) &&
2048       !IS_BITFIELD (type) &&
2049       !IS_FLOAT (type) &&
2050       !IS_FLOAT (optype) &&
2051       ((IS_SPEC (type) && IS_SPEC (optype)) ||
2052        (!IS_SPEC (type) && !IS_SPEC (optype))))
2053     {
2054       ic = newiCode ('=', NULL, op);
2055       IC_RESULT (ic) = newiTempOperand (type, 0);
2056       SPIL_LOC (IC_RESULT (ic)) =
2057         (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
2058       IC_RESULT (ic)->isaddr = 0;
2059     }
2060   else
2061     {
2062       ic = newiCode (CAST, operandFromLink (type),
2063                      geniCodeRValue (op, FALSE));
2064
2065       IC_RESULT (ic) = newiTempOperand (type, 0);
2066     }
2067
2068   /* preserve the storage class & output class */
2069   /* of the original variable                  */
2070   restype = getSpec (operandType (IC_RESULT (ic)));
2071   if (!IS_LITERAL(opetype) &&
2072       !IS_BIT(opetype))
2073     {
2074       SPEC_SCLS (restype) = SPEC_SCLS (opetype);
2075       SPEC_OCLS (restype) = SPEC_OCLS (opetype);
2076     }
2077   ADDTOCHAIN (ic);
2078   return IC_RESULT (ic);
2079 }
2080
2081 /*-----------------------------------------------------------------*/
2082 /* geniCodeLabel - will create a Label                             */
2083 /*-----------------------------------------------------------------*/
2084 void
2085 geniCodeLabel (symbol * label)
2086 {
2087   iCode *ic;
2088
2089   ic = newiCodeLabelGoto (LABEL, label);
2090   ADDTOCHAIN (ic);
2091 }
2092
2093 /*-----------------------------------------------------------------*/
2094 /* geniCodeGoto  - will create a Goto                              */
2095 /*-----------------------------------------------------------------*/
2096 void
2097 geniCodeGoto (symbol * label)
2098 {
2099   iCode *ic;
2100
2101   ic = newiCodeLabelGoto (GOTO, label);
2102   ADDTOCHAIN (ic);
2103 }
2104
2105 /*-----------------------------------------------------------------*/
2106 /* geniCodeMultiply - gen intermediate code for multiplication     */
2107 /*-----------------------------------------------------------------*/
2108 static operand *
2109 geniCodeMultiply (operand * left, operand * right, RESULT_TYPE resultType)
2110 {
2111   iCode *ic;
2112   int p2 = 0;
2113   sym_link *resType;
2114   LRTYPE;
2115
2116   /* if they are both literal then we know the result */
2117   if (IS_LITERAL (letype) && IS_LITERAL (retype))
2118     return operandFromValue (valMult (left->operand.valOperand,
2119                                       right->operand.valOperand));
2120
2121   if (IS_LITERAL(retype)) {
2122     p2 = powof2 ((TYPE_UDWORD) floatFromVal (right->operand.valOperand));
2123   }
2124
2125   resType = usualBinaryConversions (&left, &right, resultType, '*');
2126 #if 1
2127   rtype = operandType (right);
2128   retype = getSpec (rtype);
2129   ltype = operandType (left);
2130   letype = getSpec (ltype);
2131 #endif
2132
2133   /* if the right is a literal & power of 2 */
2134   /* then make it a left shift              */
2135   /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
2136      efficient in most cases than 2 bytes result = 2 bytes << literal
2137      if port has 1 byte muldiv */
2138   if (p2 && !IS_FLOAT (letype)
2139       && !((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype))
2140            && (port->support.muldiv == 1))
2141       && strcmp (port->target, "pic16") != 0  /* don't shift for pic */
2142       && strcmp (port->target, "pic14") != 0)
2143     {
2144       if ((resultType == RESULT_TYPE_INT) && (getSize (resType) != getSize (ltype)))
2145         {
2146           /* LEFT_OP need same size for left and result, */
2147           left = geniCodeCast (resType, left, TRUE);
2148           ltype = operandType (left);
2149         }
2150       ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
2151     }
2152   else
2153     {
2154       ic = newiCode ('*', left, right);         /* normal multiplication */
2155       /* if the size left or right > 1 then support routine */
2156       if (getSize (ltype) > 1 || getSize (rtype) > 1)
2157         ic->supportRtn = 1;
2158
2159     }
2160   IC_RESULT (ic) = newiTempOperand (resType, 1);
2161
2162   ADDTOCHAIN (ic);
2163   return IC_RESULT (ic);
2164 }
2165
2166 /*-----------------------------------------------------------------*/
2167 /* geniCodeDivision - gen intermediate code for division           */
2168 /*-----------------------------------------------------------------*/
2169 static operand *
2170 geniCodeDivision (operand * left, operand * right, RESULT_TYPE resultType)
2171 {
2172   iCode *ic;
2173   int p2 = 0;
2174   sym_link *resType;
2175   sym_link *rtype = operandType (right);
2176   sym_link *retype = getSpec (rtype);
2177   sym_link *ltype = operandType (left);
2178   sym_link *letype = getSpec (ltype);
2179
2180   resType = usualBinaryConversions (&left, &right, resultType, '/');
2181
2182   /* if the right is a literal & power of 2
2183      and left is unsigned then make it a
2184      right shift */
2185   if (IS_LITERAL (retype) &&
2186       !IS_FLOAT (letype) &&
2187       IS_UNSIGNED(letype) &&
2188       (p2 = powof2 ((TYPE_UDWORD)
2189                     floatFromVal (right->operand.valOperand)))) {
2190     ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
2191   }
2192   else
2193     {
2194       ic = newiCode ('/', left, right);         /* normal division */
2195       /* if the size left or right > 1 then support routine */
2196       if (getSize (ltype) > 1 || getSize (rtype) > 1)
2197         ic->supportRtn = 1;
2198     }
2199   IC_RESULT (ic) = newiTempOperand (resType, 0);
2200
2201   ADDTOCHAIN (ic);
2202   return IC_RESULT (ic);
2203 }
2204 /*-----------------------------------------------------------------*/
2205 /* geniCodeModulus  - gen intermediate code for modulus            */
2206 /*-----------------------------------------------------------------*/
2207 static operand *
2208 geniCodeModulus (operand * left, operand * right, RESULT_TYPE resultType)
2209 {
2210   iCode *ic;
2211   sym_link *resType;
2212   LRTYPE;
2213
2214   /* if they are both literal then we know the result */
2215   if (IS_LITERAL (letype) && IS_LITERAL (retype))
2216     return operandFromValue (valMod (left->operand.valOperand,
2217                                      right->operand.valOperand));
2218
2219   resType = usualBinaryConversions (&left, &right, resultType, '%');
2220
2221   /* now they are the same size */
2222   ic = newiCode ('%', left, right);
2223
2224   /* if the size left or right > 1 then support routine */
2225   if (getSize (ltype) > 1 || getSize (rtype) > 1)
2226     ic->supportRtn = 1;
2227   IC_RESULT (ic) = newiTempOperand (resType, 0);
2228
2229   ADDTOCHAIN (ic);
2230   return IC_RESULT (ic);
2231 }
2232
2233 /*-----------------------------------------------------------------*/
2234 /* geniCodePtrPtrSubtract - subtracts pointer from pointer         */
2235 /*-----------------------------------------------------------------*/
2236 operand *
2237 geniCodePtrPtrSubtract (operand * left, operand * right)
2238 {
2239   iCode *ic;
2240   operand *result;
2241   LRTYPE;
2242
2243   /* if they are both literals then */
2244   if (IS_LITERAL (letype) && IS_LITERAL (retype))
2245     {
2246       result = operandFromValue (valMinus (left->operand.valOperand,
2247                                            right->operand.valOperand));
2248       goto subtractExit;
2249     }
2250
2251   ic = newiCode ('-', left, right);
2252
2253   IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
2254   ADDTOCHAIN (ic);
2255
2256 subtractExit:
2257   if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
2258     return result;
2259   }
2260   
2261   // should we really do this? is this ANSI?
2262   return geniCodeDivision (result,
2263                            operandFromLit (getSize (ltype->next)),
2264                            FALSE);
2265 }
2266
2267 /*-----------------------------------------------------------------*/
2268 /* geniCodeSubtract - generates code for subtraction               */
2269 /*-----------------------------------------------------------------*/
2270 static operand *
2271 geniCodeSubtract (operand * left, operand * right, RESULT_TYPE resultType)
2272 {
2273   iCode *ic;
2274   int isarray = 0;
2275   sym_link *resType;
2276   LRTYPE;
2277
2278   /* if they both pointers then */
2279   if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
2280       (IS_PTR (rtype) || IS_ARRAY (rtype)))
2281     return geniCodePtrPtrSubtract (left, right);
2282
2283   /* if they are both literal then we know the result */
2284   if (IS_LITERAL (letype) && IS_LITERAL (retype)
2285       && left->isLiteral && right->isLiteral)
2286     return operandFromValue (valMinus (left->operand.valOperand,
2287                                        right->operand.valOperand));
2288
2289   /* if left is an array or pointer */
2290   if (IS_PTR (ltype) || IS_ARRAY (ltype))
2291     {
2292       isarray = left->isaddr;
2293       right = geniCodeMultiply (right,
2294                                 operandFromLit (getSize (ltype->next)),
2295                                 (getArraySizePtr(left) >= INTSIZE) ?
2296                                   RESULT_TYPE_INT :
2297                                   RESULT_TYPE_CHAR);
2298       resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2299     }
2300   else
2301     {                           /* make them the same size */
2302       resType = usualBinaryConversions (&left, &right, resultType, '-');
2303     }
2304
2305   ic = newiCode ('-', left, right);
2306
2307   IC_RESULT (ic) = newiTempOperand (resType, 1);
2308   IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2309
2310   /* if left or right is a float */
2311   if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2312     ic->supportRtn = 1;
2313
2314   ADDTOCHAIN (ic);
2315   return IC_RESULT (ic);
2316 }
2317
2318 /*-----------------------------------------------------------------*/
2319 /* geniCodeAdd - generates iCode for addition                      */
2320 /*-----------------------------------------------------------------*/
2321 static operand *
2322 geniCodeAdd (operand * left, operand * right, RESULT_TYPE resultType, int lvl)
2323 {
2324   iCode *ic;
2325   sym_link *resType;
2326   operand *size;
2327   int isarray = 0;
2328   bool indexUnsigned;
2329   LRTYPE;
2330
2331   /* if the right side is LITERAL zero */
2332   /* return the left side              */
2333   if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (rtype)))
2334     return left;
2335
2336   /* if left is literal zero return right */
2337   if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (ltype)))
2338     return right;
2339
2340   /* if left is a pointer then size */
2341   if (IS_PTR (ltype) || IS_ARRAY(ltype))
2342     {
2343       isarray = left->isaddr;
2344       // there is no need to multiply with 1
2345       if (getSize (ltype->next) != 1)
2346         {
2347           size  = operandFromLit (getSize (ltype->next));
2348           SPEC_USIGN (getSpec (operandType (size))) = 1;
2349           indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
2350           right = geniCodeMultiply (right,
2351                                     size,
2352                                     (getArraySizePtr(left) >= INTSIZE) ?
2353                                       RESULT_TYPE_INT :
2354                                       RESULT_TYPE_CHAR);
2355           /* Even if right is a 'unsigned char',
2356              the result will be a 'signed int' due to the promotion rules.
2357              It doesn't make sense when accessing arrays, so let's fix it here: */
2358           if (indexUnsigned)
2359             SPEC_USIGN (getSpec (operandType (right))) = 1;
2360         }
2361       resType = copyLinkChain (ltype);
2362     }
2363   else
2364     { // make them the same size
2365       resType = usualBinaryConversions (&left, &right, resultType, '+');
2366     }
2367
2368   /* if they are both literals then we know */
2369   if (IS_LITERAL (letype) && IS_LITERAL (retype)
2370       && left->isLiteral && right->isLiteral)
2371     return operandFromValue (valPlus (valFromType (ltype),
2372                                       valFromType (rtype)));
2373
2374   ic = newiCode ('+', left, right);
2375
2376   IC_RESULT (ic) = newiTempOperand (resType, 1);
2377   IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2378
2379   /* if left or right is a float then support
2380      routine */
2381   if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2382     ic->supportRtn = 1;
2383
2384   ADDTOCHAIN (ic);
2385
2386   return IC_RESULT (ic);
2387
2388 }
2389
2390 /*-----------------------------------------------------------------*/
2391 /* aggrToPtr - changes an "aggregate" to a "pointer to aggregate"  */
2392 /*-----------------------------------------------------------------*/
2393 sym_link *
2394 aggrToPtr (sym_link * type, bool force)
2395 {
2396   sym_link *etype;
2397   sym_link *ptype;
2398
2399   if (IS_PTR (type) && !force)
2400     return type;
2401
2402   etype = getSpec (type);
2403   ptype = newLink (DECLARATOR);
2404
2405   ptype->next = type;
2406
2407   /* set the pointer depending on the storage class */
2408   DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype));
2409   return ptype;
2410 }
2411
2412 /*------------------------------------------------------------------*/
2413 /* aggrToPtrDclType - like aggrToPtr, but returns only the DCL_TYPE */
2414 /*------------------------------------------------------------------*/
2415 int
2416 aggrToPtrDclType (sym_link * type, bool force)
2417 {
2418   if (IS_PTR (type) && !force)
2419     return DCL_TYPE (type);
2420
2421   /* return the pointer depending on the storage class */
2422   return PTR_TYPE (SPEC_OCLS (getSpec (type)));
2423 }
2424
2425 /*-----------------------------------------------------------------*/
2426 /* geniCodeArray2Ptr - array to pointer                            */
2427 /*-----------------------------------------------------------------*/
2428 static operand *
2429 geniCodeArray2Ptr (operand * op)
2430 {
2431   sym_link *optype = operandType (op);
2432   sym_link *opetype = getSpec (optype);
2433
2434   /* set the pointer depending on the storage class */
2435   DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype));
2436
2437   op->isaddr = 0;
2438   return op;
2439 }
2440
2441
2442 /*-----------------------------------------------------------------*/
2443 /* geniCodeArray - array access                                    */
2444 /*-----------------------------------------------------------------*/
2445 static operand *
2446 geniCodeArray (operand * left, operand * right, int lvl)
2447 {
2448   iCode *ic;
2449   operand *size;
2450   sym_link *ltype = operandType (left);
2451   bool indexUnsigned;
2452
2453   if (IS_PTR (ltype))
2454     {
2455       if (IS_PTR (ltype->next) && left->isaddr)
2456         {
2457           left = geniCodeRValue (left, FALSE);
2458         }
2459
2460       return geniCodeDerefPtr (geniCodeAdd (left,
2461                                             right,
2462                                             (getArraySizePtr(left) >= INTSIZE) ?
2463                                               RESULT_TYPE_INT :
2464                                               RESULT_TYPE_CHAR,
2465                                             lvl),
2466                                lvl);
2467     }
2468   size = operandFromLit (getSize (ltype->next));
2469   SPEC_USIGN (getSpec (operandType (size))) = 1;
2470   indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
2471   right = geniCodeMultiply (right,
2472                             size,
2473                             (getArraySizePtr(left) >= INTSIZE) ?
2474                               RESULT_TYPE_INT :
2475                               RESULT_TYPE_CHAR);
2476   /* Even if right is a 'unsigned char', the result will be a 'signed int' due to the promotion rules.
2477      It doesn't make sense when accessing arrays, so let's fix it here: */
2478   if (indexUnsigned)
2479     SPEC_USIGN (getSpec (operandType (right))) = 1;
2480   /* we can check for limits here */
2481   /* already done in SDCCast.c
2482   if (isOperandLiteral (right) &&
2483       IS_ARRAY (ltype) &&
2484       DCL_ELEM (ltype) &&
2485       (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2486     {
2487       werror (W_IDX_OUT_OF_BOUNDS,
2488               (int) operandLitValue (right) / getSize (ltype->next),
2489               DCL_ELEM (ltype));
2490     }
2491   */
2492
2493   ic = newiCode ('+', left, right);
2494
2495   IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2496                                       !IS_AGGREGATE (ltype->next) &&
2497                                       !IS_PTR (ltype->next))
2498                                      ? ltype : ltype->next), 0);
2499
2500   if (!IS_AGGREGATE (ltype->next))
2501     {
2502       IC_RESULT (ic)->isaddr = 1;
2503       IC_RESULT (ic)->aggr2ptr = 1;
2504     }
2505   ADDTOCHAIN (ic);
2506
2507   return IC_RESULT (ic);
2508 }
2509
2510 /*-----------------------------------------------------------------*/
2511 /* geniCodeStruct - generates intermediate code for structures     */
2512 /*-----------------------------------------------------------------*/
2513 operand *
2514 geniCodeStruct (operand * left, operand * right, bool islval)
2515 {
2516   iCode *ic;
2517   sym_link *type = operandType (left);
2518   sym_link *etype = getSpec (type);
2519   sym_link *retype;
2520   symbol *element = getStructElement (SPEC_STRUCT (etype),
2521                                       right->operand.symOperand);
2522
2523   wassert(IS_SYMOP(right));
2524
2525   /* add the offset */
2526   ic = newiCode ('+', left, operandFromLit (element->offset));
2527
2528   IC_RESULT (ic) = newiTempOperand (element->type, 0);
2529
2530   /* preserve the storage & output class of the struct */
2531   /* as well as the volatile attribute */
2532   retype = getSpec (operandType (IC_RESULT (ic)));
2533   SPEC_SCLS (retype) = SPEC_SCLS (etype);
2534   SPEC_OCLS (retype) = SPEC_OCLS (etype);
2535   SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2536   SPEC_CONST (retype) |= SPEC_CONST (etype);
2537
2538   if (IS_PTR (element->type))
2539     setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2540
2541   IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2542
2543   ADDTOCHAIN (ic);
2544   return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2545 }
2546
2547 /*-----------------------------------------------------------------*/
2548 /* geniCodePostInc - generate int code for Post increment          */
2549 /*-----------------------------------------------------------------*/
2550 operand *
2551 geniCodePostInc (operand * op)
2552 {
2553   iCode *ic;
2554   operand *rOp;
2555   sym_link *optype = operandType (op);
2556   operand *result;
2557   operand *rv = (IS_ITEMP (op) ?
2558                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2559                  op);
2560   sym_link *rvtype = operandType (rv);
2561   int size = 0;
2562
2563   /* if this is not an address we have trouble */
2564   if (!op->isaddr)
2565     {
2566       werror (E_LVALUE_REQUIRED, "++");
2567       return op;
2568     }
2569
2570   rOp = newiTempOperand (rvtype, 0);
2571   OP_SYMBOL(rOp)->noSpilLoc = 1;
2572
2573   if (IS_ITEMP (rv))
2574     OP_SYMBOL(rv)->noSpilLoc = 1;
2575
2576   geniCodeAssign (rOp, rv, 0, 0);
2577
2578   size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2579   if (size == 0)
2580     werror(W_SIZEOF_VOID);
2581   if (IS_FLOAT (rvtype))
2582     ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2583   else
2584     ic = newiCode ('+', rv, operandFromLit (size));
2585
2586   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2587   ADDTOCHAIN (ic);
2588
2589   geniCodeAssign (op, result, 0, 0);
2590
2591   return rOp;
2592
2593 }
2594
2595 /*-----------------------------------------------------------------*/
2596 /* geniCodePreInc - generate code for preIncrement                 */
2597 /*-----------------------------------------------------------------*/
2598 operand *
2599 geniCodePreInc (operand * op, bool lvalue)
2600 {
2601   iCode *ic;
2602   sym_link *optype = operandType (op);
2603   operand *rop = (IS_ITEMP (op) ?
2604                   geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2605                   op);
2606   sym_link *roptype = operandType (rop);
2607   operand *result;
2608   int size = 0;
2609
2610   if (!op->isaddr)
2611     {
2612       werror (E_LVALUE_REQUIRED, "++");
2613       return op;
2614     }
2615
2616   size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2617   if (size == 0)
2618     werror(W_SIZEOF_VOID);
2619   if (IS_FLOAT (roptype))
2620     ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2621   else
2622     ic = newiCode ('+', rop, operandFromLit (size));
2623   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2624   ADDTOCHAIN (ic);
2625
2626   (void) geniCodeAssign (op, result, 0, 0);
2627   if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
2628     return op;
2629   else
2630     return result;
2631 }
2632
2633 /*-----------------------------------------------------------------*/
2634 /* geniCodePostDec - generates code for Post decrement             */
2635 /*-----------------------------------------------------------------*/
2636 operand *
2637 geniCodePostDec (operand * op)
2638 {
2639   iCode *ic;
2640   operand *rOp;
2641   sym_link *optype = operandType (op);
2642   operand *result;
2643   operand *rv = (IS_ITEMP (op) ?
2644                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2645                  op);
2646   sym_link *rvtype = operandType (rv);
2647   int size = 0;
2648
2649   /* if this is not an address we have trouble */
2650   if (!op->isaddr)
2651     {
2652       werror (E_LVALUE_REQUIRED, "--");
2653       return op;
2654     }
2655
2656   rOp = newiTempOperand (rvtype, 0);
2657   OP_SYMBOL(rOp)->noSpilLoc = 1;
2658
2659   if (IS_ITEMP (rv))
2660     OP_SYMBOL(rv)->noSpilLoc = 1;
2661
2662   geniCodeAssign (rOp, rv, 0, 0);
2663
2664   size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2665   if (size == 0)
2666     werror(W_SIZEOF_VOID);
2667   if (IS_FLOAT (rvtype))
2668     ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2669   else
2670     ic = newiCode ('-', rv, operandFromLit (size));
2671
2672   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2673   ADDTOCHAIN (ic);
2674
2675   geniCodeAssign (op, result, 0, 0);
2676
2677   return rOp;
2678
2679 }
2680
2681 /*-----------------------------------------------------------------*/
2682 /* geniCodePreDec - generate code for pre  decrement               */
2683 /*-----------------------------------------------------------------*/
2684 operand *
2685 geniCodePreDec (operand * op, bool lvalue)
2686 {
2687   iCode *ic;
2688   sym_link *optype = operandType (op);
2689   operand *rop = (IS_ITEMP (op) ?
2690                   geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2691                   op);
2692   sym_link *roptype = operandType (rop);
2693   operand *result;
2694   int size = 0;
2695
2696   if (!op->isaddr)
2697     {
2698       werror (E_LVALUE_REQUIRED, "--");
2699       return op;
2700     }
2701
2702   size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2703   if (size == 0)
2704     werror(W_SIZEOF_VOID);
2705   if (IS_FLOAT (roptype))
2706     ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2707   else
2708     ic = newiCode ('-', rop, operandFromLit (size));
2709   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2710   ADDTOCHAIN (ic);
2711
2712   (void) geniCodeAssign (op, result, 0, 0);
2713   if (lvalue || IS_TRUE_SYMOP (op) || IS_BITVAR (optype))
2714     return op;
2715   else
2716     return result;
2717 }
2718
2719
2720 /*-----------------------------------------------------------------*/
2721 /* geniCodeBitwise - gen int code for bitWise  operators           */
2722 /*-----------------------------------------------------------------*/
2723 operand *
2724 geniCodeBitwise (operand * left, operand * right,
2725                  int oper, sym_link * resType)
2726 {
2727   iCode *ic;
2728
2729   left = geniCodeCast (resType, left, TRUE);
2730   right = geniCodeCast (resType, right, TRUE);
2731
2732   ic = newiCode (oper, left, right);
2733   IC_RESULT (ic) = newiTempOperand (resType, 0);
2734
2735   ADDTOCHAIN (ic);
2736   return IC_RESULT (ic);
2737 }
2738
2739 /*-----------------------------------------------------------------*/
2740 /* geniCodeAddressOf - gens icode for '&' address of operator      */
2741 /*-----------------------------------------------------------------*/
2742 operand *
2743 geniCodeAddressOf (operand * op)
2744 {
2745   iCode *ic;
2746   sym_link *p;
2747   sym_link *optype = operandType (op);
2748   sym_link *opetype = getSpec (optype);
2749
2750   if (IS_ITEMP (op) && op->isaddr && IS_PTR (optype))
2751     {
2752       op = operandFromOperand (op);
2753       op->isaddr = 0;
2754       return op;
2755     }
2756   
2757   /* lvalue check already done in decorateType */
2758   /* this must be a lvalue */
2759 /*     if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2760 /*  werror (E_LVALUE_REQUIRED,"&"); */
2761 /*  return op; */
2762 /*     } */
2763
2764   p = newLink (DECLARATOR);
2765
2766   /* set the pointer depending on the storage class */
2767   DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
2768
2769   p->next = copyLinkChain (optype);
2770
2771   /* if already a temp */
2772   if (IS_ITEMP (op))
2773     {
2774       setOperandType (op, p);
2775       op->isaddr = 0;
2776       return op;
2777     }
2778
2779   /* other wise make this of the type coming in */
2780   ic = newiCode (ADDRESS_OF, op, NULL);
2781   IC_RESULT (ic) = newiTempOperand (p, 1);
2782   IC_RESULT (ic)->isaddr = 0;
2783   ADDTOCHAIN (ic);
2784   return IC_RESULT (ic);
2785 }
2786 /*-----------------------------------------------------------------*/
2787 /* setOClass - sets the output class depending on the pointer type */
2788 /*-----------------------------------------------------------------*/
2789 void 
2790 setOClass (sym_link * ptr, sym_link * spec)
2791 {
2792   switch (DCL_TYPE (ptr))
2793     {
2794     case POINTER:
2795       SPEC_OCLS (spec) = data;
2796       break;
2797
2798     case GPOINTER:
2799       SPEC_OCLS (spec) = generic;
2800       break;
2801
2802     case FPOINTER:
2803       SPEC_OCLS (spec) = xdata;
2804       break;
2805
2806     case CPOINTER:
2807       SPEC_OCLS (spec) = code;
2808       break;
2809
2810     case IPOINTER:
2811       SPEC_OCLS (spec) = idata;
2812       break;
2813
2814     case PPOINTER:
2815       SPEC_OCLS (spec) = xstack;
2816       break;
2817
2818     case EEPPOINTER:
2819       SPEC_OCLS (spec) = eeprom;
2820       break;
2821
2822     default:
2823       break;
2824
2825     }
2826 }
2827
2828 /*-----------------------------------------------------------------*/
2829 /* geniCodeDerefPtr - dereference pointer with '*'                 */
2830 /*-----------------------------------------------------------------*/
2831 operand *
2832 geniCodeDerefPtr (operand * op,int lvl)
2833 {
2834   sym_link *rtype, *retype;
2835   sym_link *optype = operandType (op);
2836
2837   // if this is an array then array access
2838   if (IS_ARRAY (optype)) {
2839     // don't worry, this will be optimized out later
2840     return geniCodeArray (op, operandFromLit (0), lvl);
2841   }
2842
2843   // just in case someone screws up
2844   wassert (IS_PTR (optype));
2845
2846   if (IS_TRUE_SYMOP (op))
2847     {
2848       op->isaddr = 1;
2849       op = geniCodeRValue (op, TRUE);
2850     }
2851
2852   /* now get rid of the pointer part */
2853   if (isLvaluereq(lvl) && IS_ITEMP (op))
2854     {
2855       retype = getSpec (rtype = copyLinkChain (optype));
2856     }
2857   else
2858     {
2859       retype = getSpec (rtype = copyLinkChain (optype->next));
2860       /* outputclass needs 2b updated */
2861       setOClass (optype, retype);
2862     }
2863   
2864   op->isGptr = IS_GENPTR (optype);
2865
2866   op->isaddr = (IS_PTR (rtype) ||
2867                 IS_STRUCT (rtype) ||
2868                 IS_INT (rtype) ||
2869                 IS_CHAR (rtype) ||
2870                 IS_FLOAT (rtype));
2871
2872   if (!isLvaluereq(lvl))
2873     op = geniCodeRValue (op, TRUE);
2874
2875   setOperandType (op, rtype);
2876
2877   return op;
2878 }
2879
2880 /*-----------------------------------------------------------------*/
2881 /* geniCodeUnaryMinus - does a unary minus of the operand          */
2882 /*-----------------------------------------------------------------*/
2883 operand *
2884 geniCodeUnaryMinus (operand * op)
2885 {
2886   iCode *ic;
2887   sym_link *optype = operandType (op);
2888
2889   if (IS_LITERAL (optype))
2890     return operandFromLit (-floatFromVal (op->operand.valOperand));
2891
2892   ic = newiCode (UNARYMINUS, op, NULL);
2893   IC_RESULT (ic) = newiTempOperand (optype, 0);
2894   ADDTOCHAIN (ic);
2895   return IC_RESULT (ic);
2896 }
2897
2898 /*-----------------------------------------------------------------*/
2899 /* geniCodeLeftShift - gen i code for left shift                   */
2900 /*-----------------------------------------------------------------*/
2901 operand *
2902 geniCodeLeftShift (operand * left, operand * right, RESULT_TYPE resultType)
2903 {
2904   iCode *ic;
2905   sym_link *resType;
2906
2907   ic = newiCode (LEFT_OP, left, right);
2908
2909   resType = usualBinaryConversions (&left, &right, resultType, LEFT_OP);
2910   IC_RESULT (ic) = newiTempOperand (resType, 0);
2911   ADDTOCHAIN (ic);
2912   return IC_RESULT (ic);
2913 }
2914
2915 /*-----------------------------------------------------------------*/
2916 /* geniCodeRightShift - gen i code for right shift                 */
2917 /*-----------------------------------------------------------------*/
2918 operand *
2919 geniCodeRightShift (operand * left, operand * right)
2920 {
2921   iCode *ic;
2922
2923   ic = newiCode (RIGHT_OP, left, right);
2924   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2925   ADDTOCHAIN (ic);
2926   return IC_RESULT (ic);
2927 }
2928
2929 /*-----------------------------------------------------------------*/
2930 /* geniCodeLogic- logic code                                       */
2931 /*-----------------------------------------------------------------*/
2932 static operand *
2933 geniCodeLogic (operand * left, operand * right, int op)
2934 {
2935   iCode *ic;
2936   sym_link *ctype;
2937   sym_link *rtype = operandType (right);
2938   sym_link *ltype = operandType (left);
2939
2940   /* left is integral type and right is literal then
2941      check if the literal value is within bounds */
2942   if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2943     {
2944       checkConstantRange(ltype,
2945                          OP_VALUE(right), "compare operation", 1);
2946     }
2947
2948   /* if one operand is a pointer and the other is a literal generic void pointer,
2949      change the type of the literal generic void pointer to match the other pointer */
2950   if (IS_GENPTR (ltype) && IS_VOID (ltype->next) && IS_ITEMP (left)
2951       && IS_PTR (rtype) && !IS_GENPTR(rtype))
2952     {
2953       /* find left's definition */
2954       ic = (iCode *) setFirstItem (iCodeChain);
2955       while (ic)
2956         {
2957           if (((ic->op == CAST) || (ic->op == '='))
2958               && isOperandEqual(left, IC_RESULT (ic)))
2959             break;
2960           else
2961             ic = setNextItem (iCodeChain);
2962         }
2963       /* if casting literal to generic pointer, then cast to rtype instead */
2964       if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic))) 
2965         {
2966           left = operandFromValue (valCastLiteral (rtype, operandLitValue (IC_RIGHT (ic))));
2967           ltype = operandType(left);
2968         }
2969     }
2970   if (IS_GENPTR (rtype) && IS_VOID (rtype->next) && IS_ITEMP (right)
2971       && IS_PTR (ltype) && !IS_GENPTR(ltype))
2972     {
2973       /* find right's definition */
2974       ic = (iCode *) setFirstItem (iCodeChain);
2975       while (ic)
2976         {
2977           if (((ic->op == CAST) || (ic->op == '='))
2978               && isOperandEqual(right, IC_RESULT (ic)))
2979             break;
2980           else
2981             ic = setNextItem (iCodeChain);
2982         }
2983       /* if casting literal to generic pointer, then cast to rtype instead */
2984       if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic))) 
2985         {
2986           right = operandFromValue (valCastLiteral (ltype, operandLitValue (IC_RIGHT (ic))));
2987           rtype = operandType(right);
2988         }
2989     }
2990
2991   ctype = usualBinaryConversions (&left, &right, RESULT_TYPE_NONE, 0);
2992
2993   ic = newiCode (op, left, right);
2994   IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2995
2996   /* if comparing float
2997      and not a '==' || '!=' || '&&' || '||' (these
2998      will be inlined */
2999   if (IS_FLOAT(ctype) &&
3000       op != EQ_OP &&
3001       op != NE_OP &&
3002       op != AND_OP &&
3003       op != OR_OP)
3004    ic->supportRtn = 1;
3005
3006   ADDTOCHAIN (ic);
3007   return IC_RESULT (ic);
3008 }
3009
3010 /*-----------------------------------------------------------------*/
3011 /* geniCodeLogicAndOr - && || operations                           */
3012 /*-----------------------------------------------------------------*/
3013 static operand *
3014 geniCodeLogicAndOr (ast *tree, int lvl)
3015 {
3016   iCode *ic;
3017   symbol *falseLabel = newiTempLabel (NULL);
3018   symbol *trueLabel  = newiTempLabel (NULL);
3019   symbol *exitLabel  = newiTempLabel (NULL);
3020   operand *op, *result, *condition;
3021
3022   /* AND_OP and OR_OP are no longer generated because of bug-905492.
3023      They can be reenabled by executing the following block. If you find
3024      a decent optimization you could start right here:
3025   */
3026 #if 0
3027   if (0)
3028     {
3029        operand *leftOp, *rightOp;
3030
3031        leftOp  = geniCodeRValue (ast2iCode (tree->left , lvl + 1), FALSE);
3032        rightOp = geniCodeRValue (ast2iCode (tree->right, lvl + 1), FALSE);
3033
3034        return geniCodeLogic (leftOp, rightOp, tree->opval.op);
3035     }
3036 #endif
3037
3038   /* generate two IFX for the '&&' or '||' op */
3039
3040   /* evaluate left operand */
3041   condition = ast2iCode (tree->left, lvl + 1);
3042   op = geniCodeRValue (condition, FALSE);
3043
3044   /* test left operand */
3045   if (tree->opval.op == AND_OP)
3046     ic = newiCodeCondition (op, NULL, falseLabel);
3047   else /* OR_OP */
3048     ic = newiCodeCondition (op, trueLabel, NULL);
3049   ADDTOCHAIN (ic);
3050   
3051   /* evaluate right operand */
3052   condition = ast2iCode (tree->right, lvl + 1);
3053   op = geniCodeRValue (condition, FALSE);
3054   
3055   /* test right operand */
3056   ic = newiCodeCondition (op, trueLabel, NULL);
3057   ADDTOCHAIN (ic);
3058   
3059   /* store 0 or 1 in result */
3060   result = newiTempOperand (newCharLink(), 1);
3061   
3062   geniCodeLabel (falseLabel);
3063   geniCodeAssign (result, operandFromLit (0), 0, 0);
3064   /* generate an unconditional goto */
3065   geniCodeGoto (exitLabel);
3066
3067   geniCodeLabel (trueLabel);
3068   geniCodeAssign (result, operandFromLit (1), 0, 0);
3069
3070   geniCodeLabel (exitLabel);
3071
3072   return result;
3073 }
3074
3075 /*-----------------------------------------------------------------*/
3076 /* geniCodeUnary - for a a generic unary operation                 */
3077 /*-----------------------------------------------------------------*/
3078 operand *
3079 geniCodeUnary (operand * op, int oper)
3080 {
3081   iCode *ic = newiCode (oper, op, NULL);
3082
3083   IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
3084   ADDTOCHAIN (ic);
3085   return IC_RESULT (ic);
3086 }
3087
3088 /*-----------------------------------------------------------------*/
3089 /* geniCodeConditional - geniCode for '?' ':' operation            */
3090 /*-----------------------------------------------------------------*/
3091 operand *
3092 geniCodeConditional (ast * tree,int lvl)
3093 {
3094   iCode *ic;
3095   symbol *falseLabel = newiTempLabel (NULL);
3096   symbol *exitLabel = newiTempLabel (NULL);
3097   operand *cond = ast2iCode (tree->left,lvl+1);
3098   operand *true, *false, *result;
3099
3100   ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
3101                           NULL, falseLabel);
3102   ADDTOCHAIN (ic);
3103
3104   true = ast2iCode (tree->right->left,lvl+1);
3105
3106   /* move the value to a new Operand */
3107   result = newiTempOperand (tree->right->ftype, 0);
3108   geniCodeAssign (result, geniCodeRValue (true, FALSE), 0, 0);
3109
3110   /* generate an unconditional goto */
3111   geniCodeGoto (exitLabel);
3112
3113   /* now for the right side */
3114   geniCodeLabel (falseLabel);
3115
3116   false = ast2iCode (tree->right->right,lvl+1);
3117   geniCodeAssign (result, geniCodeRValue (false, FALSE), 0, 0);
3118
3119   /* create the exit label */
3120   geniCodeLabel (exitLabel);
3121
3122   return result;
3123 }
3124
3125 /*-----------------------------------------------------------------*/
3126 /* geniCodeAssign - generate code for assignment                   */
3127 /*-----------------------------------------------------------------*/
3128 operand *
3129 geniCodeAssign (operand * left, operand * right, int nosupdate, int strictLval)
3130 {
3131   iCode *ic;
3132   sym_link *ltype = operandType (left);
3133   sym_link *rtype = operandType (right);
3134
3135   if (!left->isaddr && (!IS_ITEMP (left) || strictLval))
3136     {
3137       werror (E_LVALUE_REQUIRED, "assignment");
3138       return left;
3139     }
3140
3141   /* left is integral type and right is literal then
3142      check if the literal value is within bounds */
3143   if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
3144     {
3145       checkConstantRange(ltype, 
3146                          OP_VALUE(right), "= operation", 0);
3147     }
3148
3149   /* if the left & right type don't exactly match */
3150   /* if pointer set then make sure the check is
3151      done with the type & not the pointer */
3152   /* then cast rights type to left */
3153
3154   /* first check the type for pointer assignement */
3155   if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
3156       compareType (ltype, rtype) <= 0)
3157     {
3158       if (compareType (ltype->next, rtype) < 0)
3159         right = geniCodeCast (ltype->next, right, TRUE);
3160     }
3161   else if (compareType (ltype, rtype) < 0)
3162     right = geniCodeCast (ltype, right, TRUE);
3163
3164   /* If left is a true symbol & ! volatile
3165      create an assignment to temporary for
3166      the right & then assign this temporary
3167      to the symbol. This is SSA (static single
3168      assignment). Isn't it simple and folks have
3169      published mountains of paper on it */
3170   if (IS_TRUE_SYMOP (left) &&
3171       !isOperandVolatile (left, FALSE) &&
3172       isOperandGlobal (left))
3173     {
3174       symbol *sym = NULL;
3175
3176       if (IS_TRUE_SYMOP (right))
3177         sym = OP_SYMBOL (right);
3178       ic = newiCode ('=', NULL, right);
3179       IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
3180       SPIL_LOC (right) = sym;
3181       ADDTOCHAIN (ic);
3182     }
3183
3184   ic = newiCode ('=', NULL, right);
3185   IC_RESULT (ic) = left;
3186   ADDTOCHAIN (ic);
3187
3188   /* if left isgptr flag is set then support
3189      routine will be required */
3190   if (left->isGptr)
3191     ic->supportRtn = 1;
3192
3193   ic->nosupdate = nosupdate;
3194   return left;
3195 }
3196
3197 /*-----------------------------------------------------------------*/
3198 /* geniCodeDummyRead - generate code for dummy read                */
3199 /*-----------------------------------------------------------------*/
3200 static void
3201 geniCodeDummyRead (operand * op)
3202 {
3203   iCode *ic;
3204   sym_link *type = operandType (op);
3205
3206   if (!IS_VOLATILE(type))
3207     return;
3208     
3209   ic = newiCode (DUMMY_READ_VOLATILE, NULL, op);
3210   ADDTOCHAIN (ic);
3211
3212   ic->nosupdate = 1;
3213 }
3214
3215 /*-----------------------------------------------------------------*/
3216 /* geniCodeSEParms - generate code for side effecting fcalls       */
3217 /*-----------------------------------------------------------------*/
3218 static void 
3219 geniCodeSEParms (ast * parms,int lvl)
3220 {
3221   if (!parms)
3222     return;
3223
3224   if (parms->type == EX_OP && parms->opval.op == PARAM)
3225     {
3226       geniCodeSEParms (parms->left,lvl);
3227       geniCodeSEParms (parms->right,lvl);
3228       return;
3229     }
3230
3231   /* hack don't like this but too lazy to think of
3232      something better */
3233   if (IS_ADDRESS_OF_OP (parms))
3234     parms->left->lvalue = 1;
3235
3236   if (IS_CAST_OP (parms) &&
3237       IS_PTR (parms->ftype) &&
3238       IS_ADDRESS_OF_OP (parms->right))
3239     parms->right->left->lvalue = 1;
3240
3241   parms->opval.oprnd = 
3242     geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3243                 
3244   parms->type = EX_OPERAND;
3245   AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
3246                 SPEC_ARGREG(parms->ftype);
3247 }
3248
3249 /*-----------------------------------------------------------------*/
3250 /* geniCodeParms - generates parameters                            */
3251 /*-----------------------------------------------------------------*/
3252 value *
3253 geniCodeParms (ast * parms, value *argVals, int *stack, 
3254                sym_link * ftype, int lvl)
3255 {
3256   iCode *ic;
3257   operand *pval;
3258
3259   if (!parms)
3260     return argVals;
3261
3262   if (argVals==NULL) {
3263     // first argument
3264     argVals = FUNC_ARGS (ftype);
3265   }
3266
3267   /* if this is a param node then do the left & right */
3268   if (parms->type == EX_OP && parms->opval.op == PARAM)
3269     {
3270       argVals=geniCodeParms (parms->left, argVals, stack, ftype, lvl);
3271       argVals=geniCodeParms (parms->right, argVals, stack, ftype, lvl);
3272       return argVals;
3273     }
3274
3275   /* get the parameter value */
3276   if (parms->type == EX_OPERAND)
3277     pval = parms->opval.oprnd;
3278   else
3279     {
3280       /* maybe this else should go away ?? */
3281       /* hack don't like this but too lazy to think of
3282          something better */
3283       if (IS_ADDRESS_OF_OP (parms))
3284         parms->left->lvalue = 1;
3285
3286       if (IS_CAST_OP (parms) &&
3287           IS_PTR (parms->ftype) &&
3288           IS_ADDRESS_OF_OP (parms->right))
3289         parms->right->left->lvalue = 1;
3290
3291       pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3292     }
3293
3294   /* if register parm then make it a send */
3295   if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(ftype)) ||
3296       IFFUNC_ISBUILTIN(ftype))
3297     {
3298       ic = newiCode (SEND, pval, NULL);
3299       ic->argreg = SPEC_ARGREG(parms->etype);
3300       ic->builtinSEND = FUNC_ISBUILTIN(ftype);
3301       ADDTOCHAIN (ic);
3302     }
3303   else
3304     {
3305       /* now decide whether to push or assign */
3306       if (!(options.stackAuto || IFFUNC_ISREENT (ftype)))
3307         {
3308
3309           /* assign */
3310           operand *top = operandFromSymbol (argVals->sym);
3311           /* clear useDef and other bitVectors */
3312           OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
3313           geniCodeAssign (top, pval, 1, 0);
3314         }
3315       else
3316         {
3317           sym_link *p = operandType (pval);
3318           /* push */
3319           ic = newiCode (IPUSH, pval, NULL);
3320           ic->parmPush = 1;
3321           /* update the stack adjustment */
3322           *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
3323           ADDTOCHAIN (ic);
3324         }
3325     }
3326
3327   argVals=argVals->next;
3328   return argVals;
3329 }
3330
3331 /*-----------------------------------------------------------------*/
3332 /* geniCodeCall - generates temp code for calling                  */
3333 /*-----------------------------------------------------------------*/
3334 operand *
3335 geniCodeCall (operand * left, ast * parms,int lvl)
3336 {
3337   iCode *ic;
3338   operand *result;
3339   sym_link *type, *etype;
3340   sym_link *ftype;
3341   int stack = 0;
3342
3343   if (!IS_FUNC(OP_SYMBOL(left)->type) && 
3344       !IS_CODEPTR(OP_SYMBOL(left)->type)) {
3345     werror (E_FUNCTION_EXPECTED);
3346     return operandFromValue(valueFromLit(0));
3347   }
3348
3349   /* take care of parameters with side-effecting
3350      function calls in them, this is required to take care
3351      of overlaying function parameters */
3352   geniCodeSEParms (parms,lvl);
3353
3354   ftype = operandType (left);
3355   if (IS_CODEPTR (ftype))
3356     ftype = ftype->next;
3357     
3358   /* first the parameters */
3359   geniCodeParms (parms, NULL, &stack, ftype, lvl);
3360
3361   /* now call : if symbol then pcall */
3362   if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
3363     ic = newiCode (PCALL, left, NULL);
3364   } else {
3365     ic = newiCode (CALL, left, NULL);
3366   }
3367
3368   type = copyLinkChain (ftype->next);
3369   etype = getSpec (type);
3370   SPEC_EXTR (etype) = 0;
3371   IC_RESULT (ic) = result = newiTempOperand (type, 1);
3372
3373   ADDTOCHAIN (ic);
3374
3375   /* stack adjustment after call */
3376   ic->parmBytes = stack;
3377
3378   return result;
3379 }
3380
3381 /*-----------------------------------------------------------------*/
3382 /* geniCodeReceive - generate intermediate code for "receive"      */
3383 /*-----------------------------------------------------------------*/
3384 static void 
3385 geniCodeReceive (value * args)
3386 {
3387   unsigned char paramByteCounter = 0;
3388
3389   /* for all arguments that are passed in registers */
3390   while (args)
3391     {
3392       int first = 1;
3393       if (IS_REGPARM (args->etype))
3394         {
3395           operand *opr = operandFromValue (args);
3396           operand *opl;
3397           symbol *sym = OP_SYMBOL (opr);
3398           iCode *ic;
3399
3400           /* we will use it after all optimizations
3401              and before liveRange calculation */
3402           if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
3403             {
3404
3405               if ((IN_FARSPACE (SPEC_OCLS (sym->etype)) && !TARGET_IS_HC08) &&
3406                   options.stackAuto == 0 &&
3407                   (!(options.model == MODEL_FLAT24)) )
3408                 {
3409                 }
3410               else
3411                 {
3412                   opl = newiTempOperand (args->type, 0);
3413                   sym->reqv = opl;
3414                   sym->reqv->key = sym->key;
3415                   OP_SYMBOL (sym->reqv)->key = sym->key;
3416                   OP_SYMBOL (sym->reqv)->isreqv = 1;
3417                   OP_SYMBOL (sym->reqv)->islocal = 0;
3418                   SPIL_LOC (sym->reqv) = sym;
3419                 }
3420             }
3421
3422           ic = newiCode (RECEIVE, NULL, NULL);    
3423           ic->argreg = SPEC_ARGREG(args->etype);
3424           if (first) {
3425               currFunc->recvSize = getSize (sym->type);
3426               first = 0;
3427           }
3428           IC_RESULT (ic) = opr;
3429           
3430           /* misuse of parmBytes (normally used for functions) 
3431            * to save estimated stack position of this argument.
3432            * Normally this should be zero for RECEIVE iCodes.
3433            * No idea if this causes side effects on other ports. - dw
3434            */
3435           ic->parmBytes = paramByteCounter;
3436           
3437           /* what stack position do we have? */
3438           paramByteCounter += getSize (sym->type);
3439
3440           ADDTOCHAIN (ic);
3441         }
3442
3443       args = args->next;
3444     }
3445 }
3446
3447 /*-----------------------------------------------------------------*/
3448 /* geniCodeFunctionBody - create the function body                 */
3449 /*-----------------------------------------------------------------*/
3450 void 
3451 geniCodeFunctionBody (ast * tree,int lvl)
3452 {
3453   iCode *ic;
3454   operand *func;
3455   sym_link *fetype;
3456   int savelineno;
3457
3458   /* reset the auto generation */
3459   /* numbers */
3460   iTempNum = 0;
3461   iTempLblNum = 0;
3462   operandKey = 0;
3463   iCodeKey = 0;
3464   func = ast2iCode (tree->left,lvl+1);
3465   fetype = getSpec (operandType (func));
3466
3467   savelineno = lineno;
3468   lineno = OP_SYMBOL (func)->lineDef;
3469   /* create an entry label */
3470   geniCodeLabel (entryLabel);
3471   lineno = savelineno;
3472
3473   /* create a proc icode */
3474   ic = newiCode (FUNCTION, func, NULL);
3475   lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3476   ic->tree = tree;
3477
3478   ADDTOCHAIN (ic);
3479
3480   /* for all parameters that are passed
3481      on registers add a "receive" */
3482   geniCodeReceive (tree->values.args);
3483
3484   /* generate code for the body */
3485   ast2iCode (tree->right,lvl+1);
3486
3487   /* create a label for return */
3488   geniCodeLabel (returnLabel);
3489
3490   /* now generate the end proc */
3491   ic = newiCode (ENDFUNCTION, func, NULL);
3492   ic->tree = tree;
3493   ADDTOCHAIN (ic);
3494   return;
3495 }
3496
3497 /*-----------------------------------------------------------------*/
3498 /* geniCodeReturn - gen icode for 'return' statement               */
3499 /*-----------------------------------------------------------------*/
3500 void 
3501 geniCodeReturn (operand * op)
3502 {
3503   iCode *ic;
3504
3505   /* if the operand is present force an rvalue */
3506   if (op)
3507     op = geniCodeRValue (op, FALSE);
3508
3509   ic = newiCode (RETURN, op, NULL);
3510   ADDTOCHAIN (ic);
3511 }
3512
3513 /*-----------------------------------------------------------------*/
3514 /* geniCodeIfx - generates code for extended if statement          */
3515 /*-----------------------------------------------------------------*/
3516 void 
3517 geniCodeIfx (ast * tree,int lvl)
3518 {
3519   iCode *ic;
3520   operand *condition = ast2iCode (tree->left,lvl+1);
3521   sym_link *cetype;
3522
3523   /* if condition is null then exit */
3524   if (!condition)
3525     goto exit;
3526   else
3527     condition = geniCodeRValue (condition, FALSE);
3528
3529   cetype = getSpec (operandType (condition));
3530   /* if the condition is a literal */
3531   if (IS_LITERAL (cetype))
3532     {
3533       if (floatFromVal (condition->operand.valOperand))
3534         {
3535           if (tree->trueLabel)
3536             geniCodeGoto (tree->trueLabel);
3537           else
3538             assert (0);
3539         }
3540       else
3541         {
3542           if (tree->falseLabel)
3543             geniCodeGoto (tree->falseLabel);
3544           else
3545             assert (0);
3546         }
3547       goto exit;
3548     }
3549
3550   if (tree->trueLabel)
3551     {
3552       ic = newiCodeCondition (condition,
3553                               tree->trueLabel,
3554                               NULL);
3555       ADDTOCHAIN (ic);
3556
3557       if (tree->falseLabel)
3558         geniCodeGoto (tree->falseLabel);
3559     }
3560   else
3561     {
3562       ic = newiCodeCondition (condition,
3563                               NULL,
3564                               tree->falseLabel);
3565       ADDTOCHAIN (ic);
3566     }
3567
3568 exit:
3569   ast2iCode (tree->right,lvl+1);
3570 }
3571
3572 /*-----------------------------------------------------------------*/
3573 /* geniCodeJumpTable - tries to create a jump table for switch     */
3574 /*-----------------------------------------------------------------*/
3575 int 
3576 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3577 {
3578   int min, max, cnt = 1;
3579   int i, t;
3580   value *vch;
3581   iCode *ic;
3582   operand *boundary;
3583   symbol *falseLabel;
3584   set *labels = NULL;
3585   int needRangeCheck = !optimize.noJTabBoundary
3586                        || tree->values.switchVals.swDefault;
3587   sym_link *cetype = getSpec (operandType (cond));
3588   int sizeofMinCost, sizeofZeroMinCost, sizeofMaxCost;
3589   int sizeofMatchJump, sizeofJumpTable;
3590   int sizeIndex;
3591
3592   if (!tree || !caseVals)
3593     return 0;
3594
3595   /* the criteria for creating a jump table is */
3596   /* all integer numbers between the maximum & minimum must */
3597   /* be present , the maximum value should not exceed 255 */
3598   /* If not all integer numbers are present the algorithm */
3599   /* inserts jumps to the default label for the missing numbers */
3600   /* and decides later whether it is worth it */
3601   min = (int) floatFromVal (vch = caseVals);
3602
3603   while (vch->next)
3604     {
3605       cnt++;
3606       vch = vch->next;
3607     }
3608   max = (int) floatFromVal (vch);
3609
3610   /* Exit if the range is too large to handle with a jump table. */
3611   if (1 + max - min > port->jumptableCost.maxCount)
3612     return 0;
3613
3614   switch (getSize (operandType (cond)))
3615     {
3616     case 1: sizeIndex = 0; break;
3617     case 2: sizeIndex = 1; break;
3618     case 4: sizeIndex = 2; break;
3619     default: return 0;
3620     }
3621   
3622   /* Compute the size cost of the range check and subtraction. */
3623   sizeofMinCost = 0;
3624   sizeofZeroMinCost = 0;
3625   sizeofMaxCost = 0;
3626   if (needRangeCheck)
3627     {
3628       if (!(min==0 && IS_UNSIGNED (cetype)))
3629         sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3630       if (!IS_UNSIGNED (cetype))
3631         sizeofZeroMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3632       sizeofMaxCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3633     }
3634   if (min)
3635     sizeofMinCost += port->jumptableCost.sizeofSubtract;
3636   
3637   /* If the size cost of handling a non-zero minimum exceeds the */
3638   /* cost of extending the range down to zero, then it might be */
3639   /* better to extend the range to zero. */
3640   if (min > 0 && (sizeofMinCost-sizeofZeroMinCost)
3641                  >= (min * port->jumptableCost.sizeofElement))
3642     {
3643       /* Only extend the jump table if it would still be manageable. */
3644       if (1 + max <= port->jumptableCost.maxCount)
3645         {
3646           min = 0;
3647           if (IS_UNSIGNED (cetype))
3648             sizeofMinCost = 0;
3649           else
3650             sizeofMinCost = port->jumptableCost.sizeofRangeCompare[sizeIndex];
3651         }
3652     }
3653     
3654   /* Compute the total size cost of a jump table. */
3655   sizeofJumpTable = (1 + max - min) * port->jumptableCost.sizeofElement
3656                      + port->jumptableCost.sizeofDispatch
3657                      + sizeofMinCost + sizeofMaxCost;
3658
3659   /* Compute the total size cost of a match & jump sequence */
3660   sizeofMatchJump = cnt * port->jumptableCost.sizeofMatchJump[sizeIndex];
3661
3662   /* If the size cost of the jump table is uneconomical then exit */
3663   if (sizeofMatchJump <  sizeofJumpTable)
3664     return 0;
3665
3666   /* The jump table is preferable. */
3667   
3668   /* First, a label for the default or missing cases. */
3669   if (tree->values.switchVals.swDefault)
3670     {
3671       SNPRINTF (buffer, sizeof(buffer),
3672                 "_default_%d",
3673                 tree->values.switchVals.swNum);
3674     }
3675   else
3676     {
3677       SNPRINTF (buffer, sizeof(buffer),
3678                 "_swBrk_%d",
3679                 tree->values.switchVals.swNum);
3680     }
3681   falseLabel = newiTempLabel (buffer);
3682
3683   /* Build the list of labels for the jump table. */
3684   vch = caseVals;
3685   t = (int) floatFromVal (vch);
3686   for (i=min; i<=max; i++)
3687     {
3688       if (vch && t==i)
3689         {
3690           /* Explicit case: make a new label for it. */
3691           SNPRINTF (buffer, sizeof(buffer), 
3692                     "_case_%d_%d",
3693                     tree->values.switchVals.swNum,
3694                     i);
3695           addSet (&labels, newiTempLabel (buffer));
3696           vch = vch->next;
3697           if (vch)
3698             t = (int) floatFromVal (vch);
3699         }
3700       else
3701         {
3702           /* Implicit case: use the default label. */
3703           addSet (&labels, falseLabel);
3704         }
3705     }
3706
3707   /* first we rule out the boundary conditions */
3708   /* if only optimization says so */
3709   if (needRangeCheck)
3710     {
3711       sym_link *cetype = getSpec (operandType (cond));
3712       /* no need to check the lower bound if
3713          the condition is unsigned & minimum value is zero */
3714       if (!(min == 0 && IS_UNSIGNED (cetype)))
3715         {
3716           boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3717           ic = newiCodeCondition (boundary, falseLabel, NULL);
3718           ADDTOCHAIN (ic);
3719         }
3720
3721       /* now for upper bounds */
3722       boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3723       ic = newiCodeCondition (boundary, falseLabel, NULL);
3724       ADDTOCHAIN (ic);
3725     }
3726
3727   /* if the min is not zero then we no make it zero */
3728   if (min)
3729     {
3730       cond = geniCodeSubtract (cond, operandFromLit (min), RESULT_TYPE_CHAR);
3731       if (!IS_LITERAL(getSpec(operandType(cond))))
3732         setOperandType (cond, UCHARTYPE);
3733     }
3734
3735   /* now create the jumptable */
3736   ic = newiCode (JUMPTABLE, NULL, NULL);
3737   IC_JTCOND (ic) = cond;
3738   IC_JTLABELS (ic) = labels;
3739   ADDTOCHAIN (ic);
3740   return 1;
3741 }
3742
3743 /*-----------------------------------------------------------------*/
3744 /* geniCodeSwitch - changes a switch to a if statement             */
3745 /*-----------------------------------------------------------------*/
3746 void
3747 geniCodeSwitch (ast * tree,int lvl)
3748 {
3749   iCode *ic;
3750   operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3751   value *caseVals = tree->values.switchVals.swVals;
3752   symbol *trueLabel, *falseLabel;
3753       
3754   /* If the condition is a literal, then just jump to the */
3755   /* appropriate case label. */
3756   if (IS_LITERAL(getSpec(operandType(cond))))
3757     {
3758       int switchVal, caseVal;
3759       
3760       switchVal = (int) floatFromVal (cond->operand.valOperand);
3761       while (caseVals)
3762         {
3763           caseVal = (int) floatFromVal (caseVals);
3764           if (caseVal == switchVal)
3765             {
3766               SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3767                         tree->values.switchVals.swNum, caseVal);
3768               trueLabel = newiTempLabel (buffer);
3769               geniCodeGoto (trueLabel);
3770               goto jumpTable;
3771             }
3772           caseVals = caseVals->next;
3773         }
3774       goto defaultOrBreak;
3775     }
3776   
3777   /* If cond is volatile, it might change while we are trying to */
3778   /* find the matching case. To avoid this possibility, make a   */
3779   /* non-volatile copy to use instead. */
3780   if (IS_OP_VOLATILE (cond))
3781     {
3782       operand * newcond;
3783       iCode * ic;
3784       
3785       newcond = newiTempOperand (operandType (cond), TRUE);
3786       newcond->isvolatile = 0;
3787       ic = newiCode ('=', NULL, cond);
3788       IC_RESULT (ic) = newcond;
3789       ADDTOCHAIN (ic);
3790       cond = newcond;
3791     }
3792
3793   /* if we can make this a jump table */
3794   if (geniCodeJumpTable (cond, caseVals, tree))
3795     goto jumpTable;             /* no need for the comparison */
3796
3797   /* for the cases defined do */
3798   while (caseVals)
3799     {
3800
3801       operand *compare = geniCodeLogic (cond,
3802                                         operandFromValue (caseVals),
3803                                         EQ_OP);
3804
3805       SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3806                tree->values.switchVals.swNum,
3807                (int) floatFromVal (caseVals));
3808       trueLabel = newiTempLabel (buffer);
3809
3810       ic = newiCodeCondition (compare, trueLabel, NULL);
3811       ADDTOCHAIN (ic);
3812       caseVals = caseVals->next;
3813     }
3814
3815
3816 defaultOrBreak:
3817   /* if default is present then goto break else break */
3818   if (tree->values.switchVals.swDefault)
3819     {
3820         SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3821     }
3822   else
3823     {
3824         SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3825     }
3826
3827   falseLabel = newiTempLabel (buffer);
3828   geniCodeGoto (falseLabel);
3829
3830 jumpTable:
3831   ast2iCode (tree->right,lvl+1);
3832 }
3833
3834 /*-----------------------------------------------------------------*/
3835 /* geniCodeInline - intermediate code for inline assembler         */
3836 /*-----------------------------------------------------------------*/
3837 static void 
3838 geniCodeInline (ast * tree)
3839 {
3840   iCode *ic;
3841
3842   ic = newiCode (INLINEASM, NULL, NULL);
3843   IC_INLINE (ic) = tree->values.inlineasm;
3844   ADDTOCHAIN (ic);
3845 }
3846
3847 /*-----------------------------------------------------------------*/
3848 /* geniCodeArrayInit - intermediate code for array initializer     */
3849 /*-----------------------------------------------------------------*/
3850 static void
3851 geniCodeArrayInit (ast * tree, operand *array)
3852 {
3853   iCode *ic;
3854
3855   if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3856     ic = newiCode (ARRAYINIT, array, NULL);
3857     IC_ARRAYILIST (ic) = tree->values.constlist;
3858   } else {
3859     operand *left=newOperand(), *right=newOperand();
3860     left->type=right->type=SYMBOL;
3861     OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3862     OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3863     ic = newiCode (ARRAYINIT, left, right);
3864   }
3865   ADDTOCHAIN (ic);
3866 }
3867         
3868 /*-----------------------------------------------------------------*/
3869 /* geniCodeCritical - intermediate code for a critical statement   */
3870 /*-----------------------------------------------------------------*/
3871 static void 
3872 geniCodeCritical (ast *tree, int lvl)
3873 {
3874   iCode *ic;
3875   operand *op = NULL;
3876   sym_link *type;
3877
3878   if (!options.stackAuto)
3879     {
3880       type = newLink(SPECIFIER);
3881       SPEC_VOLATILE(type) = 1;
3882       SPEC_NOUN(type) = V_BIT;
3883       SPEC_SCLS(type) = S_BIT;
3884       SPEC_BLEN(type) = 1;
3885       SPEC_BSTR(type) = 0;
3886       op = newiTempOperand(type, 1);
3887     }
3888
3889   /* If op is NULL, the original interrupt state will saved on */
3890   /* the stack. Otherwise, it will be saved in op. */
3891   
3892   /* Generate a save of the current interrupt state & disable */
3893   ic = newiCode (CRITICAL, NULL, NULL);
3894   IC_RESULT (ic) = op;
3895   ADDTOCHAIN (ic);
3896   
3897   /* Generate the critical code sequence */
3898   if (tree->left && tree->left->type == EX_VALUE)
3899     geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
3900   else
3901     ast2iCode (tree->left,lvl+1);
3902   
3903   /* Generate a restore of the original interrupt state */
3904   ic = newiCode (ENDCRITICAL, NULL, op);
3905   ADDTOCHAIN (ic);
3906 }
3907
3908 /*-----------------------------------------------------------------*/
3909 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some      */
3910 /* particular case. Ie : assigning or dereferencing array or ptr   */
3911 /*-----------------------------------------------------------------*/
3912 set * lvaluereqSet = NULL;
3913 typedef struct lvalItem
3914   {
3915     int req;
3916     int lvl;
3917   }
3918 lvalItem;
3919
3920 /*-----------------------------------------------------------------*/
3921 /* addLvaluereq - add a flag for lvalreq for current ast level     */
3922 /*-----------------------------------------------------------------*/
3923 void addLvaluereq(int lvl)
3924 {
3925   lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3926   lpItem->req=1;
3927   lpItem->lvl=lvl;
3928   addSetHead(&lvaluereqSet,lpItem);
3929
3930 }
3931 /*-----------------------------------------------------------------*/
3932 /* delLvaluereq - del a flag for lvalreq for current ast level     */
3933 /*-----------------------------------------------------------------*/
3934 void delLvaluereq()
3935 {
3936   lvalItem * lpItem;
3937   lpItem = getSet(&lvaluereqSet);
3938   if(lpItem) Safe_free(lpItem);
3939 }
3940 /*-----------------------------------------------------------------*/
3941 /* clearLvaluereq - clear lvalreq flag                             */
3942 /*-----------------------------------------------------------------*/
3943 void clearLvaluereq()
3944 {
3945   lvalItem * lpItem;
3946   lpItem = peekSet(lvaluereqSet);
3947   if(lpItem) lpItem->req = 0;
3948 }
3949 /*-----------------------------------------------------------------*/
3950 /* getLvaluereq - get the last lvalreq level                       */
3951 /*-----------------------------------------------------------------*/
3952 int getLvaluereqLvl()
3953 {
3954   lvalItem * lpItem;
3955   lpItem = peekSet(lvaluereqSet);
3956   if(lpItem) return lpItem->lvl;
3957   return 0;
3958 }
3959 /*-----------------------------------------------------------------*/
3960 /* isLvaluereq - is lvalreq valid for this level ?                 */
3961 /*-----------------------------------------------------------------*/
3962 int isLvaluereq(int lvl)
3963 {
3964   lvalItem * lpItem;
3965   lpItem = peekSet(lvaluereqSet);
3966   if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3967   return 0;
3968 }
3969
3970 /*-----------------------------------------------------------------*/
3971 /* ast2iCode - creates an icodeList from an ast                    */
3972 /*-----------------------------------------------------------------*/
3973 operand *
3974 ast2iCode (ast * tree,int lvl)
3975 {
3976   operand *left = NULL;
3977   operand *right = NULL;
3978   if (!tree)
3979     return NULL;
3980
3981   /* set the global variables for filename & line number */
3982   if (tree->filename)
3983     filename = tree->filename;
3984   if (tree->lineno)
3985     lineno = tree->lineno;
3986   if (tree->block)
3987     block = tree->block;
3988   if (tree->level)
3989     scopeLevel = tree->level;
3990   if (tree->seqPoint)
3991     seqPoint = tree->seqPoint;
3992
3993   if (tree->type == EX_VALUE)
3994     return operandFromValue (tree->opval.val);
3995
3996   if (tree->type == EX_LINK)
3997     return operandFromLink (tree->opval.lnk);
3998
3999   /* if we find a nullop */
4000   if (tree->type == EX_OP &&
4001      (tree->opval.op == NULLOP ||
4002      tree->opval.op == BLOCK))
4003     {
4004       if (tree->left && tree->left->type == EX_VALUE)
4005         geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
4006       else
4007         ast2iCode (tree->left,lvl+1);
4008       if (tree->right && tree->right->type == EX_VALUE)
4009         geniCodeDummyRead (ast2iCode (tree->right,lvl+1));
4010       else
4011         ast2iCode (tree->right,lvl+1);
4012       return NULL;
4013     }
4014
4015   /* special cases for not evaluating */
4016   if (tree->opval.op != ':' &&
4017       tree->opval.op != '?' &&
4018       tree->opval.op != CALL &&
4019       tree->opval.op != IFX &&
4020       tree->opval.op != AND_OP &&
4021       tree->opval.op != OR_OP &&
4022       tree->opval.op != LABEL &&
4023       tree->opval.op != GOTO &&
4024       tree->opval.op != SWITCH &&
4025       tree->opval.op != FUNCTION &&
4026       tree->opval.op != INLINEASM &&
4027       tree->opval.op != CRITICAL)
4028     {
4029
4030         if (IS_ASSIGN_OP (tree->opval.op) ||
4031            IS_DEREF_OP (tree) ||
4032            (tree->opval.op == '&' && !tree->right) ||
4033            tree->opval.op == PTR_OP)
4034           {
4035             addLvaluereq(lvl);
4036             if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
4037                (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
4038               clearLvaluereq();
4039
4040             left = operandFromAst (tree->left,lvl);
4041             delLvaluereq();
4042             if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
4043               left = geniCodeRValue (left, TRUE);
4044           }
4045         else
4046           {
4047             left = operandFromAst (tree->left,lvl);
4048           }
4049         if (tree->opval.op == INC_OP ||
4050             tree->opval.op == DEC_OP)
4051           {
4052             addLvaluereq(lvl);
4053             right = operandFromAst (tree->right,lvl);
4054             delLvaluereq();
4055           }
4056         else
4057           {
4058             right = operandFromAst (tree->right,lvl);
4059           }
4060       }
4061
4062   /* now depending on the type of operand */
4063   /* this will be a biggy                 */
4064   switch (tree->opval.op)
4065     {
4066
4067     case '[':                   /* array operation */
4068       {
4069         //sym_link *ltype = operandType (left);
4070         //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
4071         left = geniCodeRValue (left, FALSE);
4072         right = geniCodeRValue (right, TRUE);
4073       }
4074
4075       return geniCodeArray (left, right,lvl);
4076
4077     case '.':                   /* structure dereference */
4078       if (IS_PTR (operandType (left)))
4079         left = geniCodeRValue (left, TRUE);
4080       else
4081         left = geniCodeRValue (left, FALSE);
4082
4083       return geniCodeStruct (left, right, tree->lvalue);
4084
4085     case PTR_OP:                /* structure pointer dereference */
4086       {
4087         sym_link *pType;
4088         pType = operandType (left);
4089         left = geniCodeRValue (left, TRUE);
4090
4091         setOClass (pType, getSpec (operandType (left)));
4092       }
4093
4094       return geniCodeStruct (left, right, tree->lvalue);
4095
4096     case INC_OP:                /* increment operator */
4097       if (left)
4098         return geniCodePostInc (left);
4099       else
4100         return geniCodePreInc (right, tree->lvalue);
4101
4102     case DEC_OP:                /* decrement operator */
4103       if (left)
4104         return geniCodePostDec (left);
4105       else
4106         return geniCodePreDec (right, tree->lvalue);
4107
4108     case '&':                   /* bitwise and or address of operator */
4109       if (right)
4110         {                       /* this is a bitwise operator   */
4111           left = geniCodeRValue (left, FALSE);
4112           right = geniCodeRValue (right, FALSE);
4113           return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
4114         }
4115       else
4116         return geniCodeAddressOf (left);
4117
4118     case '|':                   /* bitwise or & xor */
4119     case '^':
4120       return geniCodeBitwise (geniCodeRValue (left, FALSE),
4121                               geniCodeRValue (right, FALSE),
4122                               tree->opval.op,
4123                               tree->ftype);
4124
4125     case '/':
4126       return geniCodeDivision (geniCodeRValue (left, FALSE),
4127                                geniCodeRValue (right, FALSE),
4128                                getResultTypeFromType (tree->ftype));
4129
4130     case '%':
4131       return geniCodeModulus (geniCodeRValue (left, FALSE),
4132                               geniCodeRValue (right, FALSE),
4133                               getResultTypeFromType (tree->ftype));
4134     case '*':
4135       if (right)
4136         return geniCodeMultiply (geniCodeRValue (left, FALSE),
4137                                  geniCodeRValue (right, FALSE),
4138                                  getResultTypeFromType (tree->ftype));
4139       else
4140         return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
4141
4142     case '-':
4143       if (right)
4144         return geniCodeSubtract (geniCodeRValue (left, FALSE),
4145                                  geniCodeRValue (right, FALSE),
4146                                  getResultTypeFromType (tree->ftype));
4147       else
4148         return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
4149
4150     case '+':
4151       if (right)
4152         return geniCodeAdd (geniCodeRValue (left, FALSE),
4153                             geniCodeRValue (right, FALSE),
4154                             getResultTypeFromType (tree->ftype),
4155                             lvl);
4156       else
4157         return geniCodeRValue (left, FALSE);    /* unary '+' has no meaning */
4158
4159     case LEFT_OP:
4160       return geniCodeLeftShift (geniCodeRValue (left, FALSE),
4161                                 geniCodeRValue (right, FALSE),
4162                                 getResultTypeFromType (tree->ftype));
4163
4164     case RIGHT_OP:
4165       return geniCodeRightShift (geniCodeRValue (left, FALSE),
4166                                  geniCodeRValue (right, FALSE));
4167     case CAST:
4168 #if 0 // this indeed needs a second thought
4169       {
4170         operand *op;
4171
4172         // let's keep this simple: get the rvalue we need
4173         op=geniCodeRValue (right, FALSE);
4174         // now cast it to whatever we want
4175         op=geniCodeCast (operandType(left), op, FALSE);
4176         // if this is going to be used as an lvalue, make it so
4177         if (tree->lvalue) {
4178           op->isaddr=1;
4179         }
4180         return op;
4181       }
4182 #else // bug #604575, is it a bug ????
4183       return geniCodeCast (operandType (left),
4184                            geniCodeRValue (right, FALSE), FALSE);
4185 #endif
4186
4187     case '~':
4188     case RRC:
4189     case RLC:
4190     case SWAP:
4191       return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4192
4193     case '!':
4194     case GETHBIT:
4195       {
4196         operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
4197         setOperandType (op, UCHARTYPE);
4198         return op;
4199       }
4200     case AND_OP:
4201     case OR_OP:
4202       return geniCodeLogicAndOr (tree, lvl);
4203     case '>':
4204     case '<':
4205     case LE_OP:
4206     case GE_OP:
4207     case EQ_OP:
4208     case NE_OP:
4209       /* different compilers (even different gccs) evaluate
4210          the two calls in a different order. to get the same
4211          result on all machines we've to specify a clear sequence.
4212       return geniCodeLogic (geniCodeRValue (left, FALSE),
4213                             geniCodeRValue (right, FALSE),
4214                             tree->opval.op);
4215       */
4216       {
4217         operand *leftOp, *rightOp;
4218
4219         leftOp  = geniCodeRValue (left , FALSE);
4220         rightOp = geniCodeRValue (right, FALSE);
4221
4222         return geniCodeLogic (leftOp, rightOp, tree->opval.op);
4223       }
4224     case '?':
4225       return geniCodeConditional (tree,lvl);
4226
4227     case SIZEOF:
4228       return operandFromLit (getSize (tree->right->ftype));
4229
4230     case '=':
4231       {
4232         sym_link *rtype = operandType (right);
4233         sym_link *ltype = operandType (left);
4234         if (IS_PTR (rtype) && IS_ITEMP (right)
4235             && right->isaddr && compareType (rtype->next, ltype) == 1)
4236           right = geniCodeRValue (right, TRUE);
4237         else
4238           right = geniCodeRValue (right, FALSE);
4239
4240         geniCodeAssign (left, right, 0, 1);
4241         return right;
4242       }
4243     case MUL_ASSIGN:
4244       return
4245         geniCodeAssign (left,
4246                 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
4247                                                   FALSE),
4248                                   geniCodeRValue (right, FALSE), 
4249                                   getResultTypeFromType (tree->ftype)),
4250                         0, 1);
4251
4252     case DIV_ASSIGN:
4253       return
4254         geniCodeAssign (left,
4255                 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
4256                                                   FALSE),
4257                                   geniCodeRValue (right, FALSE),
4258                                   getResultTypeFromType (tree->ftype)),
4259                         0, 1);
4260     case MOD_ASSIGN:
4261       return
4262         geniCodeAssign (left,
4263                  geniCodeModulus (geniCodeRValue (operandFromOperand (left),
4264                                                   FALSE),
4265                                   geniCodeRValue (right, FALSE),
4266                                   getResultTypeFromType (tree->ftype)),
4267                         0, 1);
4268     case ADD_ASSIGN:
4269       {
4270         sym_link *rtype = operandType (right);
4271         sym_link *ltype = operandType (left);
4272         if (IS_PTR (rtype) && IS_ITEMP (right)
4273             && right->isaddr && compareType (rtype->next, ltype) == 1)
4274           right = geniCodeRValue (right, TRUE);
4275         else
4276           right = geniCodeRValue (right, FALSE);
4277
4278
4279         return geniCodeAssign (left,
4280                      geniCodeAdd (geniCodeRValue (operandFromOperand (left),
4281                                                   FALSE),
4282                                   right,
4283                                   getResultTypeFromType (tree->ftype),
4284                                   lvl),
4285                                0, 1);
4286       }
4287     case SUB_ASSIGN:
4288       {
4289         sym_link *rtype = operandType (right);
4290         sym_link *ltype = operandType (left);
4291         if (IS_PTR (rtype) && IS_ITEMP (right)
4292             && right->isaddr && compareType (rtype->next, ltype) == 1)
4293           {
4294             right = geniCodeRValue (right, TRUE);
4295           }
4296         else
4297           {
4298             right = geniCodeRValue (right, FALSE);
4299           }
4300         return
4301           geniCodeAssign (left,
4302                 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
4303                                                   FALSE),
4304                                   right,
4305                                   getResultTypeFromType (tree->ftype)),
4306                           0, 1);
4307       }
4308     case LEFT_ASSIGN:
4309       return
4310         geniCodeAssign (left,
4311                 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
4312                                                    ,FALSE),
4313                                    geniCodeRValue (right, FALSE),
4314                                    getResultTypeFromType (tree->ftype)),
4315                         0, 1);
4316     case RIGHT_ASSIGN:
4317       return
4318         geniCodeAssign (left,
4319                geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
4320                                                    ,FALSE),
4321                                    geniCodeRValue (right, FALSE)), 0, 1);
4322     case AND_ASSIGN:
4323       return
4324         geniCodeAssign (left,
4325                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4326                                                   FALSE),
4327                                   geniCodeRValue (right, FALSE),
4328                                   BITWISEAND,
4329                                   operandType (left)), 0, 1);
4330     case XOR_ASSIGN:
4331       return
4332         geniCodeAssign (left,
4333                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
4334                                                   FALSE),
4335                                   geniCodeRValue (right, FALSE),
4336                                   '^',
4337                                   operandType (left)), 0, 1);
4338     case OR_ASSIGN:
4339       return
4340         geniCodeAssign (left,
4341                   geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
4342                                                    ,FALSE),
4343                                    geniCodeRValue (right, FALSE),
4344                                    '|',
4345                                    operandType (left)), 0, 1);
4346     case ',':
4347       return geniCodeRValue (right, FALSE);
4348
4349     case CALL:
4350       return geniCodeCall (ast2iCode (tree->left,lvl+1),
4351                            tree->right,lvl);
4352     case LABEL:
4353       geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
4354       return ast2iCode (tree->right,lvl+1);
4355
4356     case GOTO:
4357       geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
4358       return ast2iCode (tree->right,lvl+1);
4359
4360     case FUNCTION:
4361       geniCodeFunctionBody (tree,lvl);
4362       return NULL;
4363
4364     case RETURN:
4365       geniCodeReturn (right);
4366       return NULL;
4367
4368     case IFX:
4369       geniCodeIfx (tree,lvl);
4370       return NULL;
4371
4372     case SWITCH:
4373       geniCodeSwitch (tree,lvl);
4374       return NULL;
4375
4376     case INLINEASM:
4377       geniCodeInline (tree);
4378       return NULL;
4379         
4380     case ARRAYINIT:
4381         geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
4382         return NULL;
4383     
4384     case CRITICAL:
4385         geniCodeCritical (tree, lvl);
4386     }
4387
4388   return NULL;
4389 }
4390
4391 /*-----------------------------------------------------------------*/
4392 /* reverseICChain - gets from the list and creates a linkedlist    */
4393 /*-----------------------------------------------------------------*/
4394 iCode *
4395 reverseiCChain ()
4396 {
4397   iCode *loop = NULL;
4398   iCode *prev = NULL;
4399
4400   while ((loop = getSet (&iCodeChain)))
4401     {
4402       loop->next = prev;
4403       if (prev)
4404         prev->prev = loop;
4405       prev = loop;
4406     }
4407
4408   return prev;
4409 }
4410
4411
4412 /*-----------------------------------------------------------------*/
4413 /* iCodeFromAst - given an ast will convert it to iCode            */
4414 /*-----------------------------------------------------------------*/
4415 iCode *
4416 iCodeFromAst (ast * tree)
4417 {
4418   returnLabel = newiTempLabel ("_return");
4419   entryLabel = newiTempLabel ("_entry");
4420   ast2iCode (tree,0);
4421   return reverseiCChain ();
4422 }
4423
4424 static const char *opTypeToStr(OPTYPE op)
4425 {
4426     switch(op)
4427     {
4428       case SYMBOL: return "symbol";
4429       case VALUE: return "value";
4430       case TYPE: return "type";
4431     }
4432     return "undefined type";    
4433 }
4434
4435
4436 operand *validateOpType(operand         *op, 
4437                         const char      *macro,
4438                         const char      *args,
4439                         OPTYPE          type,
4440                         const char      *file, 
4441                         unsigned        line)
4442 {    
4443     if (op && op->type == type)
4444     {
4445         return op;
4446     }
4447     fprintf(stderr, 
4448             "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
4449             " expected %s, got %s\n",
4450             macro, args, file, line, 
4451             opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
4452     exit(-1);
4453     return op; // never reached, makes compiler happy.
4454 }