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