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