b723c54116810e4fcfc3e4d25a8e3103bf5b2de6
[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 *geniCodeDivision (operand *, operand *);
49 operand *geniCodeAssign (operand *, operand *, int);
50 operand *geniCodeArray (operand *, operand *,int);
51 operand *geniCodeArray2Ptr (operand *);
52 operand *geniCodeRValue (operand *, bool);
53 operand *geniCodeDerefPtr (operand *,int);
54 int isLvaluereq(int lvl);
55 void  setOClass (sym_link * ptr, sym_link * spec);
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 (SPEC_LONG(val->type)) {
148     if (SPEC_USIGN(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 (SPEC_USIGN(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 (SPEC_NOUN(ltype)==FLOAT) {
169     // anything will do
170     return;
171   }
172
173   if (!SPEC_USIGN(val->type) && v<0) {
174     negative=1;
175     if (SPEC_USIGN(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 && !SPEC_USIGN(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              SPEC_USIGN(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 (SPEC_NOUN (opetype) == V_FLOAT)
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 (SPEC_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 (SPEC_USIGN (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         retval = operandFromValue (valCastLiteral (type,
1169                                                    operandLitValue (left) /
1170                                                    operandLitValue (right)));
1171       break;
1172     case '%':
1173       if ((TYPE_UDWORD) operandLitValue (right) == 0) {
1174           werror (E_DIVIDE_BY_ZERO);
1175           retval = right;
1176       }
1177       else
1178         {
1179           if (SPEC_USIGN(let) || SPEC_USIGN(ret))
1180             /* one of the operands is unsigned */
1181             retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) %
1182                                      (TYPE_UDWORD) operandLitValue (right));
1183           else
1184             /* both operands are signed */
1185             retval = operandFromLit ((TYPE_DWORD) operandLitValue (left) %
1186                                      (TYPE_DWORD) operandLitValue (right));
1187         }
1188       break;
1189     case LEFT_OP:
1190       /* The number of left shifts is always unsigned. Signed doesn't make
1191          sense here. Shifting by a negative number is impossible. */
1192       retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) <<
1193                                (TYPE_UDWORD) operandLitValue (right));
1194       break;
1195     case RIGHT_OP:
1196       /* The number of right shifts is always unsigned. Signed doesn't make
1197          sense here. Shifting by a negative number is impossible. */
1198       if (SPEC_USIGN(let))
1199         /* unsigned: logic shift right */
1200         retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) >>
1201                                  (TYPE_UDWORD) operandLitValue (right));
1202       else
1203         /* signed: arithmetic shift right */
1204         retval = operandFromLit ((TYPE_DWORD ) operandLitValue (left) >>
1205                                  (TYPE_UDWORD) operandLitValue (right));
1206       break;
1207     case EQ_OP:
1208       /* this op doesn't care about signedness */
1209       {
1210         TYPE_UDWORD l, r;
1211
1212         l = (TYPE_UDWORD) operandLitValue (left);
1213         if (SPEC_NOUN(OP_VALUE(left)->type) == V_CHAR)
1214           l &= 0xff;
1215         else if (!SPEC_LONG (OP_VALUE(left)->type))
1216           l &= 0xffff;
1217         r = (TYPE_UDWORD) operandLitValue (right);
1218         if (SPEC_NOUN(OP_VALUE(right)->type) == V_CHAR)
1219           r &= 0xff;
1220         else if (!SPEC_LONG (OP_VALUE(right)->type))
1221           r &= 0xffff;
1222         retval = operandFromLit (l == r);
1223       }
1224       break;
1225     case '<':
1226       retval = operandFromLit (operandLitValue (left) <
1227                                operandLitValue (right));
1228       break;
1229     case LE_OP:
1230       retval = operandFromLit (operandLitValue (left) <=
1231                                operandLitValue (right));
1232       break;
1233     case NE_OP:
1234       retval = operandFromLit (operandLitValue (left) !=
1235                                operandLitValue (right));
1236       break;
1237     case '>':
1238       retval = operandFromLit (operandLitValue (left) >
1239                                operandLitValue (right));
1240       break;
1241     case GE_OP:
1242       retval = operandFromLit (operandLitValue (left) >=
1243                                operandLitValue (right));
1244       break;
1245     case BITWISEAND:
1246       retval = operandFromValue (valCastLiteral (type,
1247                                                  (TYPE_UDWORD)operandLitValue(left) &
1248                                                  (TYPE_UDWORD)operandLitValue(right)));
1249       break;
1250     case '|':
1251       retval = operandFromValue (valCastLiteral (type,
1252                                                  (TYPE_UDWORD)operandLitValue(left) |
1253                                                  (TYPE_UDWORD)operandLitValue(right)));
1254       break;
1255     case '^':
1256       retval = operandFromValue (valCastLiteral (type,
1257                                                  (TYPE_UDWORD)operandLitValue(left) ^
1258                                                  (TYPE_UDWORD)operandLitValue(right)));
1259       break;
1260     case AND_OP:
1261       retval = operandFromLit (operandLitValue (left) &&
1262                                operandLitValue (right));
1263       break;
1264     case OR_OP:
1265       retval = operandFromLit (operandLitValue (left) ||
1266                                operandLitValue (right));
1267       break;
1268     case RRC:
1269       {
1270         TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
1271
1272         retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
1273                                  (i << 1));
1274       }
1275       break;
1276     case RLC:
1277       {
1278         TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
1279
1280         retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
1281                                  (i >> 1));
1282       }
1283       break;
1284
1285     case UNARYMINUS:
1286       retval = operandFromValue (valCastLiteral (type,
1287                                                  -1 * operandLitValue (left)));
1288       break;
1289
1290     case '~':
1291       retval = operandFromLit (~((TYPE_UDWORD) operandLitValue (left)));
1292       break;
1293
1294     case '!':
1295       retval = operandFromLit (!operandLitValue (left));
1296       break;
1297
1298     default:
1299       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1300               " operandOperation invalid operator ");
1301       assert (0);
1302     }
1303
1304   return retval;
1305 }
1306
1307
1308 /*-----------------------------------------------------------------*/
1309 /* isOperandEqual - compares two operand & return 1 if they r =    */
1310 /*-----------------------------------------------------------------*/
1311 int
1312 isOperandEqual (operand * left, operand * right)
1313 {
1314   /* if the pointers are equal then they are equal */
1315   if (left == right)
1316     return 1;
1317
1318   /* if either of them null then false */
1319   if (!left || !right)
1320     return 0;
1321
1322   if (left->type != right->type)
1323     return 0;
1324
1325   if (IS_SYMOP (left) && IS_SYMOP (right))
1326     return left->key == right->key;
1327
1328   /* if types are the same */
1329   switch (left->type)
1330     {
1331     case SYMBOL:
1332       return isSymbolEqual (left->operand.symOperand,
1333                             right->operand.symOperand);
1334     case VALUE:
1335       return (floatFromVal (left->operand.valOperand) ==
1336               floatFromVal (right->operand.valOperand));
1337     case TYPE:
1338       if (compareType (left->operand.typeOperand,
1339                      right->operand.typeOperand) == 1)
1340         return 1;
1341     }
1342
1343   return 0;
1344 }
1345
1346 /*-------------------------------------------------------------------*/
1347 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1348 /*-------------------------------------------------------------------*/
1349 int 
1350 isiCodeEqual (iCode * left, iCode * right)
1351 {
1352   /* if the same pointer */
1353   if (left == right)
1354     return 1;
1355
1356   /* if either of them null */
1357   if (!left || !right)
1358     return 0;
1359
1360   /* if operand are the same */
1361   if (left->op == right->op)
1362     {
1363
1364       /* compare all the elements depending on type */
1365       if (left->op != IFX)
1366         {
1367           if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1368             return 0;
1369           if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1370             return 0;
1371
1372         }
1373       else
1374         {
1375           if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1376             return 0;
1377           if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1378             return 0;
1379           if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1380             return 0;
1381         }
1382       
1383       return 1;
1384     }
1385   return 0;
1386 }
1387
1388 /*-----------------------------------------------------------------*/
1389 /* newiTempFromOp - create a temp Operand with same attributes     */
1390 /*-----------------------------------------------------------------*/
1391 operand *
1392 newiTempFromOp (operand * op)
1393 {
1394   operand *nop;
1395
1396   if (!op)
1397     return NULL;
1398
1399   if (!IS_ITEMP (op))
1400     return op;
1401
1402   nop = newiTempOperand (operandType (op), TRUE);
1403   nop->isaddr = op->isaddr;
1404   nop->isvolatile = op->isvolatile;
1405   nop->isGlobal = op->isGlobal;
1406   nop->isLiteral = op->isLiteral;
1407   nop->usesDefs = op->usesDefs;
1408   nop->isParm = op->isParm;
1409   return nop;
1410 }
1411
1412 /*-----------------------------------------------------------------*/
1413 /* operand from operand - creates an operand holder for the type   */
1414 /*-----------------------------------------------------------------*/
1415 operand *
1416 operandFromOperand (operand * op)
1417 {
1418   operand *nop;
1419
1420   if (!op)
1421     return NULL;
1422   nop = newOperand ();
1423   nop->type = op->type;
1424   nop->isaddr = op->isaddr;
1425   nop->key = op->key;
1426   nop->isvolatile = op->isvolatile;
1427   nop->isGlobal = op->isGlobal;
1428   nop->isLiteral = op->isLiteral;
1429   nop->usesDefs = op->usesDefs;
1430   nop->isParm = op->isParm;
1431   
1432   switch (nop->type)
1433     {
1434     case SYMBOL:
1435       nop->operand.symOperand = op->operand.symOperand;
1436       break;
1437     case VALUE:
1438       nop->operand.valOperand = op->operand.valOperand;
1439       break;
1440     case TYPE:
1441       nop->operand.typeOperand = op->operand.typeOperand;
1442       break;
1443     }
1444
1445   return nop;
1446 }
1447
1448 /*-----------------------------------------------------------------*/
1449 /* opFromOpWithDU - makes a copy of the operand and DU chains      */
1450 /*-----------------------------------------------------------------*/
1451 operand *
1452 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1453 {
1454   operand *nop = operandFromOperand (op);
1455
1456   if (nop->type == SYMBOL)
1457     {
1458       OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1459       OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1460     }
1461
1462   return nop;
1463 }
1464
1465 /*-----------------------------------------------------------------*/
1466 /* operandFromSymbol - creates an operand from a symbol            */
1467 /*-----------------------------------------------------------------*/
1468 operand *
1469 operandFromSymbol (symbol * sym)
1470 {
1471   operand *op;
1472   iCode *ic;
1473   int ok = 1;
1474   /* if the symbol's type is a literal */
1475   /* then it is an enumerator type     */
1476   if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1477     return operandFromValue (valFromType (sym->etype));
1478
1479   if (!sym->key)
1480     sym->key = ++operandKey;
1481
1482   /* if this an implicit variable, means struct/union */
1483   /* member so just return it                         */
1484   if (sym->implicit || IS_FUNC (sym->type))
1485     {
1486       op = newOperand ();
1487       op->type = SYMBOL;
1488       op->operand.symOperand = sym;
1489       op->key = sym->key;
1490       op->isvolatile = isOperandVolatile (op, TRUE);
1491       op->isGlobal = isOperandGlobal (op);
1492       return op;
1493     }
1494
1495   /* under the following conditions create a
1496      register equivalent for a local symbol */
1497   if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1498       (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1499       !TARGET_IS_HC08 &&
1500       (!(options.model == MODEL_FLAT24)) ) &&
1501       options.stackAuto == 0)
1502     ok = 0;
1503
1504   if (!IS_AGGREGATE (sym->type) &&      /* not an aggregate */
1505       !IS_FUNC (sym->type) &&   /* not a function   */
1506       !sym->_isparm &&          /* not a parameter  */
1507       sym->level &&             /* is a local variable */
1508       !sym->addrtaken &&        /* whose address has not been taken */
1509       !sym->reqv &&             /* does not already have a reg equivalence */
1510       !IS_VOLATILE (sym->etype) &&      /* not declared as volatile */
1511       !IS_STATIC (sym->etype) &&        /* and not declared static  */
1512       !sym->islbl &&            /* not a label */
1513       ok &&                     /* farspace check */
1514       !IS_BITVAR (sym->etype)   /* not a bit variable */
1515     )
1516     {                                   
1517
1518       /* we will use it after all optimizations
1519          and before liveRange calculation */
1520       sym->reqv = newiTempOperand (sym->type, 0);
1521       sym->reqv->key = sym->key;
1522       OP_SYMBOL (sym->reqv)->key = sym->key;
1523       OP_SYMBOL (sym->reqv)->isreqv = 1;
1524       OP_SYMBOL (sym->reqv)->islocal = 1;
1525       OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
1526       SPIL_LOC (sym->reqv) = sym;
1527     }
1528
1529   if (!IS_AGGREGATE (sym->type))
1530     {
1531       op = newOperand ();
1532       op->type = SYMBOL;
1533       op->operand.symOperand = sym;
1534       op->isaddr = 1;
1535       op->key = sym->key;
1536       op->isvolatile = isOperandVolatile (op, TRUE);
1537       op->isGlobal = isOperandGlobal (op);
1538       op->isPtr = IS_PTR (operandType (op));
1539       op->isParm = sym->_isparm;
1540       return op;
1541     }
1542
1543   /* create :-                     */
1544   /*    itemp = &[_symbol]         */
1545
1546   ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1547   IC_LEFT (ic)->type = SYMBOL;
1548   IC_LEFT (ic)->operand.symOperand = sym;
1549   IC_LEFT (ic)->key = sym->key;
1550   (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1551   (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1552   IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1553
1554   /* create result */
1555   IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1556   if (IS_ARRAY (sym->type))
1557     {
1558       IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1559       IC_RESULT (ic)->isaddr = 0;
1560     }
1561   else
1562     IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1563
1564   ADDTOCHAIN (ic);
1565
1566   return IC_RESULT (ic);
1567 }
1568
1569 /*-----------------------------------------------------------------*/
1570 /* operandFromValue - creates an operand from value                */
1571 /*-----------------------------------------------------------------*/
1572 operand *
1573 operandFromValue (value * val)
1574 {
1575   operand *op;
1576
1577   /* if this is a symbol then do the symbol thing */
1578   if (val->sym)
1579     return operandFromSymbol (val->sym);
1580
1581   /* this is not a symbol */
1582   op = newOperand ();
1583   op->type = VALUE;
1584   op->operand.valOperand = val;
1585   op->isLiteral = isOperandLiteral (op);
1586   return op;
1587 }
1588
1589 /*-----------------------------------------------------------------*/
1590 /* operandFromLink - operand from typeChain                        */
1591 /*-----------------------------------------------------------------*/
1592 operand *
1593 operandFromLink (sym_link * type)
1594 {
1595   operand *op;
1596
1597   /* operand from sym_link */
1598   if (!type)
1599     return NULL;
1600
1601   op = newOperand ();
1602   op->type = TYPE;
1603   op->operand.typeOperand = copyLinkChain (type);
1604   return op;
1605 }
1606
1607 /*-----------------------------------------------------------------*/
1608 /* operandFromLit - makes an operand from a literal value          */
1609 /*-----------------------------------------------------------------*/
1610 operand *
1611 operandFromLit (double i)
1612 {
1613   return operandFromValue (valueFromLit (i));
1614 }
1615
1616 /*-----------------------------------------------------------------*/
1617 /* operandFromAst - creates an operand from an ast                 */
1618 /*-----------------------------------------------------------------*/
1619 operand *
1620 operandFromAst (ast * tree,int lvl)
1621 {
1622
1623   if (!tree)
1624     return NULL;
1625
1626   /* depending on type do */
1627   switch (tree->type)
1628     {
1629     case EX_OP:
1630       return ast2iCode (tree,lvl+1);
1631       break;
1632
1633     case EX_VALUE:
1634       return operandFromValue (tree->opval.val);
1635       break;
1636
1637     case EX_LINK:
1638       return operandFromLink (tree->opval.lnk);
1639       break;
1640
1641     default:
1642       assert (0);
1643     }
1644   
1645   /*  Just to keep the compiler happy */
1646   return (operand *) 0;
1647 }
1648
1649 /*-----------------------------------------------------------------*/
1650 /* setOperandType - sets the operand's type to the given type      */
1651 /*-----------------------------------------------------------------*/
1652 void 
1653 setOperandType (operand * op, sym_link * type)
1654 {
1655   /* depending on the type of operand */
1656   switch (op->type)
1657     {
1658
1659     case VALUE:
1660       op->operand.valOperand->etype =
1661         getSpec (op->operand.valOperand->type =
1662                  copyLinkChain (type));
1663       return;
1664
1665     case SYMBOL:
1666       if (op->operand.symOperand->isitmp)
1667         op->operand.symOperand->etype =
1668           getSpec (op->operand.symOperand->type =
1669                    copyLinkChain (type));
1670       else
1671         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1672                 "attempt to modify type of source");
1673       return;
1674
1675     case TYPE:
1676       op->operand.typeOperand = copyLinkChain (type);
1677       return;
1678     }
1679
1680 }
1681 /*-----------------------------------------------------------------*/
1682 /* Get size in byte of ptr need to access an array                 */
1683 /*-----------------------------------------------------------------*/
1684 int
1685 getArraySizePtr (operand * op)
1686 {
1687   sym_link *ltype = operandType(op);
1688
1689   if(IS_PTR(ltype))
1690     {
1691       int size = getSize(ltype);
1692       return(IS_GENPTR(ltype)?(size-1):size);
1693     }
1694
1695   if(IS_ARRAY(ltype))
1696     {
1697       sym_link *letype = getSpec(ltype);
1698       switch (PTR_TYPE (SPEC_OCLS (letype)))
1699         {
1700         case IPOINTER:
1701         case PPOINTER:
1702         case POINTER:
1703           return (PTRSIZE);
1704         case EEPPOINTER:
1705         case FPOINTER:
1706         case CPOINTER:
1707         case FUNCTION:
1708           return (FPTRSIZE);
1709         case GPOINTER:
1710           return (GPTRSIZE-1);
1711
1712         default:
1713           return (FPTRSIZE);
1714         }
1715     }
1716   return (FPTRSIZE);
1717 }
1718
1719 /*-----------------------------------------------------------------*/
1720 /* perform "usual unary conversions"                               */
1721 /*-----------------------------------------------------------------*/
1722 operand *
1723 usualUnaryConversions (operand * op)
1724 {
1725   if (IS_INTEGRAL (operandType (op)))
1726     {
1727       if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1728         {
1729           /* Widen to int. */
1730           return geniCodeCast (INTTYPE, op, TRUE);
1731         }
1732     }
1733   return op;
1734 }
1735
1736 /*-----------------------------------------------------------------*/
1737 /* perform "usual binary conversions"                              */
1738 /*-----------------------------------------------------------------*/
1739 sym_link *
1740 usualBinaryConversions (operand ** op1, operand ** op2)
1741 {
1742   sym_link *ctype;
1743   sym_link *rtype = operandType (*op2);
1744   sym_link *ltype = operandType (*op1);
1745   
1746   ctype = computeType (ltype, rtype);
1747
1748   *op1 = geniCodeCast (ctype, *op1, TRUE);
1749   *op2 = geniCodeCast (ctype, *op2, TRUE);
1750   
1751   return ctype;
1752 }
1753
1754 /*-----------------------------------------------------------------*/
1755 /* geniCodeValueAtAddress - generate intermeditate code for value  */
1756 /*                          at address                             */
1757 /*-----------------------------------------------------------------*/
1758 operand *
1759 geniCodeRValue (operand * op, bool force)
1760 {
1761   iCode *ic;
1762   sym_link *type = operandType (op);
1763   sym_link *etype = getSpec (type);
1764
1765   /* if this is an array & already */
1766   /* an address then return this   */
1767   if (IS_AGGREGATE (type) ||
1768       (IS_PTR (type) && !force && !op->isaddr))
1769     return operandFromOperand (op);
1770
1771   /* if this is not an address then must be */
1772   /* rvalue already so return this one      */
1773   if (!op->isaddr)
1774     return op;
1775
1776   /* if this is not a temp symbol then */
1777   if (!IS_ITEMP (op) &&
1778       !force &&
1779       !(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08))
1780     {
1781       op = operandFromOperand (op);
1782       op->isaddr = 0;
1783       return op;
1784     }
1785
1786   if (IS_SPEC (type) &&
1787       IS_TRUE_SYMOP (op) &&
1788       (!(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08) ||
1789       (options.model == MODEL_FLAT24) ))
1790     {
1791       op = operandFromOperand (op);
1792       op->isaddr = 0;
1793       return op;
1794     }
1795
1796   ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1797   if (IS_PTR (type) && op->isaddr && force)
1798     type = type->next;
1799
1800   type = copyLinkChain (type);
1801
1802   IC_RESULT (ic) = newiTempOperand (type, 1);
1803   IC_RESULT (ic)->isaddr = 0;
1804
1805 /*     ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1806
1807   ADDTOCHAIN (ic);
1808
1809   return IC_RESULT (ic);
1810 }
1811
1812 /*-----------------------------------------------------------------*/
1813 /* geniCodeCast - changes the value from one type to another       */
1814 /*-----------------------------------------------------------------*/
1815 operand *
1816 geniCodeCast (sym_link * type, operand * op, bool implicit)
1817 {
1818   iCode *ic;
1819   sym_link *optype;
1820   sym_link *opetype = getSpec (optype = operandType (op));
1821   sym_link *restype;
1822   int errors=0;
1823
1824   /* one of them has size zero then error */
1825   if (IS_VOID (optype))
1826     {
1827       werror (E_CAST_ZERO);
1828       return op;
1829     }
1830
1831   /* if the operand is already the desired type then do nothing */
1832   if (compareType (type, optype) == 1)
1833     return op;
1834
1835   /* if this is a literal then just change the type & return */
1836   if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1837     return operandFromValue (valCastLiteral (type,
1838                                              operandLitValue (op)));
1839
1840   /* if casting to/from pointers, do some checking */
1841   if (IS_PTR(type)) { // to a pointer
1842     if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1843       if (IS_INTEGRAL(optype)) { 
1844         // maybe this is NULL, than it's ok. 
1845         if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1846           if (port->s.gptr_size > port->s.fptr_size && IS_GENPTR(type)) {
1847             // no way to set the storage
1848             if (IS_LITERAL(optype)) {
1849               werror(E_LITERAL_GENERIC);
1850               errors++;
1851             } else {
1852               werror(E_NONPTR2_GENPTR);
1853               errors++;
1854             }
1855           } else if (implicit) {
1856             werror(W_INTEGRAL2PTR_NOCAST);
1857             errors++;
1858           }
1859         }
1860       } else { 
1861         // shouldn't do that with float, array or structure unless to void
1862         if (!IS_VOID(getSpec(type)) && 
1863             !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1864           werror(E_INCOMPAT_TYPES);
1865           errors++;
1866         }
1867       }
1868     } else { // from a pointer to a pointer
1869       if (port->s.gptr_size > port->s.fptr_size /*!TARGET_IS_Z80 && !TARGET_IS_GBZ80*/) {
1870         // if not a pointer to a function
1871         if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1872           if (implicit) { // if not to generic, they have to match 
1873             if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1874               werror(E_INCOMPAT_PTYPES);
1875               errors++;
1876             }
1877           }
1878         }
1879       }
1880     }
1881   } else { // to a non pointer
1882     if (IS_PTR(optype)) { // from a pointer
1883       if (implicit) { // sneaky
1884         if (IS_INTEGRAL(type)) {
1885           werror(W_PTR2INTEGRAL_NOCAST);
1886           errors++;
1887         } else { // shouldn't do that with float, array or structure
1888           werror(E_INCOMPAT_TYPES);
1889           errors++;
1890         }
1891       }
1892     }
1893   }
1894   if (errors) {
1895     printFromToType (optype, type);
1896   }
1897
1898   /* if they are the same size create an assignment */
1899   if (getSize (type) == getSize (optype) &&
1900       !IS_BITFIELD (type) &&
1901       !IS_FLOAT (type) &&
1902       !IS_FLOAT (optype) &&
1903       ((IS_SPEC (type) && IS_SPEC (optype)) ||
1904        (!IS_SPEC (type) && !IS_SPEC (optype))))
1905     {
1906
1907       ic = newiCode ('=', NULL, op);
1908       IC_RESULT (ic) = newiTempOperand (type, 0);
1909       SPIL_LOC (IC_RESULT (ic)) =
1910         (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1911       IC_RESULT (ic)->isaddr = 0;
1912     }
1913   else
1914     {
1915       ic = newiCode (CAST, operandFromLink (type),
1916                      geniCodeRValue (op, FALSE));
1917
1918       IC_RESULT (ic) = newiTempOperand (type, 0);
1919     }
1920
1921   /* preserve the storage class & output class */
1922   /* of the original variable                  */
1923   restype = getSpec (operandType (IC_RESULT (ic)));
1924   if (!IS_LITERAL(opetype))
1925       SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1926   SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1927
1928   ADDTOCHAIN (ic);
1929   return IC_RESULT (ic);
1930 }
1931
1932 /*-----------------------------------------------------------------*/
1933 /* geniCodeLabel - will create a Label                             */
1934 /*-----------------------------------------------------------------*/
1935 void 
1936 geniCodeLabel (symbol * label)
1937 {
1938   iCode *ic;
1939
1940   ic = newiCodeLabelGoto (LABEL, label);
1941   ADDTOCHAIN (ic);
1942 }
1943
1944 /*-----------------------------------------------------------------*/
1945 /* geniCodeGoto  - will create a Goto                              */
1946 /*-----------------------------------------------------------------*/
1947 void 
1948 geniCodeGoto (symbol * label)
1949 {
1950   iCode *ic;
1951
1952   ic = newiCodeLabelGoto (GOTO, label);
1953   ADDTOCHAIN (ic);
1954 }
1955
1956 /*-----------------------------------------------------------------*/
1957 /* geniCodeMultiply - gen intermediate code for multiplication     */
1958 /*-----------------------------------------------------------------*/
1959 operand *
1960 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1961 {
1962   iCode *ic;
1963   int p2 = 0;
1964   sym_link *resType;
1965   LRTYPE;
1966
1967   /* if they are both literal then we know the result */
1968   if (IS_LITERAL (letype) && IS_LITERAL (retype))
1969     return operandFromValue (valMult (left->operand.valOperand,
1970                                       right->operand.valOperand));
1971
1972   if (IS_LITERAL(retype)) {
1973     p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1974   }
1975
1976   resType = usualBinaryConversions (&left, &right);
1977 #if 1
1978   rtype = operandType (right);
1979   retype = getSpec (rtype);
1980   ltype = operandType (left);
1981   letype = getSpec (ltype);
1982 #endif
1983   if (resultIsInt)
1984     {
1985       SPEC_NOUN(getSpec(resType))=V_INT;
1986     }
1987
1988   /* if the right is a literal & power of 2 */
1989   /* then make it a left shift              */
1990   /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
1991      efficient in most cases than 2 bytes result = 2 bytes << literal
1992      if port has 1 byte muldiv */
1993   if (p2 && !IS_FLOAT (letype) &&
1994       !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
1995         (port->support.muldiv == 1)))
1996     {
1997       if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1998         {
1999           /* LEFT_OP need same size for left and result, */
2000           left = geniCodeCast (resType, left, TRUE);
2001           ltype = operandType (left);
2002         }
2003       ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
2004     }
2005   else
2006     {
2007       ic = newiCode ('*', left, right);         /* normal multiplication */
2008       /* if the size left or right > 1 then support routine */
2009       if (getSize (ltype) > 1 || getSize (rtype) > 1)
2010         ic->supportRtn = 1;
2011
2012     }
2013   IC_RESULT (ic) = newiTempOperand (resType, 1);
2014
2015   ADDTOCHAIN (ic);
2016   return IC_RESULT (ic);
2017 }
2018
2019 /*-----------------------------------------------------------------*/
2020 /* geniCodeDivision - gen intermediate code for division           */
2021 /*-----------------------------------------------------------------*/
2022 operand *
2023 geniCodeDivision (operand * left, operand * right)
2024 {
2025   iCode *ic;
2026   int p2 = 0;
2027   sym_link *resType;
2028   sym_link *rtype = operandType (right);
2029   sym_link *retype = getSpec (rtype);
2030   sym_link *ltype = operandType (left);
2031   sym_link *letype = getSpec (ltype);
2032
2033   resType = usualBinaryConversions (&left, &right);
2034
2035   /* if the right is a literal & power of 2
2036      and left is unsigned then make it a
2037      right shift */
2038   if (IS_LITERAL (retype) &&
2039       !IS_FLOAT (letype) &&
2040       SPEC_USIGN(letype) &&
2041       (p2 = powof2 ((unsigned long)
2042                     floatFromVal (right->operand.valOperand)))) {
2043     ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
2044   }
2045   else
2046     {
2047       ic = newiCode ('/', left, right);         /* normal division */
2048       /* if the size left or right > 1 then support routine */
2049       if (getSize (ltype) > 1 || getSize (rtype) > 1)
2050         ic->supportRtn = 1;
2051     }
2052   IC_RESULT (ic) = newiTempOperand (resType, 0);
2053
2054   ADDTOCHAIN (ic);
2055   return IC_RESULT (ic);
2056 }
2057 /*-----------------------------------------------------------------*/
2058 /* geniCodeModulus  - gen intermediate code for modulus            */
2059 /*-----------------------------------------------------------------*/
2060 operand *
2061 geniCodeModulus (operand * left, operand * right)
2062 {
2063   iCode *ic;
2064   sym_link *resType;
2065   LRTYPE;
2066
2067   /* if they are both literal then we know the result */
2068   if (IS_LITERAL (letype) && IS_LITERAL (retype))
2069     return operandFromValue (valMod (left->operand.valOperand,
2070                                      right->operand.valOperand));
2071
2072   resType = usualBinaryConversions (&left, &right);
2073
2074   /* now they are the same size */
2075   ic = newiCode ('%', left, right);
2076
2077   /* if the size left or right > 1 then support routine */
2078   if (getSize (ltype) > 1 || getSize (rtype) > 1)
2079     ic->supportRtn = 1;
2080   IC_RESULT (ic) = newiTempOperand (resType, 0);
2081
2082   ADDTOCHAIN (ic);
2083   return IC_RESULT (ic);
2084 }
2085
2086 /*-----------------------------------------------------------------*/
2087 /* geniCodePtrPtrSubtract - subtracts pointer from pointer         */
2088 /*-----------------------------------------------------------------*/
2089 operand *
2090 geniCodePtrPtrSubtract (operand * left, operand * right)
2091 {
2092   iCode *ic;
2093   operand *result;
2094   LRTYPE;
2095
2096   /* if they are both literals then */
2097   if (IS_LITERAL (letype) && IS_LITERAL (retype))
2098     {
2099       result = operandFromValue (valMinus (left->operand.valOperand,
2100                                            right->operand.valOperand));
2101       goto subtractExit;
2102     }
2103
2104   ic = newiCode ('-', left, right);
2105
2106   IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
2107   ADDTOCHAIN (ic);
2108
2109 subtractExit:
2110   if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
2111     return result;
2112   }
2113   
2114   // should we really do this? is this ANSI?
2115   return geniCodeDivision (result,
2116                            operandFromLit (getSize (ltype->next)));
2117 }
2118
2119 /*-----------------------------------------------------------------*/
2120 /* geniCodeSubtract - generates code for subtraction               */
2121 /*-----------------------------------------------------------------*/
2122 operand *
2123 geniCodeSubtract (operand * left, operand * right)
2124 {
2125   iCode *ic;
2126   int isarray = 0;
2127   sym_link *resType;
2128   LRTYPE;
2129
2130   /* if they both pointers then */
2131   if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
2132       (IS_PTR (rtype) || IS_ARRAY (rtype)))
2133     return geniCodePtrPtrSubtract (left, right);
2134
2135   /* if they are both literal then we know the result */
2136   if (IS_LITERAL (letype) && IS_LITERAL (retype)
2137       && left->isLiteral && right->isLiteral)
2138     return operandFromValue (valMinus (left->operand.valOperand,
2139                                        right->operand.valOperand));
2140
2141   /* if left is an array or pointer */
2142   if (IS_PTR (ltype) || IS_ARRAY (ltype))
2143     {
2144       isarray = left->isaddr;
2145       right = geniCodeMultiply (right,
2146                                 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2147       resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2148     }
2149   else
2150     {                           /* make them the same size */
2151       resType = usualBinaryConversions (&left, &right);
2152     }
2153
2154   ic = newiCode ('-', left, right);
2155
2156   IC_RESULT (ic) = newiTempOperand (resType, 1);
2157   IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2158
2159   /* if left or right is a float */
2160   if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2161     ic->supportRtn = 1;
2162
2163   ADDTOCHAIN (ic);
2164   return IC_RESULT (ic);
2165 }
2166
2167 /*-----------------------------------------------------------------*/
2168 /* geniCodeAdd - generates iCode for addition                      */
2169 /*-----------------------------------------------------------------*/
2170 operand *
2171 geniCodeAdd (operand * left, operand * right, int lvl)
2172 {
2173   iCode *ic;
2174   sym_link *resType;
2175   operand *size;
2176   int isarray = 0;
2177   LRTYPE;
2178
2179   /* if the right side is LITERAL zero */
2180   /* return the left side              */
2181   if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (rtype)))
2182     return left;
2183
2184   /* if left is literal zero return right */
2185   if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (ltype)))
2186     return right;
2187
2188   /* if left is a pointer then size */
2189   if (IS_PTR (ltype) || IS_ARRAY(ltype))
2190     {
2191       isarray = left->isaddr;
2192       // there is no need to multiply with 1
2193       if (getSize(ltype->next)!=1) {
2194         size  = operandFromLit (getSize (ltype->next));
2195         right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
2196       }
2197       resType = copyLinkChain (ltype);
2198     }
2199   else
2200     { // make them the same size
2201       resType = usualBinaryConversions (&left, &right);
2202     }
2203
2204   /* if they are both literals then we know */
2205   if (IS_LITERAL (letype) && IS_LITERAL (retype)
2206       && left->isLiteral && right->isLiteral)
2207     return operandFromValue (valPlus (valFromType (ltype),
2208                                       valFromType (rtype)));
2209
2210   ic = newiCode ('+', left, right);
2211
2212   IC_RESULT (ic) = newiTempOperand (resType, 1);
2213   IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2214
2215   /* if left or right is a float then support
2216      routine */
2217   if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2218     ic->supportRtn = 1;
2219
2220   ADDTOCHAIN (ic);
2221
2222   return IC_RESULT (ic);
2223
2224 }
2225
2226 /*-----------------------------------------------------------------*/
2227 /* aggrToPtr - changes an aggregate to pointer to an aggregate     */
2228 /*-----------------------------------------------------------------*/
2229 sym_link *
2230 aggrToPtr (sym_link * type, bool force)
2231 {
2232   sym_link *etype;
2233   sym_link *ptype;
2234
2235   if (IS_PTR (type) && !force)
2236     return type;
2237
2238   etype = getSpec (type);
2239   ptype = newLink (DECLARATOR);
2240
2241   ptype->next = type;
2242
2243   /* set the pointer depending on the storage class */
2244   DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype));
2245   return ptype;
2246 }
2247
2248 /*-----------------------------------------------------------------*/
2249 /* geniCodeArray2Ptr - array to pointer                            */
2250 /*-----------------------------------------------------------------*/
2251 operand *
2252 geniCodeArray2Ptr (operand * op)
2253 {
2254   sym_link *optype = operandType (op);
2255   sym_link *opetype = getSpec (optype);
2256
2257   /* set the pointer depending on the storage class */
2258   DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype));
2259
2260   op->isaddr = 0;
2261   return op;
2262 }
2263
2264
2265 /*-----------------------------------------------------------------*/
2266 /* geniCodeArray - array access                                    */
2267 /*-----------------------------------------------------------------*/
2268 operand *
2269 geniCodeArray (operand * left, operand * right,int lvl)
2270 {
2271   iCode *ic;
2272   sym_link *ltype = operandType (left);
2273   
2274   if (IS_PTR (ltype))
2275     {
2276       if (IS_PTR (ltype->next) && left->isaddr)
2277         {
2278           left = geniCodeRValue (left, FALSE);
2279         }
2280       
2281       return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
2282     }
2283
2284   right = geniCodeMultiply (right,
2285                             operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2286
2287   /* we can check for limits here */
2288   if (isOperandLiteral (right) &&
2289       IS_ARRAY (ltype) &&
2290       DCL_ELEM (ltype) &&
2291       (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2292     {
2293       werror (E_ARRAY_BOUND);
2294       right = operandFromLit (0);
2295     }
2296
2297   ic = newiCode ('+', left, right);
2298
2299   IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2300                                       !IS_AGGREGATE (ltype->next) &&
2301                                       !IS_PTR (ltype->next))
2302                                      ? ltype : ltype->next), 0);
2303
2304   IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2305   ADDTOCHAIN (ic);
2306
2307   return IC_RESULT (ic);
2308 }
2309
2310 /*-----------------------------------------------------------------*/
2311 /* geniCodeStruct - generates intermediate code for structres      */
2312 /*-----------------------------------------------------------------*/
2313 operand *
2314 geniCodeStruct (operand * left, operand * right, bool islval)
2315 {
2316   iCode *ic;
2317   sym_link *type = operandType (left);
2318   sym_link *etype = getSpec (type);
2319   sym_link *retype;
2320   symbol *element = getStructElement (SPEC_STRUCT (etype),
2321                                       right->operand.symOperand);
2322
2323   wassert(IS_SYMOP(right));
2324     
2325   /* add the offset */
2326   ic = newiCode ('+', left, operandFromLit (element->offset));
2327
2328   IC_RESULT (ic) = newiTempOperand (element->type, 0);
2329
2330   /* preserve the storage & output class of the struct */
2331   /* as well as the volatile attribute */
2332   retype = getSpec (operandType (IC_RESULT (ic)));
2333   SPEC_SCLS (retype) = SPEC_SCLS (etype);
2334   SPEC_OCLS (retype) = SPEC_OCLS (etype);
2335   SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2336   SPEC_CONST (retype) |= SPEC_CONST (etype);
2337   
2338   if (IS_PTR (element->type))
2339     setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2340   
2341   IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2342
2343   ADDTOCHAIN (ic);
2344   return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2345 }
2346
2347 /*-----------------------------------------------------------------*/
2348 /* geniCodePostInc - generate int code for Post increment          */
2349 /*-----------------------------------------------------------------*/
2350 operand *
2351 geniCodePostInc (operand * op)
2352 {
2353   iCode *ic;
2354   operand *rOp;
2355   sym_link *optype = operandType (op);
2356   operand *result;
2357   operand *rv = (IS_ITEMP (op) ?
2358                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2359                  op);
2360   sym_link *rvtype = operandType (rv);
2361   int size = 0;
2362
2363   /* if this is not an address we have trouble */
2364   if (!op->isaddr)
2365     {
2366       werror (E_LVALUE_REQUIRED, "++");
2367       return op;
2368     }
2369
2370   rOp = newiTempOperand (rvtype, 0);
2371   OP_SYMBOL(rOp)->noSpilLoc = 1;
2372
2373   if (IS_ITEMP (rv))
2374     OP_SYMBOL(rv)->noSpilLoc = 1;
2375
2376   geniCodeAssign (rOp, rv, 0);
2377
2378   size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2379   if (IS_FLOAT (rvtype))
2380     ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2381   else
2382     ic = newiCode ('+', rv, operandFromLit (size));
2383
2384   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2385   ADDTOCHAIN (ic);
2386
2387   geniCodeAssign (op, result, 0);
2388
2389   return rOp;
2390
2391 }
2392
2393 /*-----------------------------------------------------------------*/
2394 /* geniCodePreInc - generate code for preIncrement                 */
2395 /*-----------------------------------------------------------------*/
2396 operand *
2397 geniCodePreInc (operand * op, bool lvalue)
2398 {
2399   iCode *ic;
2400   sym_link *optype = operandType (op);
2401   operand *rop = (IS_ITEMP (op) ?
2402                   geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2403                   op);
2404   sym_link *roptype = operandType (rop);
2405   operand *result;
2406   int size = 0;
2407
2408   if (!op->isaddr)
2409     {
2410       werror (E_LVALUE_REQUIRED, "++");
2411       return op;
2412     }
2413
2414
2415   size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2416   if (IS_FLOAT (roptype))
2417     ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2418   else
2419     ic = newiCode ('+', rop, operandFromLit (size));
2420   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2421   ADDTOCHAIN (ic);
2422
2423   (void) geniCodeAssign (op, result, 0);
2424   if (lvalue || IS_TRUE_SYMOP (op))
2425     return op;
2426   else
2427     return result;
2428 }
2429
2430 /*-----------------------------------------------------------------*/
2431 /* geniCodePostDec - generates code for Post decrement             */
2432 /*-----------------------------------------------------------------*/
2433 operand *
2434 geniCodePostDec (operand * op)
2435 {
2436   iCode *ic;
2437   operand *rOp;
2438   sym_link *optype = operandType (op);
2439   operand *result;
2440   operand *rv = (IS_ITEMP (op) ?
2441                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2442                  op);
2443   sym_link *rvtype = operandType (rv);
2444   int size = 0;
2445
2446   /* if this is not an address we have trouble */
2447   if (!op->isaddr)
2448     {
2449       werror (E_LVALUE_REQUIRED, "--");
2450       return op;
2451     }
2452
2453   rOp = newiTempOperand (rvtype, 0);
2454   OP_SYMBOL(rOp)->noSpilLoc = 1;
2455
2456   if (IS_ITEMP (rv))
2457     OP_SYMBOL(rv)->noSpilLoc = 1;
2458
2459   geniCodeAssign (rOp, rv, 0);
2460
2461   size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2462   if (IS_FLOAT (rvtype))
2463     ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2464   else
2465     ic = newiCode ('-', rv, operandFromLit (size));
2466
2467   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2468   ADDTOCHAIN (ic);
2469
2470   geniCodeAssign (op, result, 0);
2471
2472   return rOp;
2473
2474 }
2475
2476 /*-----------------------------------------------------------------*/
2477 /* geniCodePreDec - generate code for pre  decrement               */
2478 /*-----------------------------------------------------------------*/
2479 operand *
2480 geniCodePreDec (operand * op, bool lvalue)
2481 {
2482   iCode *ic;
2483   sym_link *optype = operandType (op);
2484   operand *rop = (IS_ITEMP (op) ?
2485                   geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2486                   op);
2487   sym_link *roptype = operandType (rop);
2488   operand *result;
2489   int size = 0;
2490
2491   if (!op->isaddr)
2492     {
2493       werror (E_LVALUE_REQUIRED, "--");
2494       return op;
2495     }
2496
2497
2498   size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2499   if (IS_FLOAT (roptype))
2500     ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2501   else
2502     ic = newiCode ('-', rop, operandFromLit (size));
2503   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2504   ADDTOCHAIN (ic);
2505
2506   (void) geniCodeAssign (op, result, 0);
2507   if (lvalue || IS_TRUE_SYMOP (op))
2508     return op;
2509   else
2510     return result;
2511 }
2512
2513
2514 /*-----------------------------------------------------------------*/
2515 /* geniCodeBitwise - gen int code for bitWise  operators           */
2516 /*-----------------------------------------------------------------*/
2517 operand *
2518 geniCodeBitwise (operand * left, operand * right,
2519                  int oper, sym_link * resType)
2520 {
2521   iCode *ic;
2522
2523   left = geniCodeCast (resType, left, TRUE);
2524   right = geniCodeCast (resType, right, TRUE);
2525
2526   ic = newiCode (oper, left, right);
2527   IC_RESULT (ic) = newiTempOperand (resType, 0);
2528
2529   ADDTOCHAIN (ic);
2530   return IC_RESULT (ic);
2531 }
2532
2533 /*-----------------------------------------------------------------*/
2534 /* geniCodeAddressOf - gens icode for '&' address of operator      */
2535 /*-----------------------------------------------------------------*/
2536 operand *
2537 geniCodeAddressOf (operand * op)
2538 {
2539   iCode *ic;
2540   sym_link *p;
2541   sym_link *optype = operandType (op);
2542   sym_link *opetype = getSpec (optype);
2543
2544   if (IS_ITEMP (op) && op->isaddr && IS_PTR (optype))
2545     {
2546       op = operandFromOperand (op);
2547       op->isaddr = 0;
2548       return op;
2549     }
2550   
2551   /* lvalue check already done in decorateType */
2552   /* this must be a lvalue */
2553 /*     if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2554 /*  werror (E_LVALUE_REQUIRED,"&"); */
2555 /*  return op; */
2556 /*     } */
2557
2558   p = newLink (DECLARATOR);
2559
2560   /* set the pointer depending on the storage class */
2561   DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
2562
2563   p->next = copyLinkChain (optype);
2564
2565   /* if already a temp */
2566   if (IS_ITEMP (op))
2567     {
2568       setOperandType (op, p);
2569       op->isaddr = 0;
2570       return op;
2571     }
2572
2573   /* other wise make this of the type coming in */
2574   ic = newiCode (ADDRESS_OF, op, NULL);
2575   IC_RESULT (ic) = newiTempOperand (p, 1);
2576   IC_RESULT (ic)->isaddr = 0;
2577   ADDTOCHAIN (ic);
2578   return IC_RESULT (ic);
2579 }
2580 /*-----------------------------------------------------------------*/
2581 /* setOClass - sets the output class depending on the pointer type */
2582 /*-----------------------------------------------------------------*/
2583 void 
2584 setOClass (sym_link * ptr, sym_link * spec)
2585 {
2586   switch (DCL_TYPE (ptr))
2587     {
2588     case POINTER:
2589       SPEC_OCLS (spec) = data;
2590       break;
2591
2592     case GPOINTER:
2593       SPEC_OCLS (spec) = generic;
2594       break;
2595
2596     case FPOINTER:
2597       SPEC_OCLS (spec) = xdata;
2598       break;
2599
2600     case CPOINTER:
2601       SPEC_OCLS (spec) = code;
2602       break;
2603
2604     case IPOINTER:
2605       SPEC_OCLS (spec) = idata;
2606       break;
2607
2608     case PPOINTER:
2609       SPEC_OCLS (spec) = xstack;
2610       break;
2611
2612     case EEPPOINTER:
2613       SPEC_OCLS (spec) = eeprom;
2614       break;
2615
2616     default:
2617       break;
2618
2619     }
2620 }
2621
2622 /*-----------------------------------------------------------------*/
2623 /* geniCodeDerefPtr - dereference pointer with '*'                 */
2624 /*-----------------------------------------------------------------*/
2625 operand *
2626 geniCodeDerefPtr (operand * op,int lvl)
2627 {
2628   sym_link *rtype, *retype;
2629   sym_link *optype = operandType (op);
2630
2631   // if this is an array then array access
2632   if (IS_ARRAY (optype)) {
2633     // don't worry, this will be optimized out later
2634     return geniCodeArray (op, operandFromLit (0), lvl);
2635   }
2636
2637   // just in case someone screws up
2638   wassert (IS_PTR (optype));
2639
2640   if (IS_TRUE_SYMOP (op))
2641     {
2642       op->isaddr = 1;
2643       op = geniCodeRValue (op, TRUE);
2644     }
2645
2646   /* now get rid of the pointer part */
2647   if (isLvaluereq(lvl) && IS_ITEMP (op))
2648     {
2649       retype = getSpec (rtype = copyLinkChain (optype));
2650     }
2651   else
2652     {
2653       retype = getSpec (rtype = copyLinkChain (optype->next));
2654       /* outputclass needs 2b updated */
2655       setOClass (optype, retype);
2656     }
2657   
2658   op->isGptr = IS_GENPTR (optype);
2659
2660   op->isaddr = (IS_PTR (rtype) ||
2661                 IS_STRUCT (rtype) ||
2662                 IS_INT (rtype) ||
2663                 IS_CHAR (rtype) ||
2664                 IS_FLOAT (rtype));
2665
2666   if (!isLvaluereq(lvl))
2667     op = geniCodeRValue (op, TRUE);
2668
2669   setOperandType (op, rtype);
2670
2671   return op;
2672 }
2673
2674 /*-----------------------------------------------------------------*/
2675 /* geniCodeUnaryMinus - does a unary minus of the operand          */
2676 /*-----------------------------------------------------------------*/
2677 operand *
2678 geniCodeUnaryMinus (operand * op)
2679 {
2680   iCode *ic;
2681   sym_link *optype = operandType (op);
2682
2683   if (IS_LITERAL (optype))
2684     return operandFromLit (-floatFromVal (op->operand.valOperand));
2685
2686   ic = newiCode (UNARYMINUS, op, NULL);
2687   IC_RESULT (ic) = newiTempOperand (optype, 0);
2688   ADDTOCHAIN (ic);
2689   return IC_RESULT (ic);
2690 }
2691
2692 /*-----------------------------------------------------------------*/
2693 /* geniCodeLeftShift - gen i code for left shift                   */
2694 /*-----------------------------------------------------------------*/
2695 operand *
2696 geniCodeLeftShift (operand * left, operand * right)
2697 {
2698   iCode *ic;
2699
2700   ic = newiCode (LEFT_OP, left, right);
2701   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2702   ADDTOCHAIN (ic);
2703   return IC_RESULT (ic);
2704 }
2705
2706 /*-----------------------------------------------------------------*/
2707 /* geniCodeRightShift - gen i code for right shift                 */
2708 /*-----------------------------------------------------------------*/
2709 operand *
2710 geniCodeRightShift (operand * left, operand * right)
2711 {
2712   iCode *ic;
2713
2714   ic = newiCode (RIGHT_OP, left, right);
2715   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2716   ADDTOCHAIN (ic);
2717   return IC_RESULT (ic);
2718 }
2719
2720 /*-----------------------------------------------------------------*/
2721 /* geniCodeLogic- logic code                                       */
2722 /*-----------------------------------------------------------------*/
2723 operand *
2724 geniCodeLogic (operand * left, operand * right, int op)
2725 {
2726   iCode *ic;
2727   sym_link *ctype;
2728   sym_link *rtype = operandType (right);
2729   sym_link *ltype = operandType (left);
2730
2731   /* left is integral type and right is literal then
2732      check if the literal value is within bounds */
2733   if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2734     {
2735       checkConstantRange(ltype,
2736                          OP_VALUE(right), "compare operation", 1);
2737     }
2738
2739   /* if one operand is a pointer and the other is a literal generic void pointer,
2740      change the type of the literal generic void pointer to match the other pointer */
2741   if (IS_GENPTR (ltype) && IS_VOID (ltype->next) && IS_ITEMP (left)
2742       && IS_PTR (rtype) && !IS_GENPTR(rtype))
2743     {
2744       /* find left's definition */
2745       ic = (iCode *) setFirstItem (iCodeChain);
2746       while (ic)
2747         {
2748           if (((ic->op == CAST) || (ic->op == '='))
2749               && isOperandEqual(left, IC_RESULT (ic)))
2750             break;
2751           else
2752             ic = setNextItem (iCodeChain);
2753         }
2754       /* if casting literal to generic pointer, then cast to rtype instead */
2755       if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic))) 
2756         {
2757           left = operandFromValue (valCastLiteral (rtype, operandLitValue (IC_RIGHT (ic))));
2758           ltype = operandType(left);
2759         }
2760     }
2761   if (IS_GENPTR (rtype) && IS_VOID (rtype->next) && IS_ITEMP (right)
2762       && IS_PTR (ltype) && !IS_GENPTR(ltype))
2763     {
2764       /* find right's definition */
2765       ic = (iCode *) setFirstItem (iCodeChain);
2766       while (ic)
2767         {
2768           if (((ic->op == CAST) || (ic->op == '='))
2769               && isOperandEqual(right, IC_RESULT (ic)))
2770             break;
2771           else
2772             ic = setNextItem (iCodeChain);
2773         }
2774       /* if casting literal to generic pointer, then cast to rtype instead */
2775       if (ic && (ic->op == CAST) && isOperandLiteral(IC_RIGHT (ic))) 
2776         {
2777           right = operandFromValue (valCastLiteral (ltype, operandLitValue (IC_RIGHT (ic))));
2778           rtype = operandType(right);
2779         }
2780     }
2781
2782   ctype = usualBinaryConversions (&left, &right);
2783
2784   ic = newiCode (op, left, right);
2785   IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2786
2787   /* if comparing float
2788      and not a '==' || '!=' || '&&' || '||' (these
2789      will be inlined */
2790   if (IS_FLOAT(ctype) &&
2791       op != EQ_OP &&
2792       op != NE_OP &&
2793       op != AND_OP &&
2794       op != OR_OP)
2795     ic->supportRtn = 1;
2796
2797   ADDTOCHAIN (ic);
2798   return IC_RESULT (ic);
2799 }
2800
2801 /*-----------------------------------------------------------------*/
2802 /* geniCodeUnary - for a a generic unary operation                 */
2803 /*-----------------------------------------------------------------*/
2804 operand *
2805 geniCodeUnary (operand * op, int oper)
2806 {
2807   iCode *ic = newiCode (oper, op, NULL);
2808
2809   IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2810   ADDTOCHAIN (ic);
2811   return IC_RESULT (ic);
2812 }
2813
2814 /*-----------------------------------------------------------------*/
2815 /* geniCodeConditional - geniCode for '?' ':' operation            */
2816 /*-----------------------------------------------------------------*/
2817 operand *
2818 geniCodeConditional (ast * tree,int lvl)
2819 {
2820   iCode *ic;
2821   symbol *falseLabel = newiTempLabel (NULL);
2822   symbol *exitLabel = newiTempLabel (NULL);
2823   operand *cond = ast2iCode (tree->left,lvl+1);
2824   operand *true, *false, *result;
2825
2826   ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2827                           NULL, falseLabel);
2828   ADDTOCHAIN (ic);
2829
2830   true = ast2iCode (tree->right->left,lvl+1);
2831
2832   /* move the value to a new Operand */
2833   result = newiTempOperand (tree->right->ftype, 0);
2834   geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2835
2836   /* generate an unconditional goto */
2837   geniCodeGoto (exitLabel);
2838
2839   /* now for the right side */
2840   geniCodeLabel (falseLabel);
2841
2842   false = ast2iCode (tree->right->right,lvl+1);
2843   geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2844
2845   /* create the exit label */
2846   geniCodeLabel (exitLabel);
2847
2848   return result;
2849 }
2850
2851 /*-----------------------------------------------------------------*/
2852 /* geniCodeAssign - generate code for assignment                   */
2853 /*-----------------------------------------------------------------*/
2854 operand *
2855 geniCodeAssign (operand * left, operand * right, int nosupdate)
2856 {
2857   iCode *ic;
2858   sym_link *ltype = operandType (left);
2859   sym_link *rtype = operandType (right);
2860
2861   if (!left->isaddr && !IS_ITEMP (left))
2862     {
2863       werror (E_LVALUE_REQUIRED, "assignment");
2864       return left;
2865     }
2866
2867   /* left is integral type and right is literal then
2868      check if the literal value is within bounds */
2869   if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2870     {
2871       checkConstantRange(ltype, 
2872                          OP_VALUE(right), "= operation", 0);
2873     }
2874
2875   /* if the left & right type don't exactly match */
2876   /* if pointer set then make sure the check is
2877      done with the type & not the pointer */
2878   /* then cast rights type to left */
2879
2880   /* first check the type for pointer assignement */
2881   if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2882       compareType (ltype, rtype) <= 0)
2883     {
2884       if (compareType (ltype->next, rtype) < 0)
2885         right = geniCodeCast (ltype->next, right, TRUE);
2886     }
2887   else if (compareType (ltype, rtype) < 0)
2888     right = geniCodeCast (ltype, right, TRUE);
2889
2890   /* If left is a true symbol & ! volatile
2891      create an assignment to temporary for
2892      the right & then assign this temporary
2893      to the symbol. This is SSA (static single
2894      assignment). Isn't it simple and folks have
2895      published mountains of paper on it */
2896   if (IS_TRUE_SYMOP (left) &&
2897       !isOperandVolatile (left, FALSE) &&
2898       isOperandGlobal (left))
2899     {
2900       symbol *sym = NULL;
2901
2902       if (IS_TRUE_SYMOP (right))
2903         sym = OP_SYMBOL (right);
2904       ic = newiCode ('=', NULL, right);
2905       IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2906       SPIL_LOC (right) = sym;
2907       ADDTOCHAIN (ic);
2908     }
2909
2910   ic = newiCode ('=', NULL, right);
2911   IC_RESULT (ic) = left;
2912   ADDTOCHAIN (ic);
2913
2914   /* if left isgptr flag is set then support
2915      routine will be required */
2916   if (left->isGptr)
2917     ic->supportRtn = 1;
2918
2919   ic->nosupdate = nosupdate;
2920   return left;
2921 }
2922
2923 /*-----------------------------------------------------------------*/
2924 /* geniCodeDummyRead - generate code for dummy read                */
2925 /*-----------------------------------------------------------------*/
2926 static void
2927 geniCodeDummyRead (operand * op)
2928 {
2929   iCode *ic;
2930   sym_link *type = operandType (op);
2931
2932   if (!IS_VOLATILE(type))
2933     return;
2934     
2935   ic = newiCode (DUMMY_READ_VOLATILE, NULL, op);
2936   ADDTOCHAIN (ic);
2937
2938   ic->nosupdate = 1;
2939 }
2940
2941 /*-----------------------------------------------------------------*/
2942 /* geniCodeSEParms - generate code for side effecting fcalls       */
2943 /*-----------------------------------------------------------------*/
2944 static void 
2945 geniCodeSEParms (ast * parms,int lvl)
2946 {
2947   if (!parms)
2948     return;
2949
2950   if (parms->type == EX_OP && parms->opval.op == PARAM)
2951     {
2952       geniCodeSEParms (parms->left,lvl);
2953       geniCodeSEParms (parms->right,lvl);
2954       return;
2955     }
2956
2957   /* hack don't like this but too lazy to think of
2958      something better */
2959   if (IS_ADDRESS_OF_OP (parms))
2960     parms->left->lvalue = 1;
2961
2962   if (IS_CAST_OP (parms) &&
2963       IS_PTR (parms->ftype) &&
2964       IS_ADDRESS_OF_OP (parms->right))
2965     parms->right->left->lvalue = 1;
2966
2967   parms->opval.oprnd = 
2968     geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2969                 
2970   parms->type = EX_OPERAND;
2971   AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
2972                 SPEC_ARGREG(parms->ftype);
2973 }
2974
2975 /*-----------------------------------------------------------------*/
2976 /* geniCodeParms - generates parameters                            */
2977 /*-----------------------------------------------------------------*/
2978 value *
2979 geniCodeParms (ast * parms, value *argVals, int *stack, 
2980                sym_link * fetype, symbol * func,int lvl)
2981 {
2982   iCode *ic;
2983   operand *pval;
2984
2985   if (!parms)
2986     return argVals;
2987
2988   if (argVals==NULL) {
2989     // first argument
2990     argVals=FUNC_ARGS(func->type);
2991   }
2992
2993   /* if this is a param node then do the left & right */
2994   if (parms->type == EX_OP && parms->opval.op == PARAM)
2995     {
2996       argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
2997       argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
2998       return argVals;
2999     }
3000
3001   /* get the parameter value */
3002   if (parms->type == EX_OPERAND)
3003     pval = parms->opval.oprnd;
3004   else
3005     {
3006       /* maybe this else should go away ?? */
3007       /* hack don't like this but too lazy to think of
3008          something better */
3009       if (IS_ADDRESS_OF_OP (parms))
3010         parms->left->lvalue = 1;
3011
3012       if (IS_CAST_OP (parms) &&
3013           IS_PTR (parms->ftype) &&
3014           IS_ADDRESS_OF_OP (parms->right))
3015         parms->right->left->lvalue = 1;
3016
3017       pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
3018     }
3019
3020   /* if register parm then make it a send */
3021   if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
3022       IFFUNC_ISBUILTIN(func->type))
3023     {
3024       ic = newiCode (SEND, pval, NULL);
3025       ic->argreg = SPEC_ARGREG(parms->etype);
3026       ic->builtinSEND = FUNC_ISBUILTIN(func->type);
3027       ADDTOCHAIN (ic);
3028     }
3029   else
3030     {
3031       /* now decide whether to push or assign */
3032       if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
3033         {
3034
3035           /* assign */
3036           operand *top = operandFromSymbol (argVals->sym);
3037           /* clear useDef and other bitVectors */
3038           OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
3039           geniCodeAssign (top, pval, 1);
3040         }
3041       else
3042         {
3043           sym_link *p = operandType (pval);
3044           /* push */
3045           ic = newiCode (IPUSH, pval, NULL);
3046           ic->parmPush = 1;
3047           /* update the stack adjustment */
3048           *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
3049           ADDTOCHAIN (ic);
3050         }
3051     }
3052
3053   argVals=argVals->next;
3054   return argVals;
3055 }
3056
3057 /*-----------------------------------------------------------------*/
3058 /* geniCodeCall - generates temp code for calling                  */
3059 /*-----------------------------------------------------------------*/
3060 operand *
3061 geniCodeCall (operand * left, ast * parms,int lvl)
3062 {
3063   iCode *ic;
3064   operand *result;
3065   sym_link *type, *etype;
3066   int stack = 0;
3067
3068   if (!IS_FUNC(OP_SYMBOL(left)->type) && 
3069       !IS_CODEPTR(OP_SYMBOL(left)->type)) {
3070     werror (E_FUNCTION_EXPECTED);
3071     return operandFromValue(valueFromLit(0));
3072   }
3073
3074   /* take care of parameters with side-effecting
3075      function calls in them, this is required to take care
3076      of overlaying function parameters */
3077   geniCodeSEParms (parms,lvl);
3078
3079   /* first the parameters */
3080   geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
3081
3082   /* now call : if symbol then pcall */
3083   if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
3084     ic = newiCode (PCALL, left, NULL);
3085   } else {
3086     ic = newiCode (CALL, left, NULL);
3087   }
3088
3089   type = copyLinkChain (operandType (left)->next);
3090   etype = getSpec (type);
3091   SPEC_EXTR (etype) = 0;
3092   IC_RESULT (ic) = result = newiTempOperand (type, 1);
3093
3094   ADDTOCHAIN (ic);
3095
3096   /* stack adjustment after call */
3097   ic->parmBytes = stack;
3098
3099   return result;
3100 }
3101
3102 /*-----------------------------------------------------------------*/
3103 /* geniCodeReceive - generate intermediate code for "receive"      */
3104 /*-----------------------------------------------------------------*/
3105 static void 
3106 geniCodeReceive (value * args)
3107 {
3108   /* for all arguments that are passed in registers */
3109   while (args)
3110     {
3111       int first = 1;
3112       if (IS_REGPARM (args->etype))
3113         {
3114           operand *opr = operandFromValue (args);
3115           operand *opl;
3116           symbol *sym = OP_SYMBOL (opr);
3117           iCode *ic;
3118
3119           /* we will use it after all optimizations
3120              and before liveRange calculation */
3121           if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
3122             {
3123
3124               if ((IN_FARSPACE (SPEC_OCLS (sym->etype)) && !TARGET_IS_HC08) &&
3125                   options.stackAuto == 0 &&
3126                   (!(options.model == MODEL_FLAT24)) )
3127                 {
3128                 }
3129               else
3130                 {
3131                   opl = newiTempOperand (args->type, 0);
3132                   sym->reqv = opl;
3133                   sym->reqv->key = sym->key;
3134                   OP_SYMBOL (sym->reqv)->key = sym->key;
3135                   OP_SYMBOL (sym->reqv)->isreqv = 1;
3136                   OP_SYMBOL (sym->reqv)->islocal = 0;
3137                   SPIL_LOC (sym->reqv) = sym;
3138                 }
3139             }
3140
3141           ic = newiCode (RECEIVE, NULL, NULL);    
3142           ic->argreg = SPEC_ARGREG(args->etype);
3143           if (first) {
3144               currFunc->recvSize = getSize (sym->type);
3145               first = 0;
3146           }
3147           IC_RESULT (ic) = opr;
3148           ADDTOCHAIN (ic);
3149         }
3150
3151       args = args->next;
3152     }
3153 }
3154
3155 /*-----------------------------------------------------------------*/
3156 /* geniCodeFunctionBody - create the function body                 */
3157 /*-----------------------------------------------------------------*/
3158 void 
3159 geniCodeFunctionBody (ast * tree,int lvl)
3160 {
3161   iCode *ic;
3162   operand *func;
3163   sym_link *fetype;
3164   int savelineno;
3165
3166   /* reset the auto generation */
3167   /* numbers */
3168   iTempNum = 0;
3169   iTempLblNum = 0;
3170   operandKey = 0;
3171   iCodeKey = 0;
3172   func = ast2iCode (tree->left,lvl+1);
3173   fetype = getSpec (operandType (func));
3174
3175   savelineno = lineno;
3176   lineno = OP_SYMBOL (func)->lineDef;
3177   /* create an entry label */
3178   geniCodeLabel (entryLabel);
3179   lineno = savelineno;
3180
3181   /* create a proc icode */
3182   ic = newiCode (FUNCTION, func, NULL);
3183   lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3184
3185   ADDTOCHAIN (ic);
3186
3187   /* for all parameters that are passed
3188      on registers add a "receive" */
3189   geniCodeReceive (tree->values.args);
3190
3191   /* generate code for the body */
3192   ast2iCode (tree->right,lvl+1);
3193
3194   /* create a label for return */
3195   geniCodeLabel (returnLabel);
3196
3197   /* now generate the end proc */
3198   ic = newiCode (ENDFUNCTION, func, NULL);
3199   ADDTOCHAIN (ic);
3200   return;
3201 }
3202
3203 /*-----------------------------------------------------------------*/
3204 /* geniCodeReturn - gen icode for 'return' statement               */
3205 /*-----------------------------------------------------------------*/
3206 void 
3207 geniCodeReturn (operand * op)
3208 {
3209   iCode *ic;
3210
3211   /* if the operand is present force an rvalue */
3212   if (op)
3213     op = geniCodeRValue (op, FALSE);
3214
3215   ic = newiCode (RETURN, op, NULL);
3216   ADDTOCHAIN (ic);
3217 }
3218
3219 /*-----------------------------------------------------------------*/
3220 /* geniCodeIfx - generates code for extended if statement          */
3221 /*-----------------------------------------------------------------*/
3222 void 
3223 geniCodeIfx (ast * tree,int lvl)
3224 {
3225   iCode *ic;
3226   operand *condition = ast2iCode (tree->left,lvl+1);
3227   sym_link *cetype;
3228
3229   /* if condition is null then exit */
3230   if (!condition)
3231     goto exit;
3232   else
3233     condition = geniCodeRValue (condition, FALSE);
3234
3235   cetype = getSpec (operandType (condition));
3236   /* if the condition is a literal */
3237   if (IS_LITERAL (cetype))
3238     {
3239       if (floatFromVal (condition->operand.valOperand))
3240         {
3241           if (tree->trueLabel)
3242             geniCodeGoto (tree->trueLabel);
3243           else
3244             assert (0);
3245         }
3246       else
3247         {
3248           if (tree->falseLabel)
3249             geniCodeGoto (tree->falseLabel);
3250           else
3251             assert (0);
3252         }
3253       goto exit;
3254     }
3255
3256   if (tree->trueLabel)
3257     {
3258       ic = newiCodeCondition (condition,
3259                               tree->trueLabel,
3260                               NULL);
3261       ADDTOCHAIN (ic);
3262
3263       if (tree->falseLabel)
3264         geniCodeGoto (tree->falseLabel);
3265     }
3266   else
3267     {
3268       ic = newiCodeCondition (condition,
3269                               NULL,
3270                               tree->falseLabel);
3271       ADDTOCHAIN (ic);
3272     }
3273
3274 exit:
3275   ast2iCode (tree->right,lvl+1);
3276 }
3277
3278 /*-----------------------------------------------------------------*/
3279 /* geniCodeJumpTable - tries to create a jump table for switch     */
3280 /*-----------------------------------------------------------------*/
3281 int 
3282 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3283 {
3284   int min = 0, max = 0, t, cnt = 0;
3285   value *vch;
3286   iCode *ic;
3287   operand *boundary;
3288   symbol *falseLabel;
3289   set *labels = NULL;
3290   int needRangeCheck = !optimize.noJTabBoundary
3291                        || tree->values.switchVals.swDefault;
3292
3293   if (!tree || !caseVals)
3294     return 0;
3295
3296   /* the criteria for creating a jump table is */
3297   /* all integer numbers between the maximum & minimum must */
3298   /* be present , the maximum value should not exceed 255 */
3299   min = max = (int) floatFromVal (vch = caseVals);
3300   SNPRINTF (buffer, sizeof(buffer), 
3301             "_case_%d_%d",
3302            tree->values.switchVals.swNum,
3303            min);
3304   addSet (&labels, newiTempLabel (buffer));
3305
3306   /* if there is only one case value then no need */
3307   if (!(vch = vch->next))
3308     return 0;
3309
3310   while (vch)
3311     {
3312       if (((t = (int) floatFromVal (vch)) - max) != 1)
3313         return 0;
3314       SNPRINTF (buffer, sizeof(buffer), 
3315                 "_case_%d_%d",
3316                tree->values.switchVals.swNum,
3317                t);
3318       addSet (&labels, newiTempLabel (buffer));
3319       max = t;
3320       cnt++;
3321       vch = vch->next;
3322     }
3323
3324   /* if the number of case statements <= 2 then */
3325   /* it is not economical to create the jump table */
3326   /* since two compares are needed for boundary conditions */
3327   if ((needRangeCheck && cnt <= 2) || max > (255 / 3))
3328     return 0;
3329
3330   if (tree->values.switchVals.swDefault)
3331     {
3332         SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3333     }
3334   else
3335     {
3336         SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3337     }
3338     
3339
3340   falseLabel = newiTempLabel (buffer);
3341
3342   /* so we can create a jumptable */
3343   /* first we rule out the boundary conditions */
3344   /* if only optimization says so */
3345   if (needRangeCheck)
3346     {
3347       sym_link *cetype = getSpec (operandType (cond));
3348       /* no need to check the lower bound if
3349          the condition is unsigned & minimum value is zero */
3350       if (!(min == 0 && SPEC_USIGN (cetype)))
3351         {
3352           boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3353           ic = newiCodeCondition (boundary, falseLabel, NULL);
3354           ADDTOCHAIN (ic);
3355         }
3356
3357       /* now for upper bounds */
3358       boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3359       ic = newiCodeCondition (boundary, falseLabel, NULL);
3360       ADDTOCHAIN (ic);
3361     }
3362
3363   /* if the min is not zero then we no make it zero */
3364   if (min)
3365     {
3366       cond = geniCodeSubtract (cond, operandFromLit (min));
3367       if (!IS_LITERAL(getSpec(operandType(cond))))
3368         setOperandType (cond, UCHARTYPE);
3369     }
3370
3371   /* now create the jumptable */
3372   ic = newiCode (JUMPTABLE, NULL, NULL);
3373   IC_JTCOND (ic) = cond;
3374   IC_JTLABELS (ic) = labels;
3375   ADDTOCHAIN (ic);
3376   return 1;
3377 }
3378
3379 /*-----------------------------------------------------------------*/
3380 /* geniCodeSwitch - changes a switch to a if statement             */
3381 /*-----------------------------------------------------------------*/
3382 void
3383 geniCodeSwitch (ast * tree,int lvl)
3384 {
3385   iCode *ic;
3386   operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3387   value *caseVals = tree->values.switchVals.swVals;
3388   symbol *trueLabel, *falseLabel;
3389       
3390   /* If the condition is a literal, then just jump to the */
3391   /* appropriate case label. */
3392   if (IS_LITERAL(getSpec(operandType(cond))))
3393     {
3394       int switchVal, caseVal;
3395       
3396       switchVal = (int) floatFromVal (cond->operand.valOperand);
3397       while (caseVals)
3398         {
3399           caseVal = (int) floatFromVal (caseVals);
3400           if (caseVal == switchVal)
3401             {
3402               SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3403                         tree->values.switchVals.swNum, caseVal);
3404               trueLabel = newiTempLabel (buffer);
3405               geniCodeGoto (trueLabel);
3406               goto jumpTable;
3407             }
3408           caseVals = caseVals->next;
3409         }
3410       goto defaultOrBreak;
3411     }
3412
3413   /* if we can make this a jump table */
3414   if (geniCodeJumpTable (cond, caseVals, tree))
3415     goto jumpTable;             /* no need for the comparison */
3416
3417   /* for the cases defined do */
3418   while (caseVals)
3419     {
3420
3421       operand *compare = geniCodeLogic (cond,
3422                                         operandFromValue (caseVals),
3423                                         EQ_OP);
3424
3425       SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3426                tree->values.switchVals.swNum,
3427                (int) floatFromVal (caseVals));
3428       trueLabel = newiTempLabel (buffer);
3429
3430       ic = newiCodeCondition (compare, trueLabel, NULL);
3431       ADDTOCHAIN (ic);
3432       caseVals = caseVals->next;
3433     }
3434
3435
3436 defaultOrBreak:
3437   /* if default is present then goto break else break */
3438   if (tree->values.switchVals.swDefault)
3439     {
3440         SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3441     }
3442   else
3443     {
3444         SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3445     }
3446
3447   falseLabel = newiTempLabel (buffer);
3448   geniCodeGoto (falseLabel);
3449
3450 jumpTable:
3451   ast2iCode (tree->right,lvl+1);
3452 }
3453
3454 /*-----------------------------------------------------------------*/
3455 /* geniCodeInline - intermediate code for inline assembler         */
3456 /*-----------------------------------------------------------------*/
3457 static void 
3458 geniCodeInline (ast * tree)
3459 {
3460   iCode *ic;
3461
3462   ic = newiCode (INLINEASM, NULL, NULL);
3463   IC_INLINE (ic) = tree->values.inlineasm;
3464   ADDTOCHAIN (ic);
3465 }
3466
3467 /*-----------------------------------------------------------------*/
3468 /* geniCodeArrayInit - intermediate code for array initializer     */
3469 /*-----------------------------------------------------------------*/
3470 static void 
3471 geniCodeArrayInit (ast * tree, operand *array)
3472 {
3473   iCode *ic;
3474
3475   if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3476     ic = newiCode (ARRAYINIT, array, NULL);
3477     IC_ARRAYILIST (ic) = tree->values.constlist;
3478   } else {
3479     operand *left=newOperand(), *right=newOperand();
3480     left->type=right->type=SYMBOL;
3481     OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3482     OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3483     ic = newiCode (ARRAYINIT, left, right);
3484   }
3485   ADDTOCHAIN (ic);
3486 }
3487         
3488 /*-----------------------------------------------------------------*/
3489 /* geniCodeCritical - intermediate code for a critical statement   */
3490 /*-----------------------------------------------------------------*/
3491 static void 
3492 geniCodeCritical (ast *tree, int lvl)
3493 {
3494   iCode *ic;
3495   operand *op = NULL;
3496
3497   /* If op is NULL, the original interrupt state will saved on */
3498   /* the stack. Otherwise, it will be saved in op. */
3499   
3500   /* Generate a save of the current interrupt state & disabled */
3501   ic = newiCode (CRITICAL, NULL, NULL);
3502   IC_RESULT (ic) = op;
3503   ADDTOCHAIN (ic);
3504   
3505   /* Generate the critical code sequence */
3506   if (tree->left && tree->left->type == EX_VALUE)
3507     geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
3508   else
3509     ast2iCode (tree->left,lvl+1);
3510   
3511   /* Generate a restore of the original interrupt state */
3512   ic = newiCode (ENDCRITICAL, NULL, op);
3513   ADDTOCHAIN (ic);
3514 }
3515
3516 /*-----------------------------------------------------------------*/
3517 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some      */
3518 /* particular case. Ie : assigning or dereferencing array or ptr   */
3519 /*-----------------------------------------------------------------*/
3520 set * lvaluereqSet = NULL;
3521 typedef struct lvalItem
3522   {
3523     int req;
3524     int lvl;
3525   }
3526 lvalItem;
3527
3528 /*-----------------------------------------------------------------*/
3529 /* addLvaluereq - add a flag for lvalreq for current ast level     */
3530 /*-----------------------------------------------------------------*/
3531 void addLvaluereq(int lvl)
3532 {
3533   lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3534   lpItem->req=1;
3535   lpItem->lvl=lvl;
3536   addSetHead(&lvaluereqSet,lpItem);
3537
3538 }
3539 /*-----------------------------------------------------------------*/
3540 /* delLvaluereq - del a flag for lvalreq for current ast level     */
3541 /*-----------------------------------------------------------------*/
3542 void delLvaluereq()
3543 {
3544   lvalItem * lpItem;
3545   lpItem = getSet(&lvaluereqSet);
3546   if(lpItem) Safe_free(lpItem);
3547 }
3548 /*-----------------------------------------------------------------*/
3549 /* clearLvaluereq - clear lvalreq flag                             */
3550 /*-----------------------------------------------------------------*/
3551 void clearLvaluereq()
3552 {
3553   lvalItem * lpItem;
3554   lpItem = peekSet(lvaluereqSet);
3555   if(lpItem) lpItem->req = 0;
3556 }
3557 /*-----------------------------------------------------------------*/
3558 /* getLvaluereq - get the last lvalreq level                       */
3559 /*-----------------------------------------------------------------*/
3560 int getLvaluereqLvl()
3561 {
3562   lvalItem * lpItem;
3563   lpItem = peekSet(lvaluereqSet);
3564   if(lpItem) return lpItem->lvl;
3565   return 0;
3566 }
3567 /*-----------------------------------------------------------------*/
3568 /* isLvaluereq - is lvalreq valid for this level ?                 */
3569 /*-----------------------------------------------------------------*/
3570 int isLvaluereq(int lvl)
3571 {
3572   lvalItem * lpItem;
3573   lpItem = peekSet(lvaluereqSet);
3574   if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3575   return 0;
3576 }
3577
3578 /*-----------------------------------------------------------------*/
3579 /* ast2iCode - creates an icodeList from an ast                    */
3580 /*-----------------------------------------------------------------*/
3581 operand *
3582 ast2iCode (ast * tree,int lvl)
3583 {
3584   operand *left = NULL;
3585   operand *right = NULL;
3586   if (!tree)
3587     return NULL;
3588
3589   /* set the global variables for filename & line number */
3590   if (tree->filename)
3591     filename = tree->filename;
3592   if (tree->lineno)
3593     lineno = tree->lineno;
3594   if (tree->block)
3595     block = tree->block;
3596   if (tree->level)
3597     scopeLevel = tree->level;
3598   if (tree->seqPoint)
3599     seqPoint = tree->seqPoint;
3600
3601   if (tree->type == EX_VALUE)
3602     return operandFromValue (tree->opval.val);
3603
3604   if (tree->type == EX_LINK)
3605     return operandFromLink (tree->opval.lnk);
3606
3607   /* if we find a nullop */
3608   if (tree->type == EX_OP &&
3609      (tree->opval.op == NULLOP ||
3610      tree->opval.op == BLOCK))
3611     {
3612       if (tree->left && tree->left->type == EX_VALUE)
3613         geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
3614       else
3615         ast2iCode (tree->left,lvl+1);
3616       if (tree->right && tree->right->type == EX_VALUE)
3617         geniCodeDummyRead (ast2iCode (tree->right,lvl+1));
3618       else
3619         ast2iCode (tree->right,lvl+1);
3620       return NULL;
3621     }
3622
3623   /* special cases for not evaluating */
3624   if (tree->opval.op != ':' &&
3625       tree->opval.op != '?' &&
3626       tree->opval.op != CALL &&
3627       tree->opval.op != IFX &&
3628       tree->opval.op != LABEL &&
3629       tree->opval.op != GOTO &&
3630       tree->opval.op != SWITCH &&
3631       tree->opval.op != FUNCTION &&
3632       tree->opval.op != INLINEASM &&
3633       tree->opval.op != CRITICAL)
3634     {
3635
3636         if (IS_ASSIGN_OP (tree->opval.op) ||
3637            IS_DEREF_OP (tree) ||
3638            (tree->opval.op == '&' && !tree->right) ||
3639            tree->opval.op == PTR_OP)
3640           {
3641             addLvaluereq(lvl);
3642             if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3643                (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3644               clearLvaluereq();
3645
3646             left = operandFromAst (tree->left,lvl);
3647             delLvaluereq();
3648             if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3649               left = geniCodeRValue (left, TRUE);
3650           }
3651         else
3652           {
3653             left = operandFromAst (tree->left,lvl);
3654           }
3655         if (tree->opval.op == INC_OP ||
3656             tree->opval.op == DEC_OP)
3657           {
3658             addLvaluereq(lvl);
3659             right = operandFromAst (tree->right,lvl);
3660             delLvaluereq();
3661           }
3662         else
3663           {
3664             right = operandFromAst (tree->right,lvl);
3665           }
3666       }
3667
3668   /* now depending on the type of operand */
3669   /* this will be a biggy                 */
3670   switch (tree->opval.op)
3671     {
3672
3673     case '[':                   /* array operation */
3674       {
3675         //sym_link *ltype = operandType (left);
3676         //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3677         left = geniCodeRValue (left, FALSE);
3678         right = geniCodeRValue (right, TRUE);
3679       }
3680
3681       return geniCodeArray (left, right,lvl);
3682
3683     case '.':                   /* structure dereference */
3684       if (IS_PTR (operandType (left)))
3685         left = geniCodeRValue (left, TRUE);
3686       else
3687         left = geniCodeRValue (left, FALSE);
3688
3689       return geniCodeStruct (left, right, tree->lvalue);
3690
3691     case PTR_OP:                /* structure pointer dereference */
3692       {
3693         sym_link *pType;
3694         pType = operandType (left);
3695         left = geniCodeRValue (left, TRUE);
3696
3697         setOClass (pType, getSpec (operandType (left)));
3698       }
3699
3700       return geniCodeStruct (left, right, tree->lvalue);
3701
3702     case INC_OP:                /* increment operator */
3703       if (left)
3704         return geniCodePostInc (left);
3705       else
3706         return geniCodePreInc (right, tree->lvalue);
3707
3708     case DEC_OP:                /* decrement operator */
3709       if (left)
3710         return geniCodePostDec (left);
3711       else
3712         return geniCodePreDec (right, tree->lvalue);
3713
3714     case '&':                   /* bitwise and or address of operator */
3715       if (right)
3716         {                       /* this is a bitwise operator   */
3717           left = geniCodeRValue (left, FALSE);
3718           right = geniCodeRValue (right, FALSE);
3719           return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3720         }
3721       else
3722         return geniCodeAddressOf (left);
3723
3724     case '|':                   /* bitwise or & xor */
3725     case '^':
3726       return geniCodeBitwise (geniCodeRValue (left, FALSE),
3727                               geniCodeRValue (right, FALSE),
3728                               tree->opval.op,
3729                               tree->ftype);
3730
3731     case '/':
3732       return geniCodeDivision (geniCodeRValue (left, FALSE),
3733                                geniCodeRValue (right, FALSE));
3734
3735     case '%':
3736       return geniCodeModulus (geniCodeRValue (left, FALSE),
3737                               geniCodeRValue (right, FALSE));
3738     case '*':
3739       if (right)
3740         return geniCodeMultiply (geniCodeRValue (left, FALSE),
3741                                  geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3742       else
3743         return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3744
3745     case '-':
3746       if (right) 
3747         return geniCodeSubtract (geniCodeRValue (left, FALSE),
3748                                  geniCodeRValue (right, FALSE));
3749       else
3750         return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3751
3752     case '+':
3753       if (right)
3754         return geniCodeAdd (geniCodeRValue (left, FALSE),
3755                             geniCodeRValue (right, FALSE),lvl);
3756       else
3757         return geniCodeRValue (left, FALSE);    /* unary '+' has no meaning */
3758
3759     case LEFT_OP:
3760       return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3761                                 geniCodeRValue (right, FALSE));
3762
3763     case RIGHT_OP:
3764       return geniCodeRightShift (geniCodeRValue (left, FALSE),
3765                                  geniCodeRValue (right, FALSE));
3766     case CAST: 
3767 #if 0 // this indeed needs a second thought
3768       {
3769         operand *op;
3770         
3771         // let's keep this simple: get the rvalue we need
3772         op=geniCodeRValue (right, FALSE);
3773         // now cast it to whatever we want
3774         op=geniCodeCast (operandType(left), op, FALSE);
3775         // if this is going to be used as an lvalue, make it so
3776         if (tree->lvalue) {
3777           op->isaddr=1;
3778         }
3779         return op;
3780       }
3781 #else // bug #604575, is it a bug ????
3782       return geniCodeCast (operandType (left),
3783                            geniCodeRValue (right, FALSE), FALSE);
3784 #endif
3785
3786     case '~':
3787     case RRC:
3788     case RLC:
3789     case SWAP:
3790       return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3791
3792     case '!':
3793     case GETHBIT:
3794       {
3795         operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3796         setOperandType (op, UCHARTYPE);
3797         return op;
3798       }
3799     case '>':
3800     case '<':
3801     case LE_OP:
3802     case GE_OP:
3803     case EQ_OP:
3804     case NE_OP:
3805     case AND_OP:
3806     case OR_OP:
3807       /* different compilers (even different gccs) evaluate
3808          the two calls in a different order. to get the same
3809          result on all machines we've to specify a clear sequence.
3810       return geniCodeLogic (geniCodeRValue (left, FALSE),
3811                             geniCodeRValue (right, FALSE),
3812                             tree->opval.op);
3813       */
3814       {
3815         operand *leftOp, *rightOp;
3816
3817         rightOp = geniCodeRValue (right, FALSE);
3818         leftOp  = geniCodeRValue (left , FALSE);
3819
3820         return geniCodeLogic (leftOp, rightOp, tree->opval.op);
3821       }
3822     case '?':
3823       return geniCodeConditional (tree,lvl);
3824
3825     case SIZEOF:
3826       return operandFromLit (getSize (tree->right->ftype));
3827
3828     case '=':
3829       {
3830         sym_link *rtype = operandType (right);
3831         sym_link *ltype = operandType (left);
3832         if (IS_PTR (rtype) && IS_ITEMP (right)
3833             && right->isaddr && compareType (rtype->next, ltype) == 1)
3834           right = geniCodeRValue (right, TRUE);
3835         else
3836           right = geniCodeRValue (right, FALSE);
3837
3838         geniCodeAssign (left, right, 0);
3839         return right;
3840       }
3841     case MUL_ASSIGN:
3842       return
3843         geniCodeAssign (left,
3844                 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3845                                                   FALSE),
3846                                   geniCodeRValue (right, FALSE),FALSE), 0);
3847
3848     case DIV_ASSIGN:
3849       return
3850         geniCodeAssign (left,
3851                 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3852                                                   FALSE),
3853                                   geniCodeRValue (right, FALSE)), 0);
3854     case MOD_ASSIGN:
3855       return
3856         geniCodeAssign (left,
3857                  geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3858                                                   FALSE),
3859                                   geniCodeRValue (right, FALSE)), 0);
3860     case ADD_ASSIGN:
3861       {
3862         sym_link *rtype = operandType (right);
3863         sym_link *ltype = operandType (left);
3864         if (IS_PTR (rtype) && IS_ITEMP (right)
3865             && right->isaddr && compareType (rtype->next, ltype) == 1)
3866           right = geniCodeRValue (right, TRUE);
3867         else
3868           right = geniCodeRValue (right, FALSE);
3869
3870
3871         return geniCodeAssign (left,
3872                      geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3873                                                   FALSE),
3874                                   right,lvl), 0);
3875       }
3876     case SUB_ASSIGN:
3877       {
3878         sym_link *rtype = operandType (right);
3879         sym_link *ltype = operandType (left);
3880         if (IS_PTR (rtype) && IS_ITEMP (right)
3881             && right->isaddr && compareType (rtype->next, ltype) == 1)
3882           {
3883             right = geniCodeRValue (right, TRUE);
3884           }
3885         else
3886           {
3887             right = geniCodeRValue (right, FALSE);
3888           }
3889         return
3890           geniCodeAssign (left,
3891                 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3892                                                   FALSE),
3893                                   right), 0);
3894       }
3895     case LEFT_ASSIGN:
3896       return
3897         geniCodeAssign (left,
3898                 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3899                                                    ,FALSE),
3900                                    geniCodeRValue (right, FALSE)), 0);
3901     case RIGHT_ASSIGN:
3902       return
3903         geniCodeAssign (left,
3904                geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3905                                                    ,FALSE),
3906                                    geniCodeRValue (right, FALSE)), 0);
3907     case AND_ASSIGN:
3908       return
3909         geniCodeAssign (left,
3910                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3911                                                   FALSE),
3912                                   geniCodeRValue (right, FALSE),
3913                                   BITWISEAND,
3914                                   operandType (left)), 0);
3915     case XOR_ASSIGN:
3916       return
3917         geniCodeAssign (left,
3918                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3919                                                   FALSE),
3920                                   geniCodeRValue (right, FALSE),
3921                                   '^',
3922                                   operandType (left)), 0);
3923     case OR_ASSIGN:
3924       return
3925         geniCodeAssign (left,
3926                   geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3927                                                    ,FALSE),
3928                                    geniCodeRValue (right, FALSE),
3929                                    '|',
3930                                    operandType (left)), 0);
3931     case ',':
3932       return geniCodeRValue (right, FALSE);
3933
3934     case CALL:
3935       return geniCodeCall (ast2iCode (tree->left,lvl+1),
3936                            tree->right,lvl);
3937     case LABEL:
3938       geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3939       return ast2iCode (tree->right,lvl+1);
3940
3941     case GOTO:
3942       geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3943       return ast2iCode (tree->right,lvl+1);
3944
3945     case FUNCTION:
3946       geniCodeFunctionBody (tree,lvl);
3947       return NULL;
3948
3949     case RETURN:
3950       geniCodeReturn (right);
3951       return NULL;
3952
3953     case IFX:
3954       geniCodeIfx (tree,lvl);
3955       return NULL;
3956
3957     case SWITCH:
3958       geniCodeSwitch (tree,lvl);
3959       return NULL;
3960
3961     case INLINEASM:
3962       geniCodeInline (tree);
3963       return NULL;
3964         
3965     case ARRAYINIT:
3966         geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3967         return NULL;
3968     
3969     case CRITICAL:
3970         geniCodeCritical (tree, lvl);    
3971     }
3972
3973   return NULL;
3974 }
3975
3976 /*-----------------------------------------------------------------*/
3977 /* reverseICChain - gets from the list and creates a linkedlist    */
3978 /*-----------------------------------------------------------------*/
3979 iCode *
3980 reverseiCChain ()
3981 {
3982   iCode *loop = NULL;
3983   iCode *prev = NULL;
3984
3985   while ((loop = getSet (&iCodeChain)))
3986     {
3987       loop->next = prev;
3988       if (prev)
3989         prev->prev = loop;
3990       prev = loop;
3991     }
3992
3993   return prev;
3994 }
3995
3996
3997 /*-----------------------------------------------------------------*/
3998 /* iCodeFromAst - given an ast will convert it to iCode            */
3999 /*-----------------------------------------------------------------*/
4000 iCode *
4001 iCodeFromAst (ast * tree)
4002 {
4003   returnLabel = newiTempLabel ("_return");
4004   entryLabel = newiTempLabel ("_entry");
4005   ast2iCode (tree,0);
4006   return reverseiCChain ();
4007 }
4008
4009 static const char *opTypeToStr(OPTYPE op)
4010 {
4011     switch(op)
4012     {
4013       case SYMBOL: return "symbol";
4014       case VALUE: return "value";
4015       case TYPE: return "type";
4016     }
4017     return "undefined type";    
4018 }
4019
4020
4021 operand *validateOpType(operand         *op, 
4022                         const char      *macro,
4023                         const char      *args,
4024                         OPTYPE          type,
4025                         const char      *file, 
4026                         unsigned        line)
4027 {    
4028     if (op && op->type == type)
4029     {
4030         return op;
4031     }
4032     fprintf(stderr, 
4033             "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
4034             " expected %s, got %s\n",
4035             macro, args, file, line, 
4036             opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
4037     exit(-1);
4038     return op; // never reached, makes compiler happy.
4039 }