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