Function attribute migration.
[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       IC_ARGS (nic) = IC_ARGS (ic);
687       break;
688
689     case INLINEASM:
690       IC_INLINE (nic) = IC_INLINE (ic);
691       break;
692
693     case ARRAYINIT:
694       IC_ARRAYILIST(nic) = IC_ARRAYILIST(ic);
695       break;
696
697     default:
698       IC_RESULT (nic) = operandFromOperand (IC_RESULT (ic));
699       IC_LEFT (nic) = operandFromOperand (IC_LEFT (ic));
700       IC_RIGHT (nic) = operandFromOperand (IC_RIGHT (ic));
701     }
702
703   return nic;
704 }
705
706 /*-----------------------------------------------------------------*/
707 /* getTableEntry - gets the table entry for the given operator     */
708 /*-----------------------------------------------------------------*/
709 iCodeTable *
710 getTableEntry (int oper)
711 {
712   int i;
713
714   for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
715     if (oper == codeTable[i].icode)
716       return &codeTable[i];
717
718   return NULL;
719 }
720
721 /*-----------------------------------------------------------------*/
722 /* newiTempOperand - new intermediate temp operand                 */
723 /*-----------------------------------------------------------------*/
724 operand *
725 newiTempOperand (sym_link * type, char throwType)
726 {
727   symbol *itmp;
728   operand *op = newOperand ();
729   sym_link *etype;
730
731   op->type = SYMBOL;
732   itmp = newiTemp (NULL);
733
734   etype = getSpec (type);
735
736   if (IS_LITERAL (etype))
737     throwType = 0;
738
739   /* copy the type information */
740   if (type)
741     itmp->etype = getSpec (itmp->type = (throwType ? type :
742                                          copyLinkChain (type)));
743   if (IS_LITERAL (itmp->etype))
744     {
745       SPEC_SCLS (itmp->etype) = S_REGISTER;
746       SPEC_OCLS (itmp->etype) = reg;
747     }
748
749   op->operand.symOperand = itmp;
750   op->key = itmp->key = ++operandKey;
751   return op;
752 }
753
754 /*-----------------------------------------------------------------*/
755 /* operandType - returns the type chain for an operand             */
756 /*-----------------------------------------------------------------*/
757 sym_link *
758 operandType (operand * op)
759 {
760   /* depending on type of operand */
761   switch (op->type)
762     {
763
764     case VALUE:
765       return op->operand.valOperand->type;
766
767     case SYMBOL:
768       return op->operand.symOperand->type;
769
770     case TYPE:
771       return op->operand.typeOperand;
772     default:
773       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
774               " operand type not known ");
775       assert (0);               /* should never come here */
776       /*  Just to keep the compiler happy */
777       return (sym_link *) 0;
778     }
779 }
780
781 /*-----------------------------------------------------------------*/
782 /* isParamterToCall - will return 1 if op is a parameter to args   */
783 /*-----------------------------------------------------------------*/
784 int 
785 isParameterToCall (value * args, operand * op)
786 {
787   value *tval = args;
788
789   while (tval)
790     {
791       if (tval->sym &&
792           isSymbolEqual (op->operand.symOperand, tval->sym))
793         return 1;
794       tval = tval->next;
795     }
796   return 0;
797 }
798
799 /*-----------------------------------------------------------------*/
800 /* isOperandGlobal   - return 1 if operand is a global variable    */
801 /*-----------------------------------------------------------------*/
802 int 
803 isOperandGlobal (operand * op)
804 {
805   if (!op)
806     return 0;
807
808   if (IS_ITEMP (op))
809     return 0;
810
811   if (op->type == SYMBOL &&
812       (op->operand.symOperand->level == 0 ||
813        IS_STATIC (op->operand.symOperand->etype) ||
814        IS_EXTERN (op->operand.symOperand->etype))
815     )
816     return 1;
817
818   return 0;
819 }
820
821 /*-----------------------------------------------------------------*/
822 /* isOperandVolatile - return 1 if the operand is volatile         */
823 /*-----------------------------------------------------------------*/
824 int 
825 isOperandVolatile (operand * op, bool chkTemp)
826 {
827   sym_link *optype;
828   sym_link *opetype;
829
830   if (IS_ITEMP (op) && !chkTemp)
831     return 0;
832
833   opetype = getSpec (optype = operandType (op));
834
835   if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
836     return 1;
837
838   if (IS_VOLATILE (opetype))
839     return 1;
840   return 0;
841 }
842
843 /*-----------------------------------------------------------------*/
844 /* isOperandLiteral - returns 1 if an operand contains a literal   */
845 /*-----------------------------------------------------------------*/
846 int 
847 isOperandLiteral (operand * op)
848 {
849   sym_link *opetype;
850
851   if (!op)
852     return 0;
853
854   opetype = getSpec (operandType (op));
855
856   if (IS_LITERAL (opetype))
857     return 1;
858
859   return 0;
860 }
861 /*-----------------------------------------------------------------*/
862 /* isOperandInFarSpace - will return true if operand is in farSpace */
863 /*-----------------------------------------------------------------*/
864 bool 
865 isOperandInFarSpace (operand * op)
866 {
867   sym_link *etype;
868
869   if (!op)
870     return FALSE;
871
872   if (!IS_SYMOP (op))
873     return FALSE;
874
875   if (!IS_TRUE_SYMOP (op))
876     {
877       if (SPIL_LOC (op))
878         etype = SPIL_LOC (op)->etype;
879       else
880         return FALSE;
881     }
882   else
883     {
884       etype = getSpec (operandType (op));
885     }
886   return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
887 }
888
889 /*-----------------------------------------------------------------*/
890 /* isOperandOnStack - will return true if operand is on stack      */
891 /*-----------------------------------------------------------------*/
892 bool 
893 isOperandOnStack (operand * op)
894 {
895   sym_link *etype;
896
897   if (!op)
898     return FALSE;
899
900   if (!IS_SYMOP (op))
901     return FALSE;
902
903   etype = getSpec (operandType (op));
904
905   return ((IN_STACK (etype)) ? TRUE : FALSE);
906 }
907
908 /*-----------------------------------------------------------------*/
909 /* operandLitValue - literal value of an operand                   */
910 /*-----------------------------------------------------------------*/
911 double 
912 operandLitValue (operand * op)
913 {
914   assert (isOperandLiteral (op));
915
916   return floatFromVal (op->operand.valOperand);
917 }
918
919 /*-----------------------------------------------------------------*/
920 /* operandOperation - perforoms operations on operands             */
921 /*-----------------------------------------------------------------*/
922 operand *
923 operandOperation (operand * left, operand * right,
924                   int op, sym_link * type)
925 {
926   sym_link *let , *ret=NULL;
927   operand *retval = (operand *) 0;
928   
929   assert (isOperandLiteral (left));
930   let = getSpec(operandType(left));
931   if (right) {
932     assert (isOperandLiteral (right));
933     ret = getSpec(operandType(left));
934   }
935
936   switch (op)
937     {
938     case '+':
939       retval = operandFromValue (valCastLiteral (type,
940                                                  operandLitValue (left) +
941                                                  operandLitValue (right)));
942       break;
943     case '-':
944       retval = operandFromValue (valCastLiteral (type,
945                                                  operandLitValue (left) -
946                                                  operandLitValue (right)));
947       break;
948     case '*':
949       retval = operandFromValue (valCastLiteral (type,
950                                                  operandLitValue (left) *
951                                                  operandLitValue (right)));
952       break;
953     case '/':
954       if ((unsigned long) operandLitValue (right) == 0)
955         {
956           werror (E_DIVIDE_BY_ZERO);
957           retval = right;
958
959         }
960       else
961         retval = operandFromValue (valCastLiteral (type,
962                                                    operandLitValue (left) /
963                                                    operandLitValue (right)));
964       break;
965     case '%':
966       if ((unsigned long) operandLitValue (right) == 0) {
967           werror (E_DIVIDE_BY_ZERO);
968           retval = right;
969       }
970       else 
971         retval = operandFromLit ((SPEC_USIGN(let) ? 
972                                   (unsigned long) operandLitValue (left) :
973                                   (long) operandLitValue (left)) %
974                                  (SPEC_USIGN(ret) ? 
975                                   (unsigned long) operandLitValue (right) :
976                                   (long) operandLitValue (right)));
977
978       break;
979     case LEFT_OP:
980       retval = operandFromLit ((SPEC_USIGN(let) ? 
981                                   (unsigned long) operandLitValue (left) :
982                                   (long) operandLitValue (left)) <<
983                                  (SPEC_USIGN(ret) ? 
984                                   (unsigned long) operandLitValue (right) :
985                                   (long) operandLitValue (right)));
986       break;
987     case RIGHT_OP:
988       retval = operandFromLit ((SPEC_USIGN(let) ? 
989                                   (unsigned long) operandLitValue (left) :
990                                   (long) operandLitValue (left)) >>
991                                  (SPEC_USIGN(ret) ? 
992                                   (unsigned long) operandLitValue (right) :
993                                   (long) operandLitValue (right)));
994       break;
995     case EQ_OP:
996       retval = operandFromLit (operandLitValue (left) ==
997                                operandLitValue (right));
998       break;
999     case '<':
1000       retval = operandFromLit (operandLitValue (left) <
1001                                operandLitValue (right));
1002       break;
1003     case LE_OP:
1004       retval = operandFromLit (operandLitValue (left) <=
1005                                operandLitValue (right));
1006       break;
1007     case NE_OP:
1008       retval = operandFromLit (operandLitValue (left) !=
1009                                operandLitValue (right));
1010       break;
1011     case '>':
1012       retval = operandFromLit (operandLitValue (left) >
1013                                operandLitValue (right));
1014       break;
1015     case GE_OP:
1016       retval = operandFromLit (operandLitValue (left) >=
1017                                operandLitValue (right));
1018       break;
1019     case BITWISEAND:
1020       retval = operandFromLit ((long)operandLitValue(left) & 
1021                                (long)operandLitValue(right));
1022       break;
1023     case '|':
1024       retval = operandFromLit ((long)operandLitValue (left) |
1025                                (long)operandLitValue (right));
1026       break;
1027     case '^':
1028       retval = operandFromLit ((long)operandLitValue (left) ^
1029                                (long)operandLitValue (right));
1030       break;
1031     case AND_OP:
1032       retval = operandFromLit (operandLitValue (left) &&
1033                                operandLitValue (right));
1034       break;
1035     case OR_OP:
1036       retval = operandFromLit (operandLitValue (left) ||
1037                                operandLitValue (right));
1038       break;
1039     case RRC:
1040       {
1041         long i = (long) operandLitValue (left);
1042
1043         retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
1044                                  (i << 1));
1045       }
1046       break;
1047     case RLC:
1048       {
1049         long i = (long) operandLitValue (left);
1050
1051         retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
1052                                  (i >> 1));
1053       }
1054       break;
1055
1056     case UNARYMINUS:
1057       retval = operandFromLit (-1 * operandLitValue (left));
1058       break;
1059
1060     case '~':
1061       retval = operandFromLit (~((long) operandLitValue (left)));
1062       break;
1063
1064     case '!':
1065       retval = operandFromLit (!operandLitValue (left));
1066       break;
1067
1068     default:
1069       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1070               " operandOperation invalid operator ");
1071       assert (0);
1072     }
1073
1074   return retval;
1075 }
1076
1077
1078 /*-----------------------------------------------------------------*/
1079 /* isOperandEqual - compares two operand & return 1 if they r =    */
1080 /*-----------------------------------------------------------------*/
1081 int 
1082 isOperandEqual (operand * left, operand * right)
1083 {
1084   /* if the pointers are equal then they are equal */
1085   if (left == right)
1086     return 1;
1087
1088   /* if either of them null then false */
1089   if (!left || !right)
1090     return 0;
1091
1092   if (left->type != right->type)
1093     return 0;
1094
1095   if (IS_SYMOP (left) && IS_SYMOP (right))
1096     return left->key == right->key;
1097
1098   /* if types are the same */
1099   switch (left->type)
1100     {
1101     case SYMBOL:
1102       return isSymbolEqual (left->operand.symOperand,
1103                             right->operand.symOperand);
1104     case VALUE:
1105       return (floatFromVal (left->operand.valOperand) ==
1106               floatFromVal (right->operand.valOperand));
1107     case TYPE:
1108       if (compareType (left->operand.typeOperand,
1109                      right->operand.typeOperand) == 1)
1110         return 1;
1111     }
1112
1113   return 0;
1114 }
1115
1116 /*-------------------------------------------------------------------*/
1117 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1118 /*-------------------------------------------------------------------*/
1119 int 
1120 isiCodeEqual (iCode * left, iCode * right)
1121 {
1122   /* if the same pointer */
1123   if (left == right)
1124     return 1;
1125
1126   /* if either of them null */
1127   if (!left || !right)
1128     return 0;
1129
1130   /* if operand are the same */
1131   if (left->op == right->op)
1132     {
1133
1134       /* compare all the elements depending on type */
1135       if (left->op != IFX)
1136         {
1137           if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1138             return 0;
1139           if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1140             return 0;
1141
1142         }
1143       else
1144         {
1145           if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1146             return 0;
1147           if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1148             return 0;
1149           if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1150             return 0;
1151         }
1152       
1153       return 1;
1154     }
1155   return 0;
1156 }
1157
1158 /*-----------------------------------------------------------------*/
1159 /* newiTempFromOp - create a temp Operand with same attributes     */
1160 /*-----------------------------------------------------------------*/
1161 operand *
1162 newiTempFromOp (operand * op)
1163 {
1164   operand *nop;
1165
1166   if (!op)
1167     return NULL;
1168
1169   if (!IS_ITEMP (op))
1170     return op;
1171
1172   nop = newiTempOperand (operandType (op), TRUE);
1173   nop->isaddr = op->isaddr;
1174   nop->isvolatile = op->isvolatile;
1175   nop->isGlobal = op->isGlobal;
1176   nop->isLiteral = op->isLiteral;
1177   nop->usesDefs = op->usesDefs;
1178   nop->isParm = op->isParm;
1179   return nop;
1180 }
1181
1182 /*-----------------------------------------------------------------*/
1183 /* operand from operand - creates an operand holder for the type   */
1184 /*-----------------------------------------------------------------*/
1185 operand *
1186 operandFromOperand (operand * op)
1187 {
1188   operand *nop;
1189
1190   if (!op)
1191     return NULL;
1192   nop = newOperand ();
1193   nop->type = op->type;
1194   nop->isaddr = op->isaddr;
1195   nop->key = op->key;
1196   nop->isvolatile = op->isvolatile;
1197   nop->isGlobal = op->isGlobal;
1198   nop->isLiteral = op->isLiteral;
1199   nop->usesDefs = op->usesDefs;
1200   nop->isParm = op->isParm;
1201
1202   switch (nop->type)
1203     {
1204     case SYMBOL:
1205       nop->operand.symOperand = op->operand.symOperand;
1206       break;
1207     case VALUE:
1208       nop->operand.valOperand = op->operand.valOperand;
1209       break;
1210     case TYPE:
1211       nop->operand.typeOperand = op->operand.typeOperand;
1212       break;
1213     }
1214
1215   return nop;
1216 }
1217
1218 /*-----------------------------------------------------------------*/
1219 /* opFromOpWithDU - makes a copy of the operand and DU chains      */
1220 /*-----------------------------------------------------------------*/
1221 operand *
1222 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1223 {
1224   operand *nop = operandFromOperand (op);
1225
1226   if (nop->type == SYMBOL)
1227     {
1228       OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1229       OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1230     }
1231
1232   return nop;
1233 }
1234
1235 /*-----------------------------------------------------------------*/
1236 /* operandFromSymbol - creates an operand from a symbol            */
1237 /*-----------------------------------------------------------------*/
1238 operand *
1239 operandFromSymbol (symbol * sym)
1240 {
1241   operand *op;
1242   iCode *ic;
1243   int ok = 1;
1244   /* if the symbol's type is a literal */
1245   /* then it is an enumerator type     */
1246   if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1247     return operandFromValue (valFromType (sym->etype));
1248
1249   if (!sym->key)
1250     sym->key = ++operandKey;
1251
1252   /* if this an implicit variable, means struct/union */
1253   /* member so just return it                         */
1254   if (sym->implicit || IS_FUNC (sym->type))
1255     {
1256       op = newOperand ();
1257       op->type = SYMBOL;
1258       op->operand.symOperand = sym;
1259       op->key = sym->key;
1260       op->isvolatile = isOperandVolatile (op, TRUE);
1261       op->isGlobal = isOperandGlobal (op);
1262       return op;
1263     }
1264
1265   /* under the following conditions create a
1266      register equivalent for a local symbol */
1267   if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1268       (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1269       (!(options.model == MODEL_FLAT24)) ) &&
1270       options.stackAuto == 0)
1271     ok = 0;
1272
1273   if (!IS_AGGREGATE (sym->type) &&      /* not an aggregate */
1274       !IS_FUNC (sym->type) &&   /* not a function   */
1275       !sym->_isparm &&          /* not a parameter  */
1276       sym->level &&             /* is a local variable */
1277       !sym->addrtaken &&        /* whose address has not been taken */
1278       !sym->reqv &&             /* does not already have a register euivalence */
1279       !IS_VOLATILE (sym->etype) &&      /* not declared as volatile */
1280       !IS_STATIC (sym->etype) &&        /* and not declared static  */
1281       !sym->islbl &&            /* not a label */
1282       ok &&                     /* farspace check */
1283       !IS_BITVAR (sym->etype)   /* not a bit variable */
1284     )
1285     {
1286
1287       /* we will use it after all optimizations
1288          and before liveRange calculation */
1289       sym->reqv = newiTempOperand (sym->type, 0);
1290       sym->reqv->key = sym->key;
1291       OP_SYMBOL (sym->reqv)->key = sym->key;
1292       OP_SYMBOL (sym->reqv)->isreqv = 1;
1293       OP_SYMBOL (sym->reqv)->islocal = 1;
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     /* fprintf (stderr, "%s%s %d: ", op->operand.symOperand->name,
1661        implicit?"(implicit)":"", errors); */
1662     fprintf (stderr, "from type '");
1663     printTypeChain (optype, stderr);
1664     fprintf (stderr, "' to type '");
1665     printTypeChain (type, stderr);
1666     fprintf (stderr, "'\n");
1667   }
1668
1669   /* if they are the same size create an assignment */
1670   if (getSize (type) == getSize (optype) &&
1671       !IS_BITFIELD (type) &&
1672       !IS_FLOAT (type) &&
1673       !IS_FLOAT (optype) &&
1674       ((IS_SPEC (type) && IS_SPEC (optype)) ||
1675        (!IS_SPEC (type) && !IS_SPEC (optype))))
1676     {
1677
1678       ic = newiCode ('=', NULL, op);
1679       IC_RESULT (ic) = newiTempOperand (type, 0);
1680       SPIL_LOC (IC_RESULT (ic)) =
1681         (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1682       IC_RESULT (ic)->isaddr = 0;
1683     }
1684   else
1685     {
1686       ic = newiCode (CAST, operandFromLink (type),
1687                      geniCodeRValue (op, FALSE));
1688
1689       IC_RESULT (ic) = newiTempOperand (type, 0);
1690     }
1691
1692   /* preserve the storage class & output class */
1693   /* of the original variable                  */
1694   restype = getSpec (operandType (IC_RESULT (ic)));
1695   SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1696   SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1697
1698   ADDTOCHAIN (ic);
1699   return IC_RESULT (ic);
1700 }
1701
1702 /*-----------------------------------------------------------------*/
1703 /* geniCodeLabel - will create a Label                             */
1704 /*-----------------------------------------------------------------*/
1705 void 
1706 geniCodeLabel (symbol * label)
1707 {
1708   iCode *ic;
1709
1710   ic = newiCodeLabelGoto (LABEL, label);
1711   ADDTOCHAIN (ic);
1712 }
1713
1714 /*-----------------------------------------------------------------*/
1715 /* geniCodeGoto  - will create a Goto                              */
1716 /*-----------------------------------------------------------------*/
1717 void 
1718 geniCodeGoto (symbol * label)
1719 {
1720   iCode *ic;
1721
1722   ic = newiCodeLabelGoto (GOTO, label);
1723   ADDTOCHAIN (ic);
1724 }
1725
1726 /*-----------------------------------------------------------------*/
1727 /* geniCodeMultiply - gen intermediate code for multiplication     */
1728 /*-----------------------------------------------------------------*/
1729 operand *
1730 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1731 {
1732   iCode *ic;
1733   int p2 = 0;
1734   sym_link *resType;
1735   LRTYPE;
1736
1737   /* if they are both literal then we know the result */
1738   if (IS_LITERAL (letype) && IS_LITERAL (retype))
1739     return operandFromValue (valMult (left->operand.valOperand,
1740                                       right->operand.valOperand));
1741
1742   if (IS_LITERAL(retype)) {
1743     p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1744   }
1745
1746   resType = usualBinaryConversions (&left, &right);
1747 #if 1
1748   rtype = operandType (right);
1749   retype = getSpec (rtype);
1750   ltype = operandType (left);
1751   letype = getSpec (ltype);
1752 #endif
1753   if (resultIsInt)
1754     {
1755       SPEC_NOUN(getSpec(resType))=V_INT;
1756     }
1757
1758   /* if the right is a literal & power of 2 */
1759   /* then make it a left shift              */
1760   /* code generated for 1 byte * 1 byte literal = 2 bytes result is more 
1761      efficient in most cases than 2 bytes result = 2 bytes << literal 
1762      if port has 1 byte muldiv */
1763   if (p2 && !IS_FLOAT (letype) &&
1764       !((resultIsInt) && (getSize (resType) != getSize (ltype)) && 
1765         (port->support.muldiv == 1)))
1766     {
1767       if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1768         {
1769           /* LEFT_OP need same size for left and result, */
1770           left = geniCodeCast (resType, left, TRUE);
1771           ltype = operandType (left);
1772         }
1773       ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1774     }
1775   else
1776     {
1777       ic = newiCode ('*', left, right);         /* normal multiplication */
1778       /* if the size left or right > 1 then support routine */
1779       if (getSize (ltype) > 1 || getSize (rtype) > 1)
1780         ic->supportRtn = 1;
1781
1782     }
1783   IC_RESULT (ic) = newiTempOperand (resType, 1);
1784
1785   ADDTOCHAIN (ic);
1786   return IC_RESULT (ic);
1787 }
1788
1789 /*-----------------------------------------------------------------*/
1790 /* geniCodeDivision - gen intermediate code for division           */
1791 /*-----------------------------------------------------------------*/
1792 operand *
1793 geniCodeDivision (operand * left, operand * right)
1794 {
1795   iCode *ic;
1796   int p2 = 0;
1797   sym_link *resType;
1798   sym_link *rtype = operandType (right);
1799   sym_link *retype = getSpec (rtype);
1800   sym_link *ltype = operandType (left);
1801   sym_link *letype = getSpec (ltype);
1802
1803   resType = usualBinaryConversions (&left, &right);
1804
1805   /* if the right is a literal & power of 2 */
1806   /* then make it a right shift             */
1807   if (IS_LITERAL (retype) &&
1808       !IS_FLOAT (letype) &&
1809       (p2 = powof2 ((unsigned long)
1810                     floatFromVal (right->operand.valOperand)))) {
1811     ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1812   }
1813   else
1814     {
1815       ic = newiCode ('/', left, right);         /* normal division */
1816       /* if the size left or right > 1 then support routine */
1817       if (getSize (ltype) > 1 || getSize (rtype) > 1)
1818         ic->supportRtn = 1;
1819     }
1820   IC_RESULT (ic) = newiTempOperand (resType, 0);
1821
1822   ADDTOCHAIN (ic);
1823   return IC_RESULT (ic);
1824 }
1825 /*-----------------------------------------------------------------*/
1826 /* geniCodeModulus  - gen intermediate code for modulus            */
1827 /*-----------------------------------------------------------------*/
1828 operand *
1829 geniCodeModulus (operand * left, operand * right)
1830 {
1831   iCode *ic;
1832   sym_link *resType;
1833   LRTYPE;
1834
1835   /* if they are both literal then we know the result */
1836   if (IS_LITERAL (letype) && IS_LITERAL (retype))
1837     return operandFromValue (valMod (left->operand.valOperand,
1838                                      right->operand.valOperand));
1839
1840   resType = usualBinaryConversions (&left, &right);
1841
1842   /* now they are the same size */
1843   ic = newiCode ('%', left, right);
1844
1845   /* if the size left or right > 1 then support routine */
1846   if (getSize (ltype) > 1 || getSize (rtype) > 1)
1847     ic->supportRtn = 1;
1848   IC_RESULT (ic) = newiTempOperand (resType, 0);
1849
1850   ADDTOCHAIN (ic);
1851   return IC_RESULT (ic);
1852 }
1853
1854 /*-----------------------------------------------------------------*/
1855 /* geniCodePtrPtrSubtract - subtracts pointer from pointer         */
1856 /*-----------------------------------------------------------------*/
1857 operand *
1858 geniCodePtrPtrSubtract (operand * left, operand * right)
1859 {
1860   iCode *ic;
1861   operand *result;
1862   LRTYPE;
1863
1864   /* if they are both literals then */
1865   if (IS_LITERAL (letype) && IS_LITERAL (retype))
1866     {
1867       result = operandFromValue (valMinus (left->operand.valOperand,
1868                                            right->operand.valOperand));
1869       goto subtractExit;
1870     }
1871
1872   ic = newiCode ('-', left, right);
1873
1874   IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1875   ADDTOCHAIN (ic);
1876
1877 subtractExit:
1878   return geniCodeDivision (result,
1879                            operandFromLit (getSize (ltype->next)));
1880 }
1881
1882 /*-----------------------------------------------------------------*/
1883 /* geniCodeSubtract - generates code for subtraction               */
1884 /*-----------------------------------------------------------------*/
1885 operand *
1886 geniCodeSubtract (operand * left, operand * right)
1887 {
1888   iCode *ic;
1889   int isarray = 0;
1890   sym_link *resType;
1891   LRTYPE;
1892
1893   /* if they both pointers then */
1894   if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
1895       (IS_PTR (rtype) || IS_ARRAY (rtype)))
1896     return geniCodePtrPtrSubtract (left, right);
1897
1898   /* if they are both literal then we know the result */
1899   if (IS_LITERAL (letype) && IS_LITERAL (retype)
1900       && left->isLiteral && right->isLiteral)
1901     return operandFromValue (valMinus (left->operand.valOperand,
1902                                        right->operand.valOperand));
1903
1904   /* if left is an array or pointer */
1905   if (IS_PTR (ltype) || IS_ARRAY (ltype))
1906     {
1907       isarray = left->isaddr;
1908       right = geniCodeMultiply (right,
1909                                 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
1910       resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
1911     }
1912   else
1913     {                           /* make them the same size */
1914       resType = usualBinaryConversions (&left, &right);
1915     }
1916
1917   ic = newiCode ('-', left, right);
1918
1919   IC_RESULT (ic) = newiTempOperand (resType, 1);
1920   IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1921
1922   /* if left or right is a float */
1923   if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1924     ic->supportRtn = 1;
1925
1926   ADDTOCHAIN (ic);
1927   return IC_RESULT (ic);
1928 }
1929
1930 /*-----------------------------------------------------------------*/
1931 /* geniCodeAdd - generates iCode for addition                      */
1932 /*-----------------------------------------------------------------*/
1933 operand *
1934 geniCodeAdd (operand * left, operand * right,int lvl)
1935 {
1936   iCode *ic;
1937   sym_link *resType;
1938   operand *size;
1939   int isarray = 0;
1940   LRTYPE;
1941
1942   /* if left is an array then array access */
1943   if (IS_ARRAY (ltype))
1944     return geniCodeArray (left, right,lvl);
1945
1946   /* if the right side is LITERAL zero */
1947   /* return the left side              */
1948   if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
1949     return left;
1950
1951   /* if left is literal zero return right */
1952   if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
1953     return right;
1954
1955   /* if left is an array or pointer then size */
1956   if (IS_PTR (ltype))
1957     {
1958       isarray = left->isaddr;
1959       // there is no need to multiply with 1
1960       if (getSize(ltype->next)!=1) {
1961         size  = operandFromLit (getSize (ltype->next));
1962         right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
1963       }
1964       resType = copyLinkChain (ltype);
1965     }
1966   else
1967     {                           /* make them the same size */
1968       resType = usualBinaryConversions (&left, &right);
1969     }
1970
1971   /* if they are both literals then we know */
1972   if (IS_LITERAL (letype) && IS_LITERAL (retype)
1973       && left->isLiteral && right->isLiteral)
1974     return operandFromValue (valPlus (valFromType (letype),
1975                                       valFromType (retype)));
1976
1977   ic = newiCode ('+', left, right);
1978
1979   IC_RESULT (ic) = newiTempOperand (resType, 1);
1980   IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1981
1982   /* if left or right is a float then support
1983      routine */
1984   if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1985     ic->supportRtn = 1;
1986
1987   ADDTOCHAIN (ic);
1988
1989   return IC_RESULT (ic);
1990
1991 }
1992
1993 /*-----------------------------------------------------------------*/
1994 /* aggrToPtr - changes an aggregate to pointer to an aggregate     */
1995 /*-----------------------------------------------------------------*/
1996 sym_link *
1997 aggrToPtr (sym_link * type, bool force)
1998 {
1999   sym_link *etype;
2000   sym_link *ptype;
2001
2002
2003   if (IS_PTR (type) && !force)
2004     return type;
2005
2006   etype = getSpec (type);
2007   ptype = newLink ();
2008
2009   ptype->next = type;
2010   /* if the output class is generic */
2011   if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
2012     DCL_PTR_CONST (ptype) = port->mem.code_ro;
2013
2014   /* if the variable was declared a constant */
2015   /* then the pointer points to a constant */
2016   if (IS_CONSTANT (etype))
2017     DCL_PTR_CONST (ptype) = 1;
2018
2019   /* the variable was volatile then pointer to volatile */
2020   if (IS_VOLATILE (etype))
2021     DCL_PTR_VOLATILE (ptype) = 1;
2022   return ptype;
2023 }
2024
2025 /*-----------------------------------------------------------------*/
2026 /* geniCodeArray2Ptr - array to pointer                            */
2027 /*-----------------------------------------------------------------*/
2028 operand *
2029 geniCodeArray2Ptr (operand * op)
2030 {
2031   sym_link *optype = operandType (op);
2032   sym_link *opetype = getSpec (optype);
2033
2034   /* set the pointer depending on the storage class */
2035   if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2036     DCL_PTR_CONST (optype) = port->mem.code_ro;
2037
2038
2039   /* if the variable was declared a constant */
2040   /* then the pointer points to a constant */
2041   if (IS_CONSTANT (opetype))
2042     DCL_PTR_CONST (optype) = 1;
2043
2044   /* the variable was volatile then pointer to volatile */
2045   if (IS_VOLATILE (opetype))
2046     DCL_PTR_VOLATILE (optype) = 1;
2047   op->isaddr = 0;
2048   return op;
2049 }
2050
2051
2052 /*-----------------------------------------------------------------*/
2053 /* geniCodeArray - array access                                    */
2054 /*-----------------------------------------------------------------*/
2055 operand *
2056 geniCodeArray (operand * left, operand * right,int lvl)
2057 {
2058   iCode *ic;
2059   sym_link *ltype = operandType (left);
2060
2061   if (IS_PTR (ltype))
2062     {
2063       if (IS_PTR (ltype->next) && left->isaddr)
2064         {
2065           left = geniCodeRValue (left, FALSE);
2066         }
2067       return geniCodeDerefPtr (geniCodeAdd (left, right,lvl),lvl);
2068     }
2069
2070   right = geniCodeMultiply (right,
2071                             operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2072
2073   /* we can check for limits here */
2074   if (isOperandLiteral (right) &&
2075       IS_ARRAY (ltype) &&
2076       DCL_ELEM (ltype) &&
2077       (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2078     {
2079       werror (E_ARRAY_BOUND);
2080       right = operandFromLit (0);
2081     }
2082
2083   ic = newiCode ('+', left, right);
2084
2085   IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2086                                       !IS_AGGREGATE (ltype->next) &&
2087                                       !IS_PTR (ltype->next))
2088                                      ? ltype : ltype->next), 0);
2089
2090   IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2091   ADDTOCHAIN (ic);
2092   return IC_RESULT (ic);
2093 }
2094
2095 /*-----------------------------------------------------------------*/
2096 /* geniCodeStruct - generates intermediate code for structres      */
2097 /*-----------------------------------------------------------------*/
2098 operand *
2099 geniCodeStruct (operand * left, operand * right, bool islval)
2100 {
2101   iCode *ic;
2102   sym_link *type = operandType (left);
2103   sym_link *etype = getSpec (type);
2104   sym_link *retype;
2105   symbol *element = getStructElement (SPEC_STRUCT (etype),
2106                                       right->operand.symOperand);
2107
2108   /* add the offset */
2109   ic = newiCode ('+', left, operandFromLit (element->offset));
2110
2111   IC_RESULT (ic) = newiTempOperand (element->type, 0);
2112
2113   /* preserve the storage & output class of the struct */
2114   /* as well as the volatile attribute */
2115   retype = getSpec (operandType (IC_RESULT (ic)));
2116   SPEC_SCLS (retype) = SPEC_SCLS (etype);
2117   SPEC_OCLS (retype) = SPEC_OCLS (etype);
2118   SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2119
2120   if (IS_PTR (element->type))
2121     setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2122
2123   IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2124
2125
2126   ADDTOCHAIN (ic);
2127   return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2128 }
2129
2130 /*-----------------------------------------------------------------*/
2131 /* geniCodePostInc - generate int code for Post increment          */
2132 /*-----------------------------------------------------------------*/
2133 operand *
2134 geniCodePostInc (operand * op)
2135 {
2136   iCode *ic;
2137   operand *rOp;
2138   sym_link *optype = operandType (op);
2139   operand *result;
2140   operand *rv = (IS_ITEMP (op) ?
2141                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2142                  op);
2143   sym_link *rvtype = operandType (rv);
2144   int size = 0;
2145
2146   /* if this is not an address we have trouble */
2147   if (!op->isaddr)
2148     {
2149       werror (E_LVALUE_REQUIRED, "++");
2150       return op;
2151     }
2152
2153   rOp = newiTempOperand (rvtype, 0);
2154   OP_SYMBOL(rOp)->noSpilLoc = 1;
2155
2156   if (IS_ITEMP (rv))
2157     OP_SYMBOL(rv)->noSpilLoc = 1;
2158
2159   geniCodeAssign (rOp, rv, 0);
2160
2161   size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2162   if (IS_FLOAT (rvtype))
2163     ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2164   else
2165     ic = newiCode ('+', rv, operandFromLit (size));
2166
2167   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2168   ADDTOCHAIN (ic);
2169
2170   geniCodeAssign (op, result, 0);
2171
2172   return rOp;
2173
2174 }
2175
2176 /*-----------------------------------------------------------------*/
2177 /* geniCodePreInc - generate code for preIncrement                 */
2178 /*-----------------------------------------------------------------*/
2179 operand *
2180 geniCodePreInc (operand * op)
2181 {
2182   iCode *ic;
2183   sym_link *optype = operandType (op);
2184   operand *rop = (IS_ITEMP (op) ?
2185                   geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2186                   op);
2187   sym_link *roptype = operandType (rop);
2188   operand *result;
2189   int size = 0;
2190
2191   if (!op->isaddr)
2192     {
2193       werror (E_LVALUE_REQUIRED, "++");
2194       return op;
2195     }
2196
2197
2198   size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2199   if (IS_FLOAT (roptype))
2200     ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2201   else
2202     ic = newiCode ('+', rop, operandFromLit (size));
2203   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2204   ADDTOCHAIN (ic);
2205
2206
2207   return geniCodeAssign (op, result, 0);
2208 }
2209
2210 /*-----------------------------------------------------------------*/
2211 /* geniCodePostDec - generates code for Post decrement             */
2212 /*-----------------------------------------------------------------*/
2213 operand *
2214 geniCodePostDec (operand * op)
2215 {
2216   iCode *ic;
2217   operand *rOp;
2218   sym_link *optype = operandType (op);
2219   operand *result;
2220   operand *rv = (IS_ITEMP (op) ?
2221                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2222                  op);
2223   sym_link *rvtype = operandType (rv);
2224   int size = 0;
2225
2226   /* if this is not an address we have trouble */
2227   if (!op->isaddr)
2228     {
2229       werror (E_LVALUE_REQUIRED, "--");
2230       return op;
2231     }
2232
2233   rOp = newiTempOperand (rvtype, 0);
2234   OP_SYMBOL(rOp)->noSpilLoc = 1;
2235
2236   if (IS_ITEMP (rv))
2237     OP_SYMBOL(rv)->noSpilLoc = 1;
2238
2239   geniCodeAssign (rOp, rv, 0);
2240
2241   size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2242   if (IS_FLOAT (rvtype))
2243     ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2244   else
2245     ic = newiCode ('-', rv, operandFromLit (size));
2246
2247   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2248   ADDTOCHAIN (ic);
2249
2250   geniCodeAssign (op, result, 0);
2251
2252   return rOp;
2253
2254 }
2255
2256 /*-----------------------------------------------------------------*/
2257 /* geniCodePreDec - generate code for pre  decrement               */
2258 /*-----------------------------------------------------------------*/
2259 operand *
2260 geniCodePreDec (operand * op)
2261 {
2262   iCode *ic;
2263   sym_link *optype = operandType (op);
2264   operand *rop = (IS_ITEMP (op) ?
2265                   geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2266                   op);
2267   sym_link *roptype = operandType (rop);
2268   operand *result;
2269   int size = 0;
2270
2271   if (!op->isaddr)
2272     {
2273       werror (E_LVALUE_REQUIRED, "--");
2274       return op;
2275     }
2276
2277
2278   size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2279   if (IS_FLOAT (roptype))
2280     ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2281   else
2282     ic = newiCode ('-', rop, operandFromLit (size));
2283   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2284   ADDTOCHAIN (ic);
2285
2286
2287   return geniCodeAssign (op, result, 0);
2288 }
2289
2290
2291 /*-----------------------------------------------------------------*/
2292 /* geniCodeBitwise - gen int code for bitWise  operators           */
2293 /*-----------------------------------------------------------------*/
2294 operand *
2295 geniCodeBitwise (operand * left, operand * right,
2296                  int oper, sym_link * resType)
2297 {
2298   iCode *ic;
2299
2300   left = geniCodeCast (resType, left, TRUE);
2301   right = geniCodeCast (resType, right, TRUE);
2302
2303   ic = newiCode (oper, left, right);
2304   IC_RESULT (ic) = newiTempOperand (resType, 0);
2305
2306   ADDTOCHAIN (ic);
2307   return IC_RESULT (ic);
2308 }
2309
2310 /*-----------------------------------------------------------------*/
2311 /* geniCodeAddressOf - gens icode for '&' address of operator      */
2312 /*-----------------------------------------------------------------*/
2313 operand *
2314 geniCodeAddressOf (operand * op)
2315 {
2316   iCode *ic;
2317   sym_link *p;
2318   sym_link *optype = operandType (op);
2319   sym_link *opetype = getSpec (optype);
2320
2321   /* lvalue check already done in decorateType */
2322   /* this must be a lvalue */
2323 /*     if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2324 /*  werror (E_LVALUE_REQUIRED,"&"); */
2325 /*  return op; */
2326 /*     } */
2327
2328   p = newLink ();
2329   p->class = DECLARATOR;
2330
2331   /* set the pointer depending on the storage class */
2332   if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2333     DCL_PTR_CONST (p) = port->mem.code_ro;
2334
2335   /* make sure we preserve the const & volatile */
2336   if (IS_CONSTANT (opetype))
2337     DCL_PTR_CONST (p) = 1;
2338
2339   if (IS_VOLATILE (opetype))
2340     DCL_PTR_VOLATILE (p) = 1;
2341
2342   p->next = copyLinkChain (optype);
2343
2344   /* if already a temp */
2345   if (IS_ITEMP (op))
2346     {
2347       setOperandType (op, p);
2348       op->isaddr = 0;
2349       return op;
2350     }
2351
2352   /* other wise make this of the type coming in */
2353   ic = newiCode (ADDRESS_OF, op, NULL);
2354   IC_RESULT (ic) = newiTempOperand (p, 1);
2355   IC_RESULT (ic)->isaddr = 0;
2356   ADDTOCHAIN (ic);
2357   return IC_RESULT (ic);
2358 }
2359 /*-----------------------------------------------------------------*/
2360 /* setOClass - sets the output class depending on the pointer type */
2361 /*-----------------------------------------------------------------*/
2362 void 
2363 setOClass (sym_link * ptr, sym_link * spec)
2364 {
2365   switch (DCL_TYPE (ptr))
2366     {
2367     case POINTER:
2368       SPEC_OCLS (spec) = data;
2369       break;
2370
2371     case GPOINTER:
2372       SPEC_OCLS (spec) = generic;
2373       break;
2374
2375     case FPOINTER:
2376       SPEC_OCLS (spec) = xdata;
2377       break;
2378
2379     case CPOINTER:
2380       SPEC_OCLS (spec) = code;
2381       break;
2382
2383     case IPOINTER:
2384       SPEC_OCLS (spec) = idata;
2385       break;
2386
2387     case PPOINTER:
2388       SPEC_OCLS (spec) = xstack;
2389       break;
2390
2391     case EEPPOINTER:
2392       SPEC_OCLS (spec) = eeprom;
2393       break;
2394
2395     default:
2396       break;
2397
2398     }
2399 }
2400
2401 /*-----------------------------------------------------------------*/
2402 /* geniCodeDerefPtr - dereference pointer with '*'                 */
2403 /*-----------------------------------------------------------------*/
2404 operand *
2405 geniCodeDerefPtr (operand * op,int lvl)
2406 {
2407   sym_link *rtype, *retype;
2408   sym_link *optype = operandType (op);
2409
2410   /* if this is a pointer then generate the rvalue */
2411   if (IS_PTR (optype))
2412     {
2413       if (IS_TRUE_SYMOP (op))
2414         {
2415           op->isaddr = 1;
2416           op = geniCodeRValue (op, TRUE);
2417         }
2418       else
2419         op = geniCodeRValue (op, TRUE);
2420     }
2421
2422   /* now get rid of the pointer part */
2423   if (isLvaluereq(lvl) && IS_ITEMP (op))
2424     {
2425       retype = getSpec (rtype = copyLinkChain (optype));
2426     }
2427   else
2428     {
2429       retype = getSpec (rtype = copyLinkChain (optype->next));
2430     }
2431
2432   /* if this is a pointer then outputclass needs 2b updated */
2433   if (IS_PTR (optype))
2434     setOClass (optype, retype);
2435
2436   op->isGptr = IS_GENPTR (optype);
2437
2438   /* if the pointer was declared as a constant */
2439   /* then we cannot allow assignment to the derefed */
2440   if (IS_PTR_CONST (optype))
2441     SPEC_CONST (retype) = 1;
2442
2443   op->isaddr = (IS_PTR (rtype) ||
2444                 IS_STRUCT (rtype) ||
2445                 IS_INT (rtype) ||
2446                 IS_CHAR (rtype) ||
2447                 IS_FLOAT (rtype));
2448
2449   if (!isLvaluereq(lvl))
2450     op = geniCodeRValue (op, TRUE);
2451
2452   setOperandType (op, rtype);
2453
2454   return op;
2455 }
2456
2457 /*-----------------------------------------------------------------*/
2458 /* geniCodeUnaryMinus - does a unary minus of the operand          */
2459 /*-----------------------------------------------------------------*/
2460 operand *
2461 geniCodeUnaryMinus (operand * op)
2462 {
2463   iCode *ic;
2464   sym_link *optype = operandType (op);
2465
2466   if (IS_LITERAL (optype))
2467     return operandFromLit (-floatFromVal (op->operand.valOperand));
2468
2469   ic = newiCode (UNARYMINUS, op, NULL);
2470   IC_RESULT (ic) = newiTempOperand (optype, 0);
2471   ADDTOCHAIN (ic);
2472   return IC_RESULT (ic);
2473 }
2474
2475 /*-----------------------------------------------------------------*/
2476 /* geniCodeLeftShift - gen i code for left shift                   */
2477 /*-----------------------------------------------------------------*/
2478 operand *
2479 geniCodeLeftShift (operand * left, operand * right)
2480 {
2481   iCode *ic;
2482
2483   ic = newiCode (LEFT_OP, left, right);
2484   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2485   ADDTOCHAIN (ic);
2486   return IC_RESULT (ic);
2487 }
2488
2489 /*-----------------------------------------------------------------*/
2490 /* geniCodeRightShift - gen i code for right shift                 */
2491 /*-----------------------------------------------------------------*/
2492 operand *
2493 geniCodeRightShift (operand * left, operand * right)
2494 {
2495   iCode *ic;
2496
2497   ic = newiCode (RIGHT_OP, left, right);
2498   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2499   ADDTOCHAIN (ic);
2500   return IC_RESULT (ic);
2501 }
2502
2503 /*-----------------------------------------------------------------*/
2504 /* geniCodeLogic- logic code                                       */
2505 /*-----------------------------------------------------------------*/
2506 operand *
2507 geniCodeLogic (operand * left, operand * right, int op)
2508 {
2509   iCode *ic;
2510   sym_link *ctype;
2511   sym_link *rtype = operandType (right);
2512   sym_link *ltype = operandType (left);
2513
2514   /* left is integral type and right is literal then
2515      check if the literal value is within bounds */
2516   if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2517     {
2518       checkConstantRange(ltype, 
2519                          OP_VALUE(right), "compare operation", 1);
2520     }
2521
2522   ctype = usualBinaryConversions (&left, &right);
2523
2524   ic = newiCode (op, left, right);
2525   IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2526
2527   /* if comparing float
2528      and not a '==' || '!=' || '&&' || '||' (these
2529      will be inlined */
2530   if (IS_FLOAT(ctype) &&
2531       op != EQ_OP &&
2532       op != NE_OP &&
2533       op != AND_OP &&
2534       op != OR_OP)
2535     ic->supportRtn = 1;
2536
2537   ADDTOCHAIN (ic);
2538   return IC_RESULT (ic);
2539 }
2540
2541 /*-----------------------------------------------------------------*/
2542 /* geniCodeUnary - for a a generic unary operation                 */
2543 /*-----------------------------------------------------------------*/
2544 operand *
2545 geniCodeUnary (operand * op, int oper)
2546 {
2547   iCode *ic = newiCode (oper, op, NULL);
2548
2549   IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2550   ADDTOCHAIN (ic);
2551   return IC_RESULT (ic);
2552 }
2553
2554 /*-----------------------------------------------------------------*/
2555 /* geniCodeConditional - geniCode for '?' ':' operation            */
2556 /*-----------------------------------------------------------------*/
2557 operand *
2558 geniCodeConditional (ast * tree,int lvl)
2559 {
2560   iCode *ic;
2561   symbol *falseLabel = newiTempLabel (NULL);
2562   symbol *exitLabel = newiTempLabel (NULL);
2563   operand *cond = ast2iCode (tree->left,lvl+1);
2564   operand *true, *false, *result;
2565
2566   ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2567                           NULL, falseLabel);
2568   ADDTOCHAIN (ic);
2569
2570   true = ast2iCode (tree->right->left,lvl+1);
2571
2572   /* move the value to a new Operand */
2573   result = newiTempOperand (operandType (true), 0);
2574   geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2575
2576   /* generate an unconditional goto */
2577   geniCodeGoto (exitLabel);
2578
2579   /* now for the right side */
2580   geniCodeLabel (falseLabel);
2581
2582   false = ast2iCode (tree->right->right,lvl+1);
2583   geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2584
2585   /* create the exit label */
2586   geniCodeLabel (exitLabel);
2587
2588   return result;
2589 }
2590
2591 /*-----------------------------------------------------------------*/
2592 /* geniCodeAssign - generate code for assignment                   */
2593 /*-----------------------------------------------------------------*/
2594 operand *
2595 geniCodeAssign (operand * left, operand * right, int nosupdate)
2596 {
2597   iCode *ic;
2598   sym_link *ltype = operandType (left);
2599   sym_link *rtype = operandType (right);
2600
2601   if (!left->isaddr && !IS_ITEMP (left))
2602     {
2603       werror (E_LVALUE_REQUIRED, "assignment");
2604       return left;
2605     }
2606
2607   /* left is integral type and right is literal then
2608      check if the literal value is within bounds */
2609   if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2610     {
2611       checkConstantRange(ltype, 
2612                          OP_VALUE(right), "= operation", 0);
2613     }
2614
2615   /* if the left & right type don't exactly match */
2616   /* if pointer set then make sure the check is
2617      done with the type & not the pointer */
2618   /* then cast rights type to left */
2619
2620   /* first check the type for pointer assignement */
2621   if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2622       compareType (ltype, rtype) < 0)
2623     {
2624       if (compareType (ltype->next, rtype) < 0)
2625         right = geniCodeCast (ltype->next, right, TRUE);
2626     }
2627   else if (compareType (ltype, rtype) < 0)
2628     right = geniCodeCast (ltype, right, TRUE);
2629
2630   /* if left is a true symbol & ! volatile
2631      create an assignment to temporary for
2632      the right & then assign this temporary
2633      to the symbol this is SSA . isn't it simple
2634      and folks have published mountains of paper on it */
2635   if (IS_TRUE_SYMOP (left) &&
2636       !isOperandVolatile (left, FALSE) &&
2637       isOperandGlobal (left))
2638     {
2639       symbol *sym = NULL;
2640
2641       if (IS_TRUE_SYMOP (right))
2642         sym = OP_SYMBOL (right);
2643       ic = newiCode ('=', NULL, right);
2644       IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2645       SPIL_LOC (right) = sym;
2646       ADDTOCHAIN (ic);
2647     }
2648
2649   ic = newiCode ('=', NULL, right);
2650   IC_RESULT (ic) = left;
2651   ADDTOCHAIN (ic);
2652
2653   /* if left isgptr flag is set then support
2654      routine will be required */
2655   if (left->isGptr)
2656     ic->supportRtn = 1;
2657
2658   ic->nosupdate = nosupdate;
2659   return left;
2660 }
2661
2662 /*-----------------------------------------------------------------*/
2663 /* geniCodeSEParms - generate code for side effecting fcalls       */
2664 /*-----------------------------------------------------------------*/
2665 static void 
2666 geniCodeSEParms (ast * parms,int lvl)
2667 {
2668   if (!parms)
2669     return;
2670
2671   if (parms->type == EX_OP && parms->opval.op == PARAM)
2672     {
2673       geniCodeSEParms (parms->left,lvl);
2674       geniCodeSEParms (parms->right,lvl);
2675       return;
2676     }
2677
2678   /* hack don't like this but too lazy to think of
2679      something better */
2680   if (IS_ADDRESS_OF_OP (parms))
2681     parms->left->lvalue = 1;
2682
2683   if (IS_CAST_OP (parms) &&
2684       IS_PTR (parms->ftype) &&
2685       IS_ADDRESS_OF_OP (parms->right))
2686     parms->right->left->lvalue = 1;
2687
2688   parms->opval.oprnd =
2689     geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2690
2691   parms->type = EX_OPERAND;
2692 }
2693
2694 /*-----------------------------------------------------------------*/
2695 /* geniCodeParms - generates parameters                            */
2696 /*-----------------------------------------------------------------*/
2697 value *
2698 geniCodeParms (ast * parms, value *argVals, int *stack, 
2699                sym_link * fetype, symbol * func,int lvl)
2700 {
2701   iCode *ic;
2702   operand *pval;
2703
2704   if (!parms)
2705     return argVals;
2706
2707   if (argVals==NULL) {
2708     // first argument
2709     argVals=FUNC_ARGS(func->type);
2710   }
2711
2712   if (parms->argSym || 
2713       (parms->type!=EX_OP && parms->type!=EX_OPERAND)) {
2714     fprintf (stderr, "What the fuck??\n");
2715   }
2716
2717   /* if this is a param node then do the left & right */
2718   if (parms->type == EX_OP && parms->opval.op == PARAM)
2719     {
2720       argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
2721       argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
2722       return argVals;
2723     }
2724
2725   /* get the parameter value */
2726   if (parms->type == EX_OPERAND)
2727     pval = parms->opval.oprnd;
2728   else
2729     {
2730       /* maybe this else should go away ?? */
2731       /* hack don't like this but too lazy to think of
2732          something better */
2733       if (IS_ADDRESS_OF_OP (parms))
2734         parms->left->lvalue = 1;
2735
2736       if (IS_CAST_OP (parms) &&
2737           IS_PTR (parms->ftype) &&
2738           IS_ADDRESS_OF_OP (parms->right))
2739         parms->right->left->lvalue = 1;
2740
2741       pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2742     }
2743
2744   /* if register arg then make it a send */
2745   if (((argVals->sym && IS_REGPARM (argVals->sym->etype)) ||
2746        IS_REGPARM (parms->etype)) && !IFFUNC_HASVARARGS(func->type))
2747     //!DECL_HASVARARGS(func->type) && 
2748     //!options.stackAuto &&
2749     //!IS_RENT(func->etype) &&
2750     //IS_REGPARM (argVals->sym->etype))
2751     {
2752       ic = newiCode (SEND, pval, NULL);
2753       ADDTOCHAIN (ic);
2754     }
2755   else
2756     {
2757       /* now decide whether to push or assign */
2758       if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
2759         {
2760
2761           /* assign */
2762           operand *top = operandFromSymbol (argVals->sym);
2763           geniCodeAssign (top, pval, 1);
2764         }
2765       else
2766         {
2767           sym_link *p = operandType (pval);
2768           /* push */
2769           ic = newiCode (IPUSH, pval, NULL);
2770           ic->parmPush = 1;
2771           /* update the stack adjustment */
2772           *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2773           ADDTOCHAIN (ic);
2774         }
2775     }
2776
2777   argVals=argVals->next;
2778   return argVals;
2779 }
2780
2781 /*-----------------------------------------------------------------*/
2782 /* geniCodeCall - generates temp code for calling                  */
2783 /*-----------------------------------------------------------------*/
2784 operand *
2785 geniCodeCall (operand * left, ast * parms,int lvl)
2786 {
2787   iCode *ic;
2788   operand *result;
2789   sym_link *type, *etype;
2790   int stack = 0;
2791
2792   if (!IS_FUNC(OP_SYMBOL(left)->type) && 
2793       !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2794     werror (E_FUNCTION_EXPECTED);
2795     return NULL;
2796   }
2797
2798   /* take care of parameters with side-effecting
2799      function calls in them, this is required to take care
2800      of overlaying function parameters */
2801   geniCodeSEParms (parms,lvl);
2802
2803   /* first the parameters */
2804   geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2805
2806   /* now call : if symbol then pcall */
2807   if (IS_OP_POINTER (left) || IS_ITEMP(left))
2808     ic = newiCode (PCALL, left, NULL);
2809   else
2810     ic = newiCode (CALL, left, NULL);
2811
2812   IC_ARGS (ic) = FUNC_ARGS(left->operand.symOperand->type);
2813   type = copyLinkChain (operandType (left)->next);
2814   etype = getSpec (type);
2815   SPEC_EXTR (etype) = 0;
2816   IC_RESULT (ic) = result = newiTempOperand (type, 1);
2817
2818   ADDTOCHAIN (ic);
2819
2820   /* stack adjustment after call */
2821   ic->parmBytes = stack;
2822
2823   return result;
2824 }
2825
2826 /*-----------------------------------------------------------------*/
2827 /* geniCodeReceive - generate intermediate code for "receive"      */
2828 /*-----------------------------------------------------------------*/
2829 static void 
2830 geniCodeReceive (value * args)
2831 {
2832   /* for all arguments that are passed in registers */
2833   while (args)
2834     {
2835
2836       if (IS_REGPARM (args->etype))
2837         {
2838           operand *opr = operandFromValue (args);
2839           operand *opl;
2840           symbol *sym = OP_SYMBOL (opr);
2841           iCode *ic;
2842
2843           /* we will use it after all optimizations
2844              and before liveRange calculation */
2845           if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2846             {
2847
2848               if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2849                   options.stackAuto == 0 &&
2850                   /* !TARGET_IS_DS390) */
2851                   (!(options.model == MODEL_FLAT24)) )
2852                 {
2853                 }
2854               else
2855                 {
2856                   opl = newiTempOperand (args->type, 0);
2857                   sym->reqv = opl;
2858                   sym->reqv->key = sym->key;
2859                   OP_SYMBOL (sym->reqv)->key = sym->key;
2860                   OP_SYMBOL (sym->reqv)->isreqv = 1;
2861                   OP_SYMBOL (sym->reqv)->islocal = 0;
2862                   SPIL_LOC (sym->reqv) = sym;
2863                 }
2864             }
2865
2866           ic = newiCode (RECEIVE, NULL, NULL);
2867           currFunc->recvSize = getSize (sym->etype);
2868           IC_RESULT (ic) = opr;
2869           ADDTOCHAIN (ic);
2870         }
2871
2872       args = args->next;
2873     }
2874 }
2875
2876 /*-----------------------------------------------------------------*/
2877 /* geniCodeFunctionBody - create the function body                 */
2878 /*-----------------------------------------------------------------*/
2879 void 
2880 geniCodeFunctionBody (ast * tree,int lvl)
2881 {
2882   iCode *ic;
2883   operand *func;
2884   sym_link *fetype;
2885   int savelineno;
2886
2887   /* reset the auto generation */
2888   /* numbers */
2889   iTempNum = 0;
2890   iTempLblNum = 0;
2891   operandKey = 0;
2892   iCodeKey = 0;
2893   func = ast2iCode (tree->left,lvl+1);
2894   fetype = getSpec (operandType (func));
2895
2896   savelineno = lineno;
2897   lineno = OP_SYMBOL (func)->lineDef;
2898   /* create an entry label */
2899   geniCodeLabel (entryLabel);
2900   lineno = savelineno;
2901
2902   /* create a proc icode */
2903   ic = newiCode (FUNCTION, func, NULL);
2904   /* if the function has parmas   then */
2905   /* save the parameters information    */
2906   ic->argLabel.args = tree->values.args;
2907   ic->lineno = OP_SYMBOL (func)->lineDef;
2908
2909   ADDTOCHAIN (ic);
2910
2911   /* for all parameters that are passed
2912      on registers add a "receive" */
2913   geniCodeReceive (tree->values.args);
2914
2915   /* generate code for the body */
2916   ast2iCode (tree->right,lvl+1);
2917
2918   /* create a label for return */
2919   geniCodeLabel (returnLabel);
2920
2921   /* now generate the end proc */
2922   ic = newiCode (ENDFUNCTION, func, NULL);
2923   ADDTOCHAIN (ic);
2924   return;
2925 }
2926
2927 /*-----------------------------------------------------------------*/
2928 /* geniCodeReturn - gen icode for 'return' statement               */
2929 /*-----------------------------------------------------------------*/
2930 void 
2931 geniCodeReturn (operand * op)
2932 {
2933   iCode *ic;
2934
2935   /* if the operand is present force an rvalue */
2936   if (op)
2937     op = geniCodeRValue (op, FALSE);
2938
2939   ic = newiCode (RETURN, op, NULL);
2940   ADDTOCHAIN (ic);
2941 }
2942
2943 /*-----------------------------------------------------------------*/
2944 /* geniCodeIfx - generates code for extended if statement          */
2945 /*-----------------------------------------------------------------*/
2946 void 
2947 geniCodeIfx (ast * tree,int lvl)
2948 {
2949   iCode *ic;
2950   operand *condition = ast2iCode (tree->left,lvl+1);
2951   sym_link *cetype;
2952
2953   /* if condition is null then exit */
2954   if (!condition)
2955     goto exit;
2956   else
2957     condition = geniCodeRValue (condition, FALSE);
2958
2959   cetype = getSpec (operandType (condition));
2960   /* if the condition is a literal */
2961   if (IS_LITERAL (cetype))
2962     {
2963       if (floatFromVal (condition->operand.valOperand))
2964         {
2965           if (tree->trueLabel)
2966             geniCodeGoto (tree->trueLabel);
2967           else
2968             assert (1);
2969         }
2970       else
2971         {
2972           if (tree->falseLabel)
2973             geniCodeGoto (tree->falseLabel);
2974           else
2975             assert (1);
2976         }
2977       goto exit;
2978     }
2979
2980   if (tree->trueLabel)
2981     {
2982       ic = newiCodeCondition (condition,
2983                               tree->trueLabel,
2984                               NULL);
2985       ADDTOCHAIN (ic);
2986
2987       if (tree->falseLabel)
2988         geniCodeGoto (tree->falseLabel);
2989     }
2990   else
2991     {
2992       ic = newiCodeCondition (condition,
2993                               NULL,
2994                               tree->falseLabel);
2995       ADDTOCHAIN (ic);
2996     }
2997
2998 exit:
2999   ast2iCode (tree->right,lvl+1);
3000 }
3001
3002 /*-----------------------------------------------------------------*/
3003 /* geniCodeJumpTable - tries to create a jump table for switch     */
3004 /*-----------------------------------------------------------------*/
3005 int 
3006 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3007 {
3008   int min = 0, max = 0, t, cnt = 0;
3009   value *vch;
3010   iCode *ic;
3011   operand *boundary;
3012   symbol *falseLabel;
3013   set *labels = NULL;
3014
3015   if (!tree || !caseVals)
3016     return 0;
3017
3018   /* the criteria for creating a jump table is */
3019   /* all integer numbers between the maximum & minimum must */
3020   /* be present , the maximum value should not exceed 255 */
3021   min = max = (int) floatFromVal (vch = caseVals);
3022   sprintf (buffer, "_case_%d_%d",
3023            tree->values.switchVals.swNum,
3024            min);
3025   addSet (&labels, newiTempLabel (buffer));
3026
3027   /* if there is only one case value then no need */
3028   if (!(vch = vch->next))
3029     return 0;
3030
3031   while (vch)
3032     {
3033       if (((t = (int) floatFromVal (vch)) - max) != 1)
3034         return 0;
3035       sprintf (buffer, "_case_%d_%d",
3036                tree->values.switchVals.swNum,
3037                t);
3038       addSet (&labels, newiTempLabel (buffer));
3039       max = t;
3040       cnt++;
3041       vch = vch->next;
3042     }
3043
3044   /* if the number of case statements <= 2 then */
3045   /* it is not economical to create the jump table */
3046   /* since two compares are needed for boundary conditions */
3047   if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3048     return 0;
3049
3050   if (tree->values.switchVals.swDefault)
3051     sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3052   else
3053     sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3054
3055   falseLabel = newiTempLabel (buffer);
3056
3057   /* so we can create a jumptable */
3058   /* first we rule out the boundary conditions */
3059   /* if only optimization says so */
3060   if (!optimize.noJTabBoundary)
3061     {
3062       sym_link *cetype = getSpec (operandType (cond));
3063       /* no need to check the lower bound if
3064          the condition is unsigned & minimum value is zero */
3065       if (!(min == 0 && SPEC_USIGN (cetype)))
3066         {
3067           boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3068           ic = newiCodeCondition (boundary, falseLabel, NULL);
3069           ADDTOCHAIN (ic);
3070         }
3071
3072       /* now for upper bounds */
3073       boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3074       ic = newiCodeCondition (boundary, falseLabel, NULL);
3075       ADDTOCHAIN (ic);
3076     }
3077
3078   /* if the min is not zero then we no make it zero */
3079   if (min)
3080     {
3081       cond = geniCodeSubtract (cond, operandFromLit (min));
3082       setOperandType (cond, UCHARTYPE);
3083     }
3084
3085   /* now create the jumptable */
3086   ic = newiCode (JUMPTABLE, NULL, NULL);
3087   IC_JTCOND (ic) = cond;
3088   IC_JTLABELS (ic) = labels;
3089   ADDTOCHAIN (ic);
3090   return 1;
3091 }
3092
3093 /*-----------------------------------------------------------------*/
3094 /* geniCodeSwitch - changes a switch to a if statement             */
3095 /*-----------------------------------------------------------------*/
3096 void 
3097 geniCodeSwitch (ast * tree,int lvl)
3098 {
3099   iCode *ic;
3100   operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3101   value *caseVals = tree->values.switchVals.swVals;
3102   symbol *trueLabel, *falseLabel;
3103
3104   /* if we can make this a jump table */
3105   if (geniCodeJumpTable (cond, caseVals, tree))
3106     goto jumpTable;             /* no need for the comparison */
3107
3108   /* for the cases defined do */
3109   while (caseVals)
3110     {
3111
3112       operand *compare = geniCodeLogic (cond,
3113                                         operandFromValue (caseVals),
3114                                         EQ_OP);
3115
3116       sprintf (buffer, "_case_%d_%d",
3117                tree->values.switchVals.swNum,
3118                (int) floatFromVal (caseVals));
3119       trueLabel = newiTempLabel (buffer);
3120
3121       ic = newiCodeCondition (compare, trueLabel, NULL);
3122       ADDTOCHAIN (ic);
3123       caseVals = caseVals->next;
3124     }
3125
3126
3127
3128   /* if default is present then goto break else break */
3129   if (tree->values.switchVals.swDefault)
3130     sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3131   else
3132     sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3133
3134   falseLabel = newiTempLabel (buffer);
3135   geniCodeGoto (falseLabel);
3136
3137 jumpTable:
3138   ast2iCode (tree->right,lvl+1);
3139 }
3140
3141 /*-----------------------------------------------------------------*/
3142 /* geniCodeInline - intermediate code for inline assembler         */
3143 /*-----------------------------------------------------------------*/
3144 static void 
3145 geniCodeInline (ast * tree)
3146 {
3147   iCode *ic;
3148
3149   ic = newiCode (INLINEASM, NULL, NULL);
3150   IC_INLINE (ic) = tree->values.inlineasm;
3151   ADDTOCHAIN (ic);
3152 }
3153
3154 /*-----------------------------------------------------------------*/
3155 /* geniCodeArrayInit - intermediate code for array initializer     */
3156 /*-----------------------------------------------------------------*/
3157 static void 
3158 geniCodeArrayInit (ast * tree, operand *array)
3159 {
3160   iCode *ic;
3161
3162   if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3163     ic = newiCode (ARRAYINIT, array, NULL);
3164     IC_ARRAYILIST (ic) = tree->values.constlist;
3165   } else {
3166     operand *left=newOperand(), *right=newOperand();
3167     left->type=right->type=SYMBOL;
3168     OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3169     OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3170     ic = newiCode (ARRAYINIT, left, right);
3171   }
3172   ADDTOCHAIN (ic);
3173 }
3174
3175 /*-----------------------------------------------------------------*/
3176 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some      */
3177 /* particular case. Ie : assigning or dereferencing array or ptr   */
3178 /*-----------------------------------------------------------------*/
3179 set * lvaluereqSet = NULL;
3180 typedef struct lvalItem
3181   {
3182     int req;
3183     int lvl;
3184   }
3185 lvalItem;
3186
3187 /*-----------------------------------------------------------------*/
3188 /* addLvaluereq - add a flag for lvalreq for current ast level     */
3189 /*-----------------------------------------------------------------*/
3190 void addLvaluereq(int lvl)
3191 {
3192   lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3193   lpItem->req=1;
3194   lpItem->lvl=lvl;
3195   addSetHead(&lvaluereqSet,lpItem);
3196
3197 }
3198 /*-----------------------------------------------------------------*/
3199 /* delLvaluereq - del a flag for lvalreq for current ast level     */
3200 /*-----------------------------------------------------------------*/
3201 void delLvaluereq()
3202 {
3203   lvalItem * lpItem;
3204   lpItem = getSet(&lvaluereqSet);
3205   if(lpItem) Safe_free(lpItem);
3206 }
3207 /*-----------------------------------------------------------------*/
3208 /* clearLvaluereq - clear lvalreq flag                             */
3209 /*-----------------------------------------------------------------*/
3210 void clearLvaluereq()
3211 {
3212   lvalItem * lpItem;
3213   lpItem = peekSet(lvaluereqSet);
3214   if(lpItem) lpItem->req = 0;
3215 }
3216 /*-----------------------------------------------------------------*/
3217 /* getLvaluereq - get the last lvalreq level                       */
3218 /*-----------------------------------------------------------------*/
3219 int getLvaluereqLvl()
3220 {
3221   lvalItem * lpItem;
3222   lpItem = peekSet(lvaluereqSet);
3223   if(lpItem) return lpItem->lvl;
3224   return 0;
3225 }
3226 /*-----------------------------------------------------------------*/
3227 /* isLvaluereq - is lvalreq valid for this level ?                 */
3228 /*-----------------------------------------------------------------*/
3229 int isLvaluereq(int lvl)
3230 {
3231   lvalItem * lpItem;
3232   lpItem = peekSet(lvaluereqSet);
3233   if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3234   return 0;
3235 }
3236
3237 /*-----------------------------------------------------------------*/
3238 /* ast2iCode - creates an icodeList from an ast                    */
3239 /*-----------------------------------------------------------------*/
3240 operand *
3241 ast2iCode (ast * tree,int lvl)
3242 {
3243   operand *left = NULL;
3244   operand *right = NULL;
3245   if (!tree)
3246     return NULL;
3247   /* set the global variables for filename & line number */
3248   if (tree->filename)
3249     filename = tree->filename;
3250   if (tree->lineno)
3251     lineno = tree->lineno;
3252   if (tree->block)
3253     block = tree->block;
3254   if (tree->level)
3255     scopeLevel = tree->level;
3256
3257   if (tree->type == EX_VALUE)
3258     return operandFromValue (tree->opval.val);
3259
3260   if (tree->type == EX_LINK)
3261     return operandFromLink (tree->opval.lnk);
3262
3263   /* if we find a nullop */
3264   if (tree->type == EX_OP &&
3265      (tree->opval.op == NULLOP ||
3266      tree->opval.op == BLOCK))
3267     {
3268       ast2iCode (tree->left,lvl+1);
3269       ast2iCode (tree->right,lvl+1);
3270       return NULL;
3271     }
3272
3273   /* special cases for not evaluating */
3274   if (tree->opval.op != ':' &&
3275       tree->opval.op != '?' &&
3276       tree->opval.op != CALL &&
3277       tree->opval.op != IFX &&
3278       tree->opval.op != LABEL &&
3279       tree->opval.op != GOTO &&
3280       tree->opval.op != SWITCH &&
3281       tree->opval.op != FUNCTION &&
3282       tree->opval.op != INLINEASM)
3283     {
3284
3285         if (IS_ASSIGN_OP (tree->opval.op) ||
3286            IS_DEREF_OP (tree) ||
3287            (tree->opval.op == '&' && !tree->right) ||
3288            tree->opval.op == PTR_OP)
3289           {
3290             addLvaluereq(lvl);
3291             if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3292                (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3293               clearLvaluereq();
3294
3295             left = operandFromAst (tree->left,lvl);
3296             delLvaluereq();
3297             if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3298               left = geniCodeRValue (left, TRUE);
3299           }
3300         else
3301           {
3302             left = operandFromAst (tree->left,lvl);
3303           }
3304         if (tree->opval.op == INC_OP ||
3305             tree->opval.op == DEC_OP)
3306           {
3307             addLvaluereq(lvl);
3308             right = operandFromAst (tree->right,lvl);
3309             delLvaluereq();
3310           }
3311         else
3312           {
3313             right = operandFromAst (tree->right,lvl);
3314           }
3315       }
3316
3317   /* now depending on the type of operand */
3318   /* this will be a biggy                 */
3319   switch (tree->opval.op)
3320     {
3321
3322     case '[':                   /* array operation */
3323       {
3324         //sym_link *ltype = operandType (left);
3325         //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3326         left = geniCodeRValue (left, FALSE);
3327         right = geniCodeRValue (right, TRUE);
3328       }
3329
3330       return geniCodeArray (left, right,lvl);
3331
3332     case '.':                   /* structure dereference */
3333       if (IS_PTR (operandType (left)))
3334         left = geniCodeRValue (left, TRUE);
3335       else
3336         left = geniCodeRValue (left, FALSE);
3337
3338       return geniCodeStruct (left, right, tree->lvalue);
3339
3340     case PTR_OP:                /* structure pointer dereference */
3341       {
3342         sym_link *pType;
3343         pType = operandType (left);
3344         left = geniCodeRValue (left, TRUE);
3345
3346         setOClass (pType, getSpec (operandType (left)));
3347       }
3348
3349       return geniCodeStruct (left, right, tree->lvalue);
3350
3351     case INC_OP:                /* increment operator */
3352       if (left)
3353         return geniCodePostInc (left);
3354       else
3355         return geniCodePreInc (right);
3356
3357     case DEC_OP:                /* decrement operator */
3358       if (left)
3359         return geniCodePostDec (left);
3360       else
3361         return geniCodePreDec (right);
3362
3363     case '&':                   /* bitwise and or address of operator */
3364       if (right)
3365         {                       /* this is a bitwise operator   */
3366           left = geniCodeRValue (left, FALSE);
3367           right = geniCodeRValue (right, FALSE);
3368           return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3369         }
3370       else
3371         return geniCodeAddressOf (left);
3372
3373     case '|':                   /* bitwise or & xor */
3374     case '^':
3375       return geniCodeBitwise (geniCodeRValue (left, FALSE),
3376                               geniCodeRValue (right, FALSE),
3377                               tree->opval.op,
3378                               tree->ftype);
3379
3380     case '/':
3381       return geniCodeDivision (geniCodeRValue (left, FALSE),
3382                                geniCodeRValue (right, FALSE));
3383
3384     case '%':
3385       return geniCodeModulus (geniCodeRValue (left, FALSE),
3386                               geniCodeRValue (right, FALSE));
3387     case '*':
3388       if (right)
3389         return geniCodeMultiply (geniCodeRValue (left, FALSE),
3390                                  geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3391       else
3392         return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3393
3394     case '-':
3395       if (right)
3396         return geniCodeSubtract (geniCodeRValue (left, FALSE),
3397                                  geniCodeRValue (right, FALSE));
3398       else
3399         return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3400
3401     case '+':
3402       if (right)
3403         return geniCodeAdd (geniCodeRValue (left, FALSE),
3404                             geniCodeRValue (right, FALSE),lvl);
3405       else
3406         return geniCodeRValue (left, FALSE);    /* unary '+' has no meaning */
3407
3408     case LEFT_OP:
3409       return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3410                                 geniCodeRValue (right, FALSE));
3411
3412     case RIGHT_OP:
3413       return geniCodeRightShift (geniCodeRValue (left, FALSE),
3414                                  geniCodeRValue (right, FALSE));
3415     case CAST:
3416       return geniCodeCast (operandType (left),
3417                            geniCodeRValue (right, FALSE), FALSE);
3418
3419     case '~':
3420     case '!':
3421     case RRC:
3422     case RLC:
3423       return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3424
3425     case GETHBIT:
3426       {
3427         operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3428         setOperandType (op, UCHARTYPE);
3429         return op;
3430       }
3431     case '>':
3432     case '<':
3433     case LE_OP:
3434     case GE_OP:
3435     case EQ_OP:
3436     case NE_OP:
3437     case AND_OP:
3438     case OR_OP:
3439       return geniCodeLogic (geniCodeRValue (left, FALSE),
3440                             geniCodeRValue (right, FALSE),
3441                             tree->opval.op);
3442     case '?':
3443       return geniCodeConditional (tree,lvl);
3444
3445     case SIZEOF:
3446       return operandFromLit (getSize (tree->right->ftype));
3447
3448     case '=':
3449       {
3450         sym_link *rtype = operandType (right);
3451         sym_link *ltype = operandType (left);
3452         if (IS_PTR (rtype) && IS_ITEMP (right)
3453             && right->isaddr && compareType (rtype->next, ltype) == 1)
3454           right = geniCodeRValue (right, TRUE);
3455         else
3456           right = geniCodeRValue (right, FALSE);
3457
3458         geniCodeAssign (left, right, 0);
3459         return right;
3460       }
3461     case MUL_ASSIGN:
3462       return
3463         geniCodeAssign (left,
3464                 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3465                                                   FALSE),
3466                                   geniCodeRValue (right, FALSE),FALSE), 0);
3467
3468     case DIV_ASSIGN:
3469       return
3470         geniCodeAssign (left,
3471                 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3472                                                   FALSE),
3473                                   geniCodeRValue (right, FALSE)), 0);
3474     case MOD_ASSIGN:
3475       return
3476         geniCodeAssign (left,
3477                  geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3478                                                   FALSE),
3479                                   geniCodeRValue (right, FALSE)), 0);
3480     case ADD_ASSIGN:
3481       {
3482         sym_link *rtype = operandType (right);
3483         sym_link *ltype = operandType (left);
3484         if (IS_PTR (rtype) && IS_ITEMP (right)
3485             && right->isaddr && compareType (rtype->next, ltype) == 1)
3486           right = geniCodeRValue (right, TRUE);
3487         else
3488           right = geniCodeRValue (right, FALSE);
3489
3490
3491         return geniCodeAssign (left,
3492                      geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3493                                                   FALSE),
3494                                   right,lvl), 0);
3495       }
3496     case SUB_ASSIGN:
3497       {
3498         sym_link *rtype = operandType (right);
3499         sym_link *ltype = operandType (left);
3500         if (IS_PTR (rtype) && IS_ITEMP (right)
3501             && right->isaddr && compareType (rtype->next, ltype) == 1)
3502           {
3503             right = geniCodeRValue (right, TRUE);
3504           }
3505         else
3506           {
3507             right = geniCodeRValue (right, FALSE);
3508           }
3509         return
3510           geniCodeAssign (left,
3511                 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3512                                                   FALSE),
3513                                   right), 0);
3514       }
3515     case LEFT_ASSIGN:
3516       return
3517         geniCodeAssign (left,
3518                 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3519                                                    ,FALSE),
3520                                    geniCodeRValue (right, FALSE)), 0);
3521     case RIGHT_ASSIGN:
3522       return
3523         geniCodeAssign (left,
3524                geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3525                                                    ,FALSE),
3526                                    geniCodeRValue (right, FALSE)), 0);
3527     case AND_ASSIGN:
3528       return
3529         geniCodeAssign (left,
3530                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3531                                                   FALSE),
3532                                   geniCodeRValue (right, FALSE),
3533                                   BITWISEAND,
3534                                   operandType (left)), 0);
3535     case XOR_ASSIGN:
3536       return
3537         geniCodeAssign (left,
3538                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3539                                                   FALSE),
3540                                   geniCodeRValue (right, FALSE),
3541                                   '^',
3542                                   operandType (left)), 0);
3543     case OR_ASSIGN:
3544       return
3545         geniCodeAssign (left,
3546                   geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3547                                                    ,FALSE),
3548                                    geniCodeRValue (right, FALSE),
3549                                    '|',
3550                                    operandType (left)), 0);
3551     case ',':
3552       return geniCodeRValue (right, FALSE);
3553
3554     case CALL:
3555       return geniCodeCall (ast2iCode (tree->left,lvl+1),
3556                            tree->right,lvl);
3557     case LABEL:
3558       geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3559       return ast2iCode (tree->right,lvl+1);
3560
3561     case GOTO:
3562       geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3563       return ast2iCode (tree->right,lvl+1);
3564
3565     case FUNCTION:
3566       geniCodeFunctionBody (tree,lvl);
3567       return NULL;
3568
3569     case RETURN:
3570       geniCodeReturn (right);
3571       return NULL;
3572
3573     case IFX:
3574       geniCodeIfx (tree,lvl);
3575       return NULL;
3576
3577     case SWITCH:
3578       geniCodeSwitch (tree,lvl);
3579       return NULL;
3580
3581     case INLINEASM:
3582       geniCodeInline (tree);
3583       return NULL;
3584         
3585     case ARRAYINIT:
3586         geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3587         return NULL;
3588     }
3589
3590   return NULL;
3591 }
3592
3593 /*-----------------------------------------------------------------*/
3594 /* reverseICChain - gets from the list and creates a linkedlist    */
3595 /*-----------------------------------------------------------------*/
3596 iCode *
3597 reverseiCChain ()
3598 {
3599   iCode *loop = NULL;
3600   iCode *prev = NULL;
3601
3602   while ((loop = getSet (&iCodeChain)))
3603     {
3604       loop->next = prev;
3605       if (prev)
3606         prev->prev = loop;
3607       prev = loop;
3608     }
3609
3610   return prev;
3611 }
3612
3613
3614 /*-----------------------------------------------------------------*/
3615 /* iCodeFromAst - given an ast will convert it to iCode            */
3616 /*-----------------------------------------------------------------*/
3617 iCode *
3618 iCodeFromAst (ast * tree)
3619 {
3620   returnLabel = newiTempLabel ("_return");
3621   entryLabel = newiTempLabel ("_entry");
3622   ast2iCode (tree,0);
3623   return reverseiCChain ();
3624 }