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