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