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