some prelimanary floating point fixes
[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   // bitwise operations must be done unsigned
2295   SPEC_USIGN(resType)=1;
2296
2297   left = geniCodeCast (resType, left, TRUE);
2298   right = geniCodeCast (resType, right, TRUE);
2299
2300   ic = newiCode (oper, left, right);
2301   IC_RESULT (ic) = newiTempOperand (resType, 0);
2302
2303   ADDTOCHAIN (ic);
2304   return IC_RESULT (ic);
2305 }
2306
2307 /*-----------------------------------------------------------------*/
2308 /* geniCodeAddressOf - gens icode for '&' address of operator      */
2309 /*-----------------------------------------------------------------*/
2310 operand *
2311 geniCodeAddressOf (operand * op)
2312 {
2313   iCode *ic;
2314   sym_link *p;
2315   sym_link *optype = operandType (op);
2316   sym_link *opetype = getSpec (optype);
2317
2318   /* lvalue check already done in decorateType */
2319   /* this must be a lvalue */
2320 /*     if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2321 /*  werror (E_LVALUE_REQUIRED,"&"); */
2322 /*  return op; */
2323 /*     } */
2324
2325   p = newLink ();
2326   p->class = DECLARATOR;
2327
2328   /* set the pointer depending on the storage class */
2329   if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2330     DCL_PTR_CONST (p) = port->mem.code_ro;
2331
2332   /* make sure we preserve the const & volatile */
2333   if (IS_CONSTANT (opetype))
2334     DCL_PTR_CONST (p) = 1;
2335
2336   if (IS_VOLATILE (opetype))
2337     DCL_PTR_VOLATILE (p) = 1;
2338
2339   p->next = copyLinkChain (optype);
2340
2341   /* if already a temp */
2342   if (IS_ITEMP (op))
2343     {
2344       setOperandType (op, p);
2345       op->isaddr = 0;
2346       return op;
2347     }
2348
2349   /* other wise make this of the type coming in */
2350   ic = newiCode (ADDRESS_OF, op, NULL);
2351   IC_RESULT (ic) = newiTempOperand (p, 1);
2352   IC_RESULT (ic)->isaddr = 0;
2353   ADDTOCHAIN (ic);
2354   return IC_RESULT (ic);
2355 }
2356 /*-----------------------------------------------------------------*/
2357 /* setOClass - sets the output class depending on the pointer type */
2358 /*-----------------------------------------------------------------*/
2359 void 
2360 setOClass (sym_link * ptr, sym_link * spec)
2361 {
2362   switch (DCL_TYPE (ptr))
2363     {
2364     case POINTER:
2365       SPEC_OCLS (spec) = data;
2366       break;
2367
2368     case GPOINTER:
2369       SPEC_OCLS (spec) = generic;
2370       break;
2371
2372     case FPOINTER:
2373       SPEC_OCLS (spec) = xdata;
2374       break;
2375
2376     case CPOINTER:
2377       SPEC_OCLS (spec) = code;
2378       break;
2379
2380     case IPOINTER:
2381       SPEC_OCLS (spec) = idata;
2382       break;
2383
2384     case PPOINTER:
2385       SPEC_OCLS (spec) = xstack;
2386       break;
2387
2388     case EEPPOINTER:
2389       SPEC_OCLS (spec) = eeprom;
2390       break;
2391
2392     default:
2393       break;
2394
2395     }
2396 }
2397
2398 /*-----------------------------------------------------------------*/
2399 /* geniCodeDerefPtr - dereference pointer with '*'                 */
2400 /*-----------------------------------------------------------------*/
2401 operand *
2402 geniCodeDerefPtr (operand * op,int lvl)
2403 {
2404   sym_link *rtype, *retype;
2405   sym_link *optype = operandType (op);
2406
2407   /* if this is a pointer then generate the rvalue */
2408   if (IS_PTR (optype))
2409     {
2410       if (IS_TRUE_SYMOP (op))
2411         {
2412           op->isaddr = 1;
2413           op = geniCodeRValue (op, TRUE);
2414         }
2415       else
2416         op = geniCodeRValue (op, TRUE);
2417     }
2418
2419   /* now get rid of the pointer part */
2420   if (isLvaluereq(lvl) && IS_ITEMP (op))
2421     {
2422       retype = getSpec (rtype = copyLinkChain (optype));
2423     }
2424   else
2425     {
2426       retype = getSpec (rtype = copyLinkChain (optype->next));
2427     }
2428
2429   /* if this is a pointer then outputclass needs 2b updated */
2430   if (IS_PTR (optype))
2431     setOClass (optype, retype);
2432
2433   op->isGptr = IS_GENPTR (optype);
2434
2435   /* if the pointer was declared as a constant */
2436   /* then we cannot allow assignment to the derefed */
2437   if (IS_PTR_CONST (optype))
2438     SPEC_CONST (retype) = 1;
2439
2440   op->isaddr = (IS_PTR (rtype) ||
2441                 IS_STRUCT (rtype) ||
2442                 IS_INT (rtype) ||
2443                 IS_CHAR (rtype) ||
2444                 IS_FLOAT (rtype));
2445
2446   if (!isLvaluereq(lvl))
2447     op = geniCodeRValue (op, TRUE);
2448
2449   setOperandType (op, rtype);
2450
2451   return op;
2452 }
2453
2454 /*-----------------------------------------------------------------*/
2455 /* geniCodeUnaryMinus - does a unary minus of the operand          */
2456 /*-----------------------------------------------------------------*/
2457 operand *
2458 geniCodeUnaryMinus (operand * op)
2459 {
2460   iCode *ic;
2461   sym_link *optype = operandType (op);
2462
2463   if (IS_LITERAL (optype))
2464     return operandFromLit (-floatFromVal (op->operand.valOperand));
2465
2466   ic = newiCode (UNARYMINUS, op, NULL);
2467   IC_RESULT (ic) = newiTempOperand (optype, 0);
2468   ADDTOCHAIN (ic);
2469   return IC_RESULT (ic);
2470 }
2471
2472 /*-----------------------------------------------------------------*/
2473 /* geniCodeLeftShift - gen i code for left shift                   */
2474 /*-----------------------------------------------------------------*/
2475 operand *
2476 geniCodeLeftShift (operand * left, operand * right)
2477 {
2478   iCode *ic;
2479
2480   ic = newiCode (LEFT_OP, left, right);
2481   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2482   ADDTOCHAIN (ic);
2483   return IC_RESULT (ic);
2484 }
2485
2486 /*-----------------------------------------------------------------*/
2487 /* geniCodeRightShift - gen i code for right shift                 */
2488 /*-----------------------------------------------------------------*/
2489 operand *
2490 geniCodeRightShift (operand * left, operand * right)
2491 {
2492   iCode *ic;
2493
2494   ic = newiCode (RIGHT_OP, left, right);
2495   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2496   ADDTOCHAIN (ic);
2497   return IC_RESULT (ic);
2498 }
2499
2500 /*-----------------------------------------------------------------*/
2501 /* geniCodeLogic- logic code                                       */
2502 /*-----------------------------------------------------------------*/
2503 operand *
2504 geniCodeLogic (operand * left, operand * right, int op)
2505 {
2506   iCode *ic;
2507   sym_link *ctype;
2508   sym_link *rtype = operandType (right);
2509   sym_link *ltype = operandType (left);
2510
2511   /* left is integral type and right is literal then
2512      check if the literal value is within bounds */
2513   if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2514     {
2515       checkConstantRange(ltype, 
2516                          OP_VALUE(right), "compare operation", 1);
2517     }
2518
2519   ctype = usualBinaryConversions (&left, &right);
2520
2521   ic = newiCode (op, left, right);
2522   IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2523
2524   /* if comparing float
2525      and not a '==' || '!=' || '&&' || '||' (these
2526      will be inlined */
2527   if (IS_FLOAT(ctype) &&
2528       op != EQ_OP &&
2529       op != NE_OP &&
2530       op != AND_OP &&
2531       op != OR_OP)
2532     ic->supportRtn = 1;
2533
2534   ADDTOCHAIN (ic);
2535   return IC_RESULT (ic);
2536 }
2537
2538 /*-----------------------------------------------------------------*/
2539 /* geniCodeUnary - for a a generic unary operation                 */
2540 /*-----------------------------------------------------------------*/
2541 operand *
2542 geniCodeUnary (operand * op, int oper)
2543 {
2544   iCode *ic = newiCode (oper, op, NULL);
2545
2546   IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2547   ADDTOCHAIN (ic);
2548   return IC_RESULT (ic);
2549 }
2550
2551 /*-----------------------------------------------------------------*/
2552 /* geniCodeConditional - geniCode for '?' ':' operation            */
2553 /*-----------------------------------------------------------------*/
2554 operand *
2555 geniCodeConditional (ast * tree,int lvl)
2556 {
2557   iCode *ic;
2558   symbol *falseLabel = newiTempLabel (NULL);
2559   symbol *exitLabel = newiTempLabel (NULL);
2560   operand *cond = ast2iCode (tree->left,lvl+1);
2561   operand *true, *false, *result;
2562
2563   ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2564                           NULL, falseLabel);
2565   ADDTOCHAIN (ic);
2566
2567   true = ast2iCode (tree->right->left,lvl+1);
2568
2569   /* move the value to a new Operand */
2570   result = newiTempOperand (operandType (true), 0);
2571   geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2572
2573   /* generate an unconditional goto */
2574   geniCodeGoto (exitLabel);
2575
2576   /* now for the right side */
2577   geniCodeLabel (falseLabel);
2578
2579   false = ast2iCode (tree->right->right,lvl+1);
2580   geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2581
2582   /* create the exit label */
2583   geniCodeLabel (exitLabel);
2584
2585   return result;
2586 }
2587
2588 /*-----------------------------------------------------------------*/
2589 /* geniCodeAssign - generate code for assignment                   */
2590 /*-----------------------------------------------------------------*/
2591 operand *
2592 geniCodeAssign (operand * left, operand * right, int nosupdate)
2593 {
2594   iCode *ic;
2595   sym_link *ltype = operandType (left);
2596   sym_link *rtype = operandType (right);
2597
2598   if (!left->isaddr && !IS_ITEMP (left))
2599     {
2600       werror (E_LVALUE_REQUIRED, "assignment");
2601       return left;
2602     }
2603
2604   /* left is integral type and right is literal then
2605      check if the literal value is within bounds */
2606   if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2607     {
2608       checkConstantRange(ltype, 
2609                          OP_VALUE(right), "= operation", 0);
2610     }
2611
2612   /* if the left & right type don't exactly match */
2613   /* if pointer set then make sure the check is
2614      done with the type & not the pointer */
2615   /* then cast rights type to left */
2616
2617   /* first check the type for pointer assignement */
2618   if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2619       compareType (ltype, rtype) <= 0)
2620     {
2621       if (compareType (ltype->next, rtype) < 0)
2622         right = geniCodeCast (ltype->next, right, TRUE);
2623     }
2624   else if (compareType (ltype, rtype) < 0)
2625     right = geniCodeCast (ltype, right, TRUE);
2626
2627   /* if left is a true symbol & ! volatile
2628      create an assignment to temporary for
2629      the right & then assign this temporary
2630      to the symbol this is SSA . isn't it simple
2631      and folks have published mountains of paper on it */
2632   if (IS_TRUE_SYMOP (left) &&
2633       !isOperandVolatile (left, FALSE) &&
2634       isOperandGlobal (left))
2635     {
2636       symbol *sym = NULL;
2637
2638       if (IS_TRUE_SYMOP (right))
2639         sym = OP_SYMBOL (right);
2640       ic = newiCode ('=', NULL, right);
2641       IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2642       SPIL_LOC (right) = sym;
2643       ADDTOCHAIN (ic);
2644     }
2645
2646   ic = newiCode ('=', NULL, right);
2647   IC_RESULT (ic) = left;
2648   ADDTOCHAIN (ic);
2649
2650   /* if left isgptr flag is set then support
2651      routine will be required */
2652   if (left->isGptr)
2653     ic->supportRtn = 1;
2654
2655   ic->nosupdate = nosupdate;
2656   return left;
2657 }
2658
2659 /*-----------------------------------------------------------------*/
2660 /* geniCodeSEParms - generate code for side effecting fcalls       */
2661 /*-----------------------------------------------------------------*/
2662 static void 
2663 geniCodeSEParms (ast * parms,int lvl)
2664 {
2665   if (!parms)
2666     return;
2667
2668   if (parms->type == EX_OP && parms->opval.op == PARAM)
2669     {
2670       geniCodeSEParms (parms->left,lvl);
2671       geniCodeSEParms (parms->right,lvl);
2672       return;
2673     }
2674
2675   /* hack don't like this but too lazy to think of
2676      something better */
2677   if (IS_ADDRESS_OF_OP (parms))
2678     parms->left->lvalue = 1;
2679
2680   if (IS_CAST_OP (parms) &&
2681       IS_PTR (parms->ftype) &&
2682       IS_ADDRESS_OF_OP (parms->right))
2683     parms->right->left->lvalue = 1;
2684
2685   parms->opval.oprnd =
2686     geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2687
2688   parms->type = EX_OPERAND;
2689 }
2690
2691 /*-----------------------------------------------------------------*/
2692 /* geniCodeParms - generates parameters                            */
2693 /*-----------------------------------------------------------------*/
2694 value *
2695 geniCodeParms (ast * parms, value *argVals, int *stack, 
2696                sym_link * fetype, symbol * func,int lvl)
2697 {
2698   iCode *ic;
2699   operand *pval;
2700
2701   if (!parms)
2702     return argVals;
2703
2704   if (argVals==NULL) {
2705     // first argument
2706     argVals=FUNC_ARGS(func->type);
2707   }
2708
2709   /* if this is a param node then do the left & right */
2710   if (parms->type == EX_OP && parms->opval.op == PARAM)
2711     {
2712       argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
2713       argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
2714       return argVals;
2715     }
2716
2717   /* get the parameter value */
2718   if (parms->type == EX_OPERAND)
2719     pval = parms->opval.oprnd;
2720   else
2721     {
2722       /* maybe this else should go away ?? */
2723       /* hack don't like this but too lazy to think of
2724          something better */
2725       if (IS_ADDRESS_OF_OP (parms))
2726         parms->left->lvalue = 1;
2727
2728       if (IS_CAST_OP (parms) &&
2729           IS_PTR (parms->ftype) &&
2730           IS_ADDRESS_OF_OP (parms->right))
2731         parms->right->left->lvalue = 1;
2732
2733       pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2734     }
2735
2736   /* if register parm then make it a send */
2737   if (IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type))
2738     {
2739       ic = newiCode (SEND, pval, NULL);
2740       ADDTOCHAIN (ic);
2741     }
2742   else
2743     {
2744       /* now decide whether to push or assign */
2745       if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
2746         {
2747
2748           /* assign */
2749           operand *top = operandFromSymbol (argVals->sym);
2750           geniCodeAssign (top, pval, 1);
2751         }
2752       else
2753         {
2754           sym_link *p = operandType (pval);
2755           /* push */
2756           ic = newiCode (IPUSH, pval, NULL);
2757           ic->parmPush = 1;
2758           /* update the stack adjustment */
2759           *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2760           ADDTOCHAIN (ic);
2761         }
2762     }
2763
2764   argVals=argVals->next;
2765   return argVals;
2766 }
2767
2768 /*-----------------------------------------------------------------*/
2769 /* geniCodeCall - generates temp code for calling                  */
2770 /*-----------------------------------------------------------------*/
2771 operand *
2772 geniCodeCall (operand * left, ast * parms,int lvl)
2773 {
2774   iCode *ic;
2775   operand *result;
2776   sym_link *type, *etype;
2777   int stack = 0;
2778
2779   if (!IS_FUNC(OP_SYMBOL(left)->type) && 
2780       !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2781     werror (E_FUNCTION_EXPECTED);
2782     return NULL;
2783   }
2784
2785   /* take care of parameters with side-effecting
2786      function calls in them, this is required to take care
2787      of overlaying function parameters */
2788   geniCodeSEParms (parms,lvl);
2789
2790   /* first the parameters */
2791   geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2792
2793   /* now call : if symbol then pcall */
2794   if (IS_OP_POINTER (left) || IS_ITEMP(left))
2795     ic = newiCode (PCALL, left, NULL);
2796   else
2797     ic = newiCode (CALL, left, NULL);
2798
2799   type = copyLinkChain (operandType (left)->next);
2800   etype = getSpec (type);
2801   SPEC_EXTR (etype) = 0;
2802   IC_RESULT (ic) = result = newiTempOperand (type, 1);
2803
2804   ADDTOCHAIN (ic);
2805
2806   /* stack adjustment after call */
2807   ic->parmBytes = stack;
2808
2809   return result;
2810 }
2811
2812 /*-----------------------------------------------------------------*/
2813 /* geniCodeReceive - generate intermediate code for "receive"      */
2814 /*-----------------------------------------------------------------*/
2815 static void 
2816 geniCodeReceive (value * args)
2817 {
2818   /* for all arguments that are passed in registers */
2819   while (args)
2820     {
2821
2822       if (IS_REGPARM (args->etype))
2823         {
2824           operand *opr = operandFromValue (args);
2825           operand *opl;
2826           symbol *sym = OP_SYMBOL (opr);
2827           iCode *ic;
2828
2829           /* we will use it after all optimizations
2830              and before liveRange calculation */
2831           if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2832             {
2833
2834               if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2835                   options.stackAuto == 0 &&
2836                   /* !TARGET_IS_DS390) */
2837                   (!(options.model == MODEL_FLAT24)) )
2838                 {
2839                 }
2840               else
2841                 {
2842                   opl = newiTempOperand (args->type, 0);
2843                   sym->reqv = opl;
2844                   sym->reqv->key = sym->key;
2845                   OP_SYMBOL (sym->reqv)->key = sym->key;
2846                   OP_SYMBOL (sym->reqv)->isreqv = 1;
2847                   OP_SYMBOL (sym->reqv)->islocal = 0;
2848                   SPIL_LOC (sym->reqv) = sym;
2849                 }
2850             }
2851
2852           ic = newiCode (RECEIVE, NULL, NULL);
2853           currFunc->recvSize = getSize (sym->etype);
2854           IC_RESULT (ic) = opr;
2855           ADDTOCHAIN (ic);
2856         }
2857
2858       args = args->next;
2859     }
2860 }
2861
2862 /*-----------------------------------------------------------------*/
2863 /* geniCodeFunctionBody - create the function body                 */
2864 /*-----------------------------------------------------------------*/
2865 void 
2866 geniCodeFunctionBody (ast * tree,int lvl)
2867 {
2868   iCode *ic;
2869   operand *func;
2870   sym_link *fetype;
2871   int savelineno;
2872
2873   /* reset the auto generation */
2874   /* numbers */
2875   iTempNum = 0;
2876   iTempLblNum = 0;
2877   operandKey = 0;
2878   iCodeKey = 0;
2879   func = ast2iCode (tree->left,lvl+1);
2880   fetype = getSpec (operandType (func));
2881
2882   savelineno = lineno;
2883   lineno = OP_SYMBOL (func)->lineDef;
2884   /* create an entry label */
2885   geniCodeLabel (entryLabel);
2886   lineno = savelineno;
2887
2888   /* create a proc icode */
2889   ic = newiCode (FUNCTION, func, NULL);
2890   ic->lineno = OP_SYMBOL (func)->lineDef;
2891
2892   ADDTOCHAIN (ic);
2893
2894   /* for all parameters that are passed
2895      on registers add a "receive" */
2896   geniCodeReceive (tree->values.args);
2897
2898   /* generate code for the body */
2899   ast2iCode (tree->right,lvl+1);
2900
2901   /* create a label for return */
2902   geniCodeLabel (returnLabel);
2903
2904   /* now generate the end proc */
2905   ic = newiCode (ENDFUNCTION, func, NULL);
2906   ADDTOCHAIN (ic);
2907   return;
2908 }
2909
2910 /*-----------------------------------------------------------------*/
2911 /* geniCodeReturn - gen icode for 'return' statement               */
2912 /*-----------------------------------------------------------------*/
2913 void 
2914 geniCodeReturn (operand * op)
2915 {
2916   iCode *ic;
2917
2918   /* if the operand is present force an rvalue */
2919   if (op)
2920     op = geniCodeRValue (op, FALSE);
2921
2922   ic = newiCode (RETURN, op, NULL);
2923   ADDTOCHAIN (ic);
2924 }
2925
2926 /*-----------------------------------------------------------------*/
2927 /* geniCodeIfx - generates code for extended if statement          */
2928 /*-----------------------------------------------------------------*/
2929 void 
2930 geniCodeIfx (ast * tree,int lvl)
2931 {
2932   iCode *ic;
2933   operand *condition = ast2iCode (tree->left,lvl+1);
2934   sym_link *cetype;
2935
2936   /* if condition is null then exit */
2937   if (!condition)
2938     goto exit;
2939   else
2940     condition = geniCodeRValue (condition, FALSE);
2941
2942   cetype = getSpec (operandType (condition));
2943   /* if the condition is a literal */
2944   if (IS_LITERAL (cetype))
2945     {
2946       if (floatFromVal (condition->operand.valOperand))
2947         {
2948           if (tree->trueLabel)
2949             geniCodeGoto (tree->trueLabel);
2950           else
2951             assert (0);
2952         }
2953       else
2954         {
2955           if (tree->falseLabel)
2956             geniCodeGoto (tree->falseLabel);
2957           else
2958             assert (0);
2959         }
2960       goto exit;
2961     }
2962
2963   if (tree->trueLabel)
2964     {
2965       ic = newiCodeCondition (condition,
2966                               tree->trueLabel,
2967                               NULL);
2968       ADDTOCHAIN (ic);
2969
2970       if (tree->falseLabel)
2971         geniCodeGoto (tree->falseLabel);
2972     }
2973   else
2974     {
2975       ic = newiCodeCondition (condition,
2976                               NULL,
2977                               tree->falseLabel);
2978       ADDTOCHAIN (ic);
2979     }
2980
2981 exit:
2982   ast2iCode (tree->right,lvl+1);
2983 }
2984
2985 /*-----------------------------------------------------------------*/
2986 /* geniCodeJumpTable - tries to create a jump table for switch     */
2987 /*-----------------------------------------------------------------*/
2988 int 
2989 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
2990 {
2991   int min = 0, max = 0, t, cnt = 0;
2992   value *vch;
2993   iCode *ic;
2994   operand *boundary;
2995   symbol *falseLabel;
2996   set *labels = NULL;
2997
2998   if (!tree || !caseVals)
2999     return 0;
3000
3001   /* the criteria for creating a jump table is */
3002   /* all integer numbers between the maximum & minimum must */
3003   /* be present , the maximum value should not exceed 255 */
3004   min = max = (int) floatFromVal (vch = caseVals);
3005   sprintf (buffer, "_case_%d_%d",
3006            tree->values.switchVals.swNum,
3007            min);
3008   addSet (&labels, newiTempLabel (buffer));
3009
3010   /* if there is only one case value then no need */
3011   if (!(vch = vch->next))
3012     return 0;
3013
3014   while (vch)
3015     {
3016       if (((t = (int) floatFromVal (vch)) - max) != 1)
3017         return 0;
3018       sprintf (buffer, "_case_%d_%d",
3019                tree->values.switchVals.swNum,
3020                t);
3021       addSet (&labels, newiTempLabel (buffer));
3022       max = t;
3023       cnt++;
3024       vch = vch->next;
3025     }
3026
3027   /* if the number of case statements <= 2 then */
3028   /* it is not economical to create the jump table */
3029   /* since two compares are needed for boundary conditions */
3030   if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3031     return 0;
3032
3033   if (tree->values.switchVals.swDefault)
3034     sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3035   else
3036     sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3037
3038   falseLabel = newiTempLabel (buffer);
3039
3040   /* so we can create a jumptable */
3041   /* first we rule out the boundary conditions */
3042   /* if only optimization says so */
3043   if (!optimize.noJTabBoundary)
3044     {
3045       sym_link *cetype = getSpec (operandType (cond));
3046       /* no need to check the lower bound if
3047          the condition is unsigned & minimum value is zero */
3048       if (!(min == 0 && SPEC_USIGN (cetype)))
3049         {
3050           boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3051           ic = newiCodeCondition (boundary, falseLabel, NULL);
3052           ADDTOCHAIN (ic);
3053         }
3054
3055       /* now for upper bounds */
3056       boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3057       ic = newiCodeCondition (boundary, falseLabel, NULL);
3058       ADDTOCHAIN (ic);
3059     }
3060
3061   /* if the min is not zero then we no make it zero */
3062   if (min)
3063     {
3064       cond = geniCodeSubtract (cond, operandFromLit (min));
3065       setOperandType (cond, UCHARTYPE);
3066     }
3067
3068   /* now create the jumptable */
3069   ic = newiCode (JUMPTABLE, NULL, NULL);
3070   IC_JTCOND (ic) = cond;
3071   IC_JTLABELS (ic) = labels;
3072   ADDTOCHAIN (ic);
3073   return 1;
3074 }
3075
3076 /*-----------------------------------------------------------------*/
3077 /* geniCodeSwitch - changes a switch to a if statement             */
3078 /*-----------------------------------------------------------------*/
3079 void 
3080 geniCodeSwitch (ast * tree,int lvl)
3081 {
3082   iCode *ic;
3083   operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3084   value *caseVals = tree->values.switchVals.swVals;
3085   symbol *trueLabel, *falseLabel;
3086
3087   /* if we can make this a jump table */
3088   if (geniCodeJumpTable (cond, caseVals, tree))
3089     goto jumpTable;             /* no need for the comparison */
3090
3091   /* for the cases defined do */
3092   while (caseVals)
3093     {
3094
3095       operand *compare = geniCodeLogic (cond,
3096                                         operandFromValue (caseVals),
3097                                         EQ_OP);
3098
3099       sprintf (buffer, "_case_%d_%d",
3100                tree->values.switchVals.swNum,
3101                (int) floatFromVal (caseVals));
3102       trueLabel = newiTempLabel (buffer);
3103
3104       ic = newiCodeCondition (compare, trueLabel, NULL);
3105       ADDTOCHAIN (ic);
3106       caseVals = caseVals->next;
3107     }
3108
3109
3110
3111   /* if default is present then goto break else break */
3112   if (tree->values.switchVals.swDefault)
3113     sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3114   else
3115     sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3116
3117   falseLabel = newiTempLabel (buffer);
3118   geniCodeGoto (falseLabel);
3119
3120 jumpTable:
3121   ast2iCode (tree->right,lvl+1);
3122 }
3123
3124 /*-----------------------------------------------------------------*/
3125 /* geniCodeInline - intermediate code for inline assembler         */
3126 /*-----------------------------------------------------------------*/
3127 static void 
3128 geniCodeInline (ast * tree)
3129 {
3130   iCode *ic;
3131
3132   ic = newiCode (INLINEASM, NULL, NULL);
3133   IC_INLINE (ic) = tree->values.inlineasm;
3134   ADDTOCHAIN (ic);
3135 }
3136
3137 /*-----------------------------------------------------------------*/
3138 /* geniCodeArrayInit - intermediate code for array initializer     */
3139 /*-----------------------------------------------------------------*/
3140 static void 
3141 geniCodeArrayInit (ast * tree, operand *array)
3142 {
3143   iCode *ic;
3144
3145   if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3146     ic = newiCode (ARRAYINIT, array, NULL);
3147     IC_ARRAYILIST (ic) = tree->values.constlist;
3148   } else {
3149     operand *left=newOperand(), *right=newOperand();
3150     left->type=right->type=SYMBOL;
3151     OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3152     OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3153     ic = newiCode (ARRAYINIT, left, right);
3154   }
3155   ADDTOCHAIN (ic);
3156 }
3157
3158 /*-----------------------------------------------------------------*/
3159 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some      */
3160 /* particular case. Ie : assigning or dereferencing array or ptr   */
3161 /*-----------------------------------------------------------------*/
3162 set * lvaluereqSet = NULL;
3163 typedef struct lvalItem
3164   {
3165     int req;
3166     int lvl;
3167   }
3168 lvalItem;
3169
3170 /*-----------------------------------------------------------------*/
3171 /* addLvaluereq - add a flag for lvalreq for current ast level     */
3172 /*-----------------------------------------------------------------*/
3173 void addLvaluereq(int lvl)
3174 {
3175   lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3176   lpItem->req=1;
3177   lpItem->lvl=lvl;
3178   addSetHead(&lvaluereqSet,lpItem);
3179
3180 }
3181 /*-----------------------------------------------------------------*/
3182 /* delLvaluereq - del a flag for lvalreq for current ast level     */
3183 /*-----------------------------------------------------------------*/
3184 void delLvaluereq()
3185 {
3186   lvalItem * lpItem;
3187   lpItem = getSet(&lvaluereqSet);
3188   if(lpItem) Safe_free(lpItem);
3189 }
3190 /*-----------------------------------------------------------------*/
3191 /* clearLvaluereq - clear lvalreq flag                             */
3192 /*-----------------------------------------------------------------*/
3193 void clearLvaluereq()
3194 {
3195   lvalItem * lpItem;
3196   lpItem = peekSet(lvaluereqSet);
3197   if(lpItem) lpItem->req = 0;
3198 }
3199 /*-----------------------------------------------------------------*/
3200 /* getLvaluereq - get the last lvalreq level                       */
3201 /*-----------------------------------------------------------------*/
3202 int getLvaluereqLvl()
3203 {
3204   lvalItem * lpItem;
3205   lpItem = peekSet(lvaluereqSet);
3206   if(lpItem) return lpItem->lvl;
3207   return 0;
3208 }
3209 /*-----------------------------------------------------------------*/
3210 /* isLvaluereq - is lvalreq valid for this level ?                 */
3211 /*-----------------------------------------------------------------*/
3212 int isLvaluereq(int lvl)
3213 {
3214   lvalItem * lpItem;
3215   lpItem = peekSet(lvaluereqSet);
3216   if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3217   return 0;
3218 }
3219
3220 /*-----------------------------------------------------------------*/
3221 /* ast2iCode - creates an icodeList from an ast                    */
3222 /*-----------------------------------------------------------------*/
3223 operand *
3224 ast2iCode (ast * tree,int lvl)
3225 {
3226   operand *left = NULL;
3227   operand *right = NULL;
3228   if (!tree)
3229     return NULL;
3230   /* set the global variables for filename & line number */
3231   if (tree->filename)
3232     filename = tree->filename;
3233   if (tree->lineno)
3234     lineno = tree->lineno;
3235   if (tree->block)
3236     block = tree->block;
3237   if (tree->level)
3238     scopeLevel = tree->level;
3239
3240   if (tree->type == EX_VALUE)
3241     return operandFromValue (tree->opval.val);
3242
3243   if (tree->type == EX_LINK)
3244     return operandFromLink (tree->opval.lnk);
3245
3246   /* if we find a nullop */
3247   if (tree->type == EX_OP &&
3248      (tree->opval.op == NULLOP ||
3249      tree->opval.op == BLOCK))
3250     {
3251       ast2iCode (tree->left,lvl+1);
3252       ast2iCode (tree->right,lvl+1);
3253       return NULL;
3254     }
3255
3256   /* special cases for not evaluating */
3257   if (tree->opval.op != ':' &&
3258       tree->opval.op != '?' &&
3259       tree->opval.op != CALL &&
3260       tree->opval.op != IFX &&
3261       tree->opval.op != LABEL &&
3262       tree->opval.op != GOTO &&
3263       tree->opval.op != SWITCH &&
3264       tree->opval.op != FUNCTION &&
3265       tree->opval.op != INLINEASM)
3266     {
3267
3268         if (IS_ASSIGN_OP (tree->opval.op) ||
3269            IS_DEREF_OP (tree) ||
3270            (tree->opval.op == '&' && !tree->right) ||
3271            tree->opval.op == PTR_OP)
3272           {
3273             addLvaluereq(lvl);
3274             if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3275                (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3276               clearLvaluereq();
3277
3278             left = operandFromAst (tree->left,lvl);
3279             delLvaluereq();
3280             if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3281               left = geniCodeRValue (left, TRUE);
3282           }
3283         else
3284           {
3285             left = operandFromAst (tree->left,lvl);
3286           }
3287         if (tree->opval.op == INC_OP ||
3288             tree->opval.op == DEC_OP)
3289           {
3290             addLvaluereq(lvl);
3291             right = operandFromAst (tree->right,lvl);
3292             delLvaluereq();
3293           }
3294         else
3295           {
3296             right = operandFromAst (tree->right,lvl);
3297           }
3298       }
3299
3300   /* now depending on the type of operand */
3301   /* this will be a biggy                 */
3302   switch (tree->opval.op)
3303     {
3304
3305     case '[':                   /* array operation */
3306       {
3307         //sym_link *ltype = operandType (left);
3308         //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3309         left = geniCodeRValue (left, FALSE);
3310         right = geniCodeRValue (right, TRUE);
3311       }
3312
3313       return geniCodeArray (left, right,lvl);
3314
3315     case '.':                   /* structure dereference */
3316       if (IS_PTR (operandType (left)))
3317         left = geniCodeRValue (left, TRUE);
3318       else
3319         left = geniCodeRValue (left, FALSE);
3320
3321       return geniCodeStruct (left, right, tree->lvalue);
3322
3323     case PTR_OP:                /* structure pointer dereference */
3324       {
3325         sym_link *pType;
3326         pType = operandType (left);
3327         left = geniCodeRValue (left, TRUE);
3328
3329         setOClass (pType, getSpec (operandType (left)));
3330       }
3331
3332       return geniCodeStruct (left, right, tree->lvalue);
3333
3334     case INC_OP:                /* increment operator */
3335       if (left)
3336         return geniCodePostInc (left);
3337       else
3338         return geniCodePreInc (right);
3339
3340     case DEC_OP:                /* decrement operator */
3341       if (left)
3342         return geniCodePostDec (left);
3343       else
3344         return geniCodePreDec (right);
3345
3346     case '&':                   /* bitwise and or address of operator */
3347       if (right)
3348         {                       /* this is a bitwise operator   */
3349           left = geniCodeRValue (left, FALSE);
3350           right = geniCodeRValue (right, FALSE);
3351           return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3352         }
3353       else
3354         return geniCodeAddressOf (left);
3355
3356     case '|':                   /* bitwise or & xor */
3357     case '^':
3358       return geniCodeBitwise (geniCodeRValue (left, FALSE),
3359                               geniCodeRValue (right, FALSE),
3360                               tree->opval.op,
3361                               tree->ftype);
3362
3363     case '/':
3364       return geniCodeDivision (geniCodeRValue (left, FALSE),
3365                                geniCodeRValue (right, FALSE));
3366
3367     case '%':
3368       return geniCodeModulus (geniCodeRValue (left, FALSE),
3369                               geniCodeRValue (right, FALSE));
3370     case '*':
3371       if (right)
3372         return geniCodeMultiply (geniCodeRValue (left, FALSE),
3373                                  geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3374       else
3375         return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3376
3377     case '-':
3378       if (right)
3379         return geniCodeSubtract (geniCodeRValue (left, FALSE),
3380                                  geniCodeRValue (right, FALSE));
3381       else
3382         return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3383
3384     case '+':
3385       if (right)
3386         return geniCodeAdd (geniCodeRValue (left, FALSE),
3387                             geniCodeRValue (right, FALSE),lvl);
3388       else
3389         return geniCodeRValue (left, FALSE);    /* unary '+' has no meaning */
3390
3391     case LEFT_OP:
3392       return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3393                                 geniCodeRValue (right, FALSE));
3394
3395     case RIGHT_OP:
3396       return geniCodeRightShift (geniCodeRValue (left, FALSE),
3397                                  geniCodeRValue (right, FALSE));
3398     case CAST:
3399       return geniCodeCast (operandType (left),
3400                            geniCodeRValue (right, FALSE), FALSE);
3401
3402     case '~':
3403     case '!':
3404     case RRC:
3405     case RLC:
3406       return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3407
3408     case GETHBIT:
3409       {
3410         operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3411         setOperandType (op, UCHARTYPE);
3412         return op;
3413       }
3414     case '>':
3415     case '<':
3416     case LE_OP:
3417     case GE_OP:
3418     case EQ_OP:
3419     case NE_OP:
3420     case AND_OP:
3421     case OR_OP:
3422       return geniCodeLogic (geniCodeRValue (left, FALSE),
3423                             geniCodeRValue (right, FALSE),
3424                             tree->opval.op);
3425     case '?':
3426       return geniCodeConditional (tree,lvl);
3427
3428     case SIZEOF:
3429       return operandFromLit (getSize (tree->right->ftype));
3430
3431     case '=':
3432       {
3433         sym_link *rtype = operandType (right);
3434         sym_link *ltype = operandType (left);
3435         if (IS_PTR (rtype) && IS_ITEMP (right)
3436             && right->isaddr && compareType (rtype->next, ltype) == 1)
3437           right = geniCodeRValue (right, TRUE);
3438         else
3439           right = geniCodeRValue (right, FALSE);
3440
3441         geniCodeAssign (left, right, 0);
3442         return right;
3443       }
3444     case MUL_ASSIGN:
3445       return
3446         geniCodeAssign (left,
3447                 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3448                                                   FALSE),
3449                                   geniCodeRValue (right, FALSE),FALSE), 0);
3450
3451     case DIV_ASSIGN:
3452       return
3453         geniCodeAssign (left,
3454                 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3455                                                   FALSE),
3456                                   geniCodeRValue (right, FALSE)), 0);
3457     case MOD_ASSIGN:
3458       return
3459         geniCodeAssign (left,
3460                  geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3461                                                   FALSE),
3462                                   geniCodeRValue (right, FALSE)), 0);
3463     case ADD_ASSIGN:
3464       {
3465         sym_link *rtype = operandType (right);
3466         sym_link *ltype = operandType (left);
3467         if (IS_PTR (rtype) && IS_ITEMP (right)
3468             && right->isaddr && compareType (rtype->next, ltype) == 1)
3469           right = geniCodeRValue (right, TRUE);
3470         else
3471           right = geniCodeRValue (right, FALSE);
3472
3473
3474         return geniCodeAssign (left,
3475                      geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3476                                                   FALSE),
3477                                   right,lvl), 0);
3478       }
3479     case SUB_ASSIGN:
3480       {
3481         sym_link *rtype = operandType (right);
3482         sym_link *ltype = operandType (left);
3483         if (IS_PTR (rtype) && IS_ITEMP (right)
3484             && right->isaddr && compareType (rtype->next, ltype) == 1)
3485           {
3486             right = geniCodeRValue (right, TRUE);
3487           }
3488         else
3489           {
3490             right = geniCodeRValue (right, FALSE);
3491           }
3492         return
3493           geniCodeAssign (left,
3494                 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3495                                                   FALSE),
3496                                   right), 0);
3497       }
3498     case LEFT_ASSIGN:
3499       return
3500         geniCodeAssign (left,
3501                 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3502                                                    ,FALSE),
3503                                    geniCodeRValue (right, FALSE)), 0);
3504     case RIGHT_ASSIGN:
3505       return
3506         geniCodeAssign (left,
3507                geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3508                                                    ,FALSE),
3509                                    geniCodeRValue (right, FALSE)), 0);
3510     case AND_ASSIGN:
3511       return
3512         geniCodeAssign (left,
3513                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3514                                                   FALSE),
3515                                   geniCodeRValue (right, FALSE),
3516                                   BITWISEAND,
3517                                   operandType (left)), 0);
3518     case XOR_ASSIGN:
3519       return
3520         geniCodeAssign (left,
3521                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3522                                                   FALSE),
3523                                   geniCodeRValue (right, FALSE),
3524                                   '^',
3525                                   operandType (left)), 0);
3526     case OR_ASSIGN:
3527       return
3528         geniCodeAssign (left,
3529                   geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3530                                                    ,FALSE),
3531                                    geniCodeRValue (right, FALSE),
3532                                    '|',
3533                                    operandType (left)), 0);
3534     case ',':
3535       return geniCodeRValue (right, FALSE);
3536
3537     case CALL:
3538       return geniCodeCall (ast2iCode (tree->left,lvl+1),
3539                            tree->right,lvl);
3540     case LABEL:
3541       geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3542       return ast2iCode (tree->right,lvl+1);
3543
3544     case GOTO:
3545       geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3546       return ast2iCode (tree->right,lvl+1);
3547
3548     case FUNCTION:
3549       geniCodeFunctionBody (tree,lvl);
3550       return NULL;
3551
3552     case RETURN:
3553       geniCodeReturn (right);
3554       return NULL;
3555
3556     case IFX:
3557       geniCodeIfx (tree,lvl);
3558       return NULL;
3559
3560     case SWITCH:
3561       geniCodeSwitch (tree,lvl);
3562       return NULL;
3563
3564     case INLINEASM:
3565       geniCodeInline (tree);
3566       return NULL;
3567         
3568     case ARRAYINIT:
3569         geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3570         return NULL;
3571     }
3572
3573   return NULL;
3574 }
3575
3576 /*-----------------------------------------------------------------*/
3577 /* reverseICChain - gets from the list and creates a linkedlist    */
3578 /*-----------------------------------------------------------------*/
3579 iCode *
3580 reverseiCChain ()
3581 {
3582   iCode *loop = NULL;
3583   iCode *prev = NULL;
3584
3585   while ((loop = getSet (&iCodeChain)))
3586     {
3587       loop->next = prev;
3588       if (prev)
3589         prev->prev = loop;
3590       prev = loop;
3591     }
3592
3593   return prev;
3594 }
3595
3596
3597 /*-----------------------------------------------------------------*/
3598 /* iCodeFromAst - given an ast will convert it to iCode            */
3599 /*-----------------------------------------------------------------*/
3600 iCode *
3601 iCodeFromAst (ast * tree)
3602 {
3603   returnLabel = newiTempLabel ("_return");
3604   entryLabel = newiTempLabel ("_entry");
3605   ast2iCode (tree,0);
3606   return reverseiCChain ();
3607 }