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