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