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