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