fixed bug #474222
[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 parm then make it a send */
2745   if ((parms->argSym && IS_REGPARM(parms->argSym->etype)) ||
2746       (IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)))
2747     {
2748       ic = newiCode (SEND, pval, NULL);
2749       ADDTOCHAIN (ic);
2750     }
2751   else
2752     {
2753       /* now decide whether to push or assign */
2754       if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
2755         {
2756
2757           /* assign */
2758           operand *top = operandFromSymbol (argVals->sym);
2759           geniCodeAssign (top, pval, 1);
2760         }
2761       else
2762         {
2763           sym_link *p = operandType (pval);
2764           /* push */
2765           ic = newiCode (IPUSH, pval, NULL);
2766           ic->parmPush = 1;
2767           /* update the stack adjustment */
2768           *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2769           ADDTOCHAIN (ic);
2770         }
2771     }
2772
2773   argVals=argVals->next;
2774   return argVals;
2775 }
2776
2777 /*-----------------------------------------------------------------*/
2778 /* geniCodeCall - generates temp code for calling                  */
2779 /*-----------------------------------------------------------------*/
2780 operand *
2781 geniCodeCall (operand * left, ast * parms,int lvl)
2782 {
2783   iCode *ic;
2784   operand *result;
2785   sym_link *type, *etype;
2786   int stack = 0;
2787
2788   if (!IS_FUNC(OP_SYMBOL(left)->type) && 
2789       !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2790     werror (E_FUNCTION_EXPECTED);
2791     return NULL;
2792   }
2793
2794   /* take care of parameters with side-effecting
2795      function calls in them, this is required to take care
2796      of overlaying function parameters */
2797   geniCodeSEParms (parms,lvl);
2798
2799   /* first the parameters */
2800   geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2801
2802   /* now call : if symbol then pcall */
2803   if (IS_OP_POINTER (left) || IS_ITEMP(left))
2804     ic = newiCode (PCALL, left, NULL);
2805   else
2806     ic = newiCode (CALL, left, NULL);
2807
2808   IC_ARGS (ic) = FUNC_ARGS(left->operand.symOperand->type);
2809   type = copyLinkChain (operandType (left)->next);
2810   etype = getSpec (type);
2811   SPEC_EXTR (etype) = 0;
2812   IC_RESULT (ic) = result = newiTempOperand (type, 1);
2813
2814   ADDTOCHAIN (ic);
2815
2816   /* stack adjustment after call */
2817   ic->parmBytes = stack;
2818
2819   return result;
2820 }
2821
2822 /*-----------------------------------------------------------------*/
2823 /* geniCodeReceive - generate intermediate code for "receive"      */
2824 /*-----------------------------------------------------------------*/
2825 static void 
2826 geniCodeReceive (value * args)
2827 {
2828   /* for all arguments that are passed in registers */
2829   while (args)
2830     {
2831
2832       if (IS_REGPARM (args->etype))
2833         {
2834           operand *opr = operandFromValue (args);
2835           operand *opl;
2836           symbol *sym = OP_SYMBOL (opr);
2837           iCode *ic;
2838
2839           /* we will use it after all optimizations
2840              and before liveRange calculation */
2841           if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2842             {
2843
2844               if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2845                   options.stackAuto == 0 &&
2846                   /* !TARGET_IS_DS390) */
2847                   (!(options.model == MODEL_FLAT24)) )
2848                 {
2849                 }
2850               else
2851                 {
2852                   opl = newiTempOperand (args->type, 0);
2853                   sym->reqv = opl;
2854                   sym->reqv->key = sym->key;
2855                   OP_SYMBOL (sym->reqv)->key = sym->key;
2856                   OP_SYMBOL (sym->reqv)->isreqv = 1;
2857                   OP_SYMBOL (sym->reqv)->islocal = 0;
2858                   SPIL_LOC (sym->reqv) = sym;
2859                 }
2860             }
2861
2862           ic = newiCode (RECEIVE, NULL, NULL);
2863           currFunc->recvSize = getSize (sym->etype);
2864           IC_RESULT (ic) = opr;
2865           ADDTOCHAIN (ic);
2866         }
2867
2868       args = args->next;
2869     }
2870 }
2871
2872 /*-----------------------------------------------------------------*/
2873 /* geniCodeFunctionBody - create the function body                 */
2874 /*-----------------------------------------------------------------*/
2875 void 
2876 geniCodeFunctionBody (ast * tree,int lvl)
2877 {
2878   iCode *ic;
2879   operand *func;
2880   sym_link *fetype;
2881   int savelineno;
2882
2883   /* reset the auto generation */
2884   /* numbers */
2885   iTempNum = 0;
2886   iTempLblNum = 0;
2887   operandKey = 0;
2888   iCodeKey = 0;
2889   func = ast2iCode (tree->left,lvl+1);
2890   fetype = getSpec (operandType (func));
2891
2892   savelineno = lineno;
2893   lineno = OP_SYMBOL (func)->lineDef;
2894   /* create an entry label */
2895   geniCodeLabel (entryLabel);
2896   lineno = savelineno;
2897
2898   /* create a proc icode */
2899   ic = newiCode (FUNCTION, func, NULL);
2900   /* if the function has parmas   then */
2901   /* save the parameters information    */
2902   ic->argLabel.args = tree->values.args;
2903   ic->lineno = OP_SYMBOL (func)->lineDef;
2904
2905   ADDTOCHAIN (ic);
2906
2907   /* for all parameters that are passed
2908      on registers add a "receive" */
2909   geniCodeReceive (tree->values.args);
2910
2911   /* generate code for the body */
2912   ast2iCode (tree->right,lvl+1);
2913
2914   /* create a label for return */
2915   geniCodeLabel (returnLabel);
2916
2917   /* now generate the end proc */
2918   ic = newiCode (ENDFUNCTION, func, NULL);
2919   ADDTOCHAIN (ic);
2920   return;
2921 }
2922
2923 /*-----------------------------------------------------------------*/
2924 /* geniCodeReturn - gen icode for 'return' statement               */
2925 /*-----------------------------------------------------------------*/
2926 void 
2927 geniCodeReturn (operand * op)
2928 {
2929   iCode *ic;
2930
2931   /* if the operand is present force an rvalue */
2932   if (op)
2933     op = geniCodeRValue (op, FALSE);
2934
2935   ic = newiCode (RETURN, op, NULL);
2936   ADDTOCHAIN (ic);
2937 }
2938
2939 /*-----------------------------------------------------------------*/
2940 /* geniCodeIfx - generates code for extended if statement          */
2941 /*-----------------------------------------------------------------*/
2942 void 
2943 geniCodeIfx (ast * tree,int lvl)
2944 {
2945   iCode *ic;
2946   operand *condition = ast2iCode (tree->left,lvl+1);
2947   sym_link *cetype;
2948
2949   /* if condition is null then exit */
2950   if (!condition)
2951     goto exit;
2952   else
2953     condition = geniCodeRValue (condition, FALSE);
2954
2955   cetype = getSpec (operandType (condition));
2956   /* if the condition is a literal */
2957   if (IS_LITERAL (cetype))
2958     {
2959       if (floatFromVal (condition->operand.valOperand))
2960         {
2961           if (tree->trueLabel)
2962             geniCodeGoto (tree->trueLabel);
2963           else
2964             assert (1);
2965         }
2966       else
2967         {
2968           if (tree->falseLabel)
2969             geniCodeGoto (tree->falseLabel);
2970           else
2971             assert (1);
2972         }
2973       goto exit;
2974     }
2975
2976   if (tree->trueLabel)
2977     {
2978       ic = newiCodeCondition (condition,
2979                               tree->trueLabel,
2980                               NULL);
2981       ADDTOCHAIN (ic);
2982
2983       if (tree->falseLabel)
2984         geniCodeGoto (tree->falseLabel);
2985     }
2986   else
2987     {
2988       ic = newiCodeCondition (condition,
2989                               NULL,
2990                               tree->falseLabel);
2991       ADDTOCHAIN (ic);
2992     }
2993
2994 exit:
2995   ast2iCode (tree->right,lvl+1);
2996 }
2997
2998 /*-----------------------------------------------------------------*/
2999 /* geniCodeJumpTable - tries to create a jump table for switch     */
3000 /*-----------------------------------------------------------------*/
3001 int 
3002 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3003 {
3004   int min = 0, max = 0, t, cnt = 0;
3005   value *vch;
3006   iCode *ic;
3007   operand *boundary;
3008   symbol *falseLabel;
3009   set *labels = NULL;
3010
3011   if (!tree || !caseVals)
3012     return 0;
3013
3014   /* the criteria for creating a jump table is */
3015   /* all integer numbers between the maximum & minimum must */
3016   /* be present , the maximum value should not exceed 255 */
3017   min = max = (int) floatFromVal (vch = caseVals);
3018   sprintf (buffer, "_case_%d_%d",
3019            tree->values.switchVals.swNum,
3020            min);
3021   addSet (&labels, newiTempLabel (buffer));
3022
3023   /* if there is only one case value then no need */
3024   if (!(vch = vch->next))
3025     return 0;
3026
3027   while (vch)
3028     {
3029       if (((t = (int) floatFromVal (vch)) - max) != 1)
3030         return 0;
3031       sprintf (buffer, "_case_%d_%d",
3032                tree->values.switchVals.swNum,
3033                t);
3034       addSet (&labels, newiTempLabel (buffer));
3035       max = t;
3036       cnt++;
3037       vch = vch->next;
3038     }
3039
3040   /* if the number of case statements <= 2 then */
3041   /* it is not economical to create the jump table */
3042   /* since two compares are needed for boundary conditions */
3043   if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3044     return 0;
3045
3046   if (tree->values.switchVals.swDefault)
3047     sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3048   else
3049     sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3050
3051   falseLabel = newiTempLabel (buffer);
3052
3053   /* so we can create a jumptable */
3054   /* first we rule out the boundary conditions */
3055   /* if only optimization says so */
3056   if (!optimize.noJTabBoundary)
3057     {
3058       sym_link *cetype = getSpec (operandType (cond));
3059       /* no need to check the lower bound if
3060          the condition is unsigned & minimum value is zero */
3061       if (!(min == 0 && SPEC_USIGN (cetype)))
3062         {
3063           boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3064           ic = newiCodeCondition (boundary, falseLabel, NULL);
3065           ADDTOCHAIN (ic);
3066         }
3067
3068       /* now for upper bounds */
3069       boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3070       ic = newiCodeCondition (boundary, falseLabel, NULL);
3071       ADDTOCHAIN (ic);
3072     }
3073
3074   /* if the min is not zero then we no make it zero */
3075   if (min)
3076     {
3077       cond = geniCodeSubtract (cond, operandFromLit (min));
3078       setOperandType (cond, UCHARTYPE);
3079     }
3080
3081   /* now create the jumptable */
3082   ic = newiCode (JUMPTABLE, NULL, NULL);
3083   IC_JTCOND (ic) = cond;
3084   IC_JTLABELS (ic) = labels;
3085   ADDTOCHAIN (ic);
3086   return 1;
3087 }
3088
3089 /*-----------------------------------------------------------------*/
3090 /* geniCodeSwitch - changes a switch to a if statement             */
3091 /*-----------------------------------------------------------------*/
3092 void 
3093 geniCodeSwitch (ast * tree,int lvl)
3094 {
3095   iCode *ic;
3096   operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3097   value *caseVals = tree->values.switchVals.swVals;
3098   symbol *trueLabel, *falseLabel;
3099
3100   /* if we can make this a jump table */
3101   if (geniCodeJumpTable (cond, caseVals, tree))
3102     goto jumpTable;             /* no need for the comparison */
3103
3104   /* for the cases defined do */
3105   while (caseVals)
3106     {
3107
3108       operand *compare = geniCodeLogic (cond,
3109                                         operandFromValue (caseVals),
3110                                         EQ_OP);
3111
3112       sprintf (buffer, "_case_%d_%d",
3113                tree->values.switchVals.swNum,
3114                (int) floatFromVal (caseVals));
3115       trueLabel = newiTempLabel (buffer);
3116
3117       ic = newiCodeCondition (compare, trueLabel, NULL);
3118       ADDTOCHAIN (ic);
3119       caseVals = caseVals->next;
3120     }
3121
3122
3123
3124   /* if default is present then goto break else break */
3125   if (tree->values.switchVals.swDefault)
3126     sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3127   else
3128     sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3129
3130   falseLabel = newiTempLabel (buffer);
3131   geniCodeGoto (falseLabel);
3132
3133 jumpTable:
3134   ast2iCode (tree->right,lvl+1);
3135 }
3136
3137 /*-----------------------------------------------------------------*/
3138 /* geniCodeInline - intermediate code for inline assembler         */
3139 /*-----------------------------------------------------------------*/
3140 static void 
3141 geniCodeInline (ast * tree)
3142 {
3143   iCode *ic;
3144
3145   ic = newiCode (INLINEASM, NULL, NULL);
3146   IC_INLINE (ic) = tree->values.inlineasm;
3147   ADDTOCHAIN (ic);
3148 }
3149
3150 /*-----------------------------------------------------------------*/
3151 /* geniCodeArrayInit - intermediate code for array initializer     */
3152 /*-----------------------------------------------------------------*/
3153 static void 
3154 geniCodeArrayInit (ast * tree, operand *array)
3155 {
3156   iCode *ic;
3157
3158   if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3159     ic = newiCode (ARRAYINIT, array, NULL);
3160     IC_ARRAYILIST (ic) = tree->values.constlist;
3161   } else {
3162     operand *left=newOperand(), *right=newOperand();
3163     left->type=right->type=SYMBOL;
3164     OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3165     OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3166     ic = newiCode (ARRAYINIT, left, right);
3167   }
3168   ADDTOCHAIN (ic);
3169 }
3170
3171 /*-----------------------------------------------------------------*/
3172 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some      */
3173 /* particular case. Ie : assigning or dereferencing array or ptr   */
3174 /*-----------------------------------------------------------------*/
3175 set * lvaluereqSet = NULL;
3176 typedef struct lvalItem
3177   {
3178     int req;
3179     int lvl;
3180   }
3181 lvalItem;
3182
3183 /*-----------------------------------------------------------------*/
3184 /* addLvaluereq - add a flag for lvalreq for current ast level     */
3185 /*-----------------------------------------------------------------*/
3186 void addLvaluereq(int lvl)
3187 {
3188   lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3189   lpItem->req=1;
3190   lpItem->lvl=lvl;
3191   addSetHead(&lvaluereqSet,lpItem);
3192
3193 }
3194 /*-----------------------------------------------------------------*/
3195 /* delLvaluereq - del a flag for lvalreq for current ast level     */
3196 /*-----------------------------------------------------------------*/
3197 void delLvaluereq()
3198 {
3199   lvalItem * lpItem;
3200   lpItem = getSet(&lvaluereqSet);
3201   if(lpItem) Safe_free(lpItem);
3202 }
3203 /*-----------------------------------------------------------------*/
3204 /* clearLvaluereq - clear lvalreq flag                             */
3205 /*-----------------------------------------------------------------*/
3206 void clearLvaluereq()
3207 {
3208   lvalItem * lpItem;
3209   lpItem = peekSet(lvaluereqSet);
3210   if(lpItem) lpItem->req = 0;
3211 }
3212 /*-----------------------------------------------------------------*/
3213 /* getLvaluereq - get the last lvalreq level                       */
3214 /*-----------------------------------------------------------------*/
3215 int getLvaluereqLvl()
3216 {
3217   lvalItem * lpItem;
3218   lpItem = peekSet(lvaluereqSet);
3219   if(lpItem) return lpItem->lvl;
3220   return 0;
3221 }
3222 /*-----------------------------------------------------------------*/
3223 /* isLvaluereq - is lvalreq valid for this level ?                 */
3224 /*-----------------------------------------------------------------*/
3225 int isLvaluereq(int lvl)
3226 {
3227   lvalItem * lpItem;
3228   lpItem = peekSet(lvaluereqSet);
3229   if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3230   return 0;
3231 }
3232
3233 /*-----------------------------------------------------------------*/
3234 /* ast2iCode - creates an icodeList from an ast                    */
3235 /*-----------------------------------------------------------------*/
3236 operand *
3237 ast2iCode (ast * tree,int lvl)
3238 {
3239   operand *left = NULL;
3240   operand *right = NULL;
3241   if (!tree)
3242     return NULL;
3243   /* set the global variables for filename & line number */
3244   if (tree->filename)
3245     filename = tree->filename;
3246   if (tree->lineno)
3247     lineno = tree->lineno;
3248   if (tree->block)
3249     block = tree->block;
3250   if (tree->level)
3251     scopeLevel = tree->level;
3252
3253   if (tree->type == EX_VALUE)
3254     return operandFromValue (tree->opval.val);
3255
3256   if (tree->type == EX_LINK)
3257     return operandFromLink (tree->opval.lnk);
3258
3259   /* if we find a nullop */
3260   if (tree->type == EX_OP &&
3261      (tree->opval.op == NULLOP ||
3262      tree->opval.op == BLOCK))
3263     {
3264       ast2iCode (tree->left,lvl+1);
3265       ast2iCode (tree->right,lvl+1);
3266       return NULL;
3267     }
3268
3269   /* special cases for not evaluating */
3270   if (tree->opval.op != ':' &&
3271       tree->opval.op != '?' &&
3272       tree->opval.op != CALL &&
3273       tree->opval.op != IFX &&
3274       tree->opval.op != LABEL &&
3275       tree->opval.op != GOTO &&
3276       tree->opval.op != SWITCH &&
3277       tree->opval.op != FUNCTION &&
3278       tree->opval.op != INLINEASM)
3279     {
3280
3281         if (IS_ASSIGN_OP (tree->opval.op) ||
3282            IS_DEREF_OP (tree) ||
3283            (tree->opval.op == '&' && !tree->right) ||
3284            tree->opval.op == PTR_OP)
3285           {
3286             addLvaluereq(lvl);
3287             if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3288                (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3289               clearLvaluereq();
3290
3291             left = operandFromAst (tree->left,lvl);
3292             delLvaluereq();
3293             if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3294               left = geniCodeRValue (left, TRUE);
3295           }
3296         else
3297           {
3298             left = operandFromAst (tree->left,lvl);
3299           }
3300         if (tree->opval.op == INC_OP ||
3301             tree->opval.op == DEC_OP)
3302           {
3303             addLvaluereq(lvl);
3304             right = operandFromAst (tree->right,lvl);
3305             delLvaluereq();
3306           }
3307         else
3308           {
3309             right = operandFromAst (tree->right,lvl);
3310           }
3311       }
3312
3313   /* now depending on the type of operand */
3314   /* this will be a biggy                 */
3315   switch (tree->opval.op)
3316     {
3317
3318     case '[':                   /* array operation */
3319       {
3320         //sym_link *ltype = operandType (left);
3321         //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3322         left = geniCodeRValue (left, FALSE);
3323         right = geniCodeRValue (right, TRUE);
3324       }
3325
3326       return geniCodeArray (left, right,lvl);
3327
3328     case '.':                   /* structure dereference */
3329       if (IS_PTR (operandType (left)))
3330         left = geniCodeRValue (left, TRUE);
3331       else
3332         left = geniCodeRValue (left, FALSE);
3333
3334       return geniCodeStruct (left, right, tree->lvalue);
3335
3336     case PTR_OP:                /* structure pointer dereference */
3337       {
3338         sym_link *pType;
3339         pType = operandType (left);
3340         left = geniCodeRValue (left, TRUE);
3341
3342         setOClass (pType, getSpec (operandType (left)));
3343       }
3344
3345       return geniCodeStruct (left, right, tree->lvalue);
3346
3347     case INC_OP:                /* increment operator */
3348       if (left)
3349         return geniCodePostInc (left);
3350       else
3351         return geniCodePreInc (right);
3352
3353     case DEC_OP:                /* decrement operator */
3354       if (left)
3355         return geniCodePostDec (left);
3356       else
3357         return geniCodePreDec (right);
3358
3359     case '&':                   /* bitwise and or address of operator */
3360       if (right)
3361         {                       /* this is a bitwise operator   */
3362           left = geniCodeRValue (left, FALSE);
3363           right = geniCodeRValue (right, FALSE);
3364           return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3365         }
3366       else
3367         return geniCodeAddressOf (left);
3368
3369     case '|':                   /* bitwise or & xor */
3370     case '^':
3371       return geniCodeBitwise (geniCodeRValue (left, FALSE),
3372                               geniCodeRValue (right, FALSE),
3373                               tree->opval.op,
3374                               tree->ftype);
3375
3376     case '/':
3377       return geniCodeDivision (geniCodeRValue (left, FALSE),
3378                                geniCodeRValue (right, FALSE));
3379
3380     case '%':
3381       return geniCodeModulus (geniCodeRValue (left, FALSE),
3382                               geniCodeRValue (right, FALSE));
3383     case '*':
3384       if (right)
3385         return geniCodeMultiply (geniCodeRValue (left, FALSE),
3386                                  geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3387       else
3388         return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3389
3390     case '-':
3391       if (right)
3392         return geniCodeSubtract (geniCodeRValue (left, FALSE),
3393                                  geniCodeRValue (right, FALSE));
3394       else
3395         return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3396
3397     case '+':
3398       if (right)
3399         return geniCodeAdd (geniCodeRValue (left, FALSE),
3400                             geniCodeRValue (right, FALSE),lvl);
3401       else
3402         return geniCodeRValue (left, FALSE);    /* unary '+' has no meaning */
3403
3404     case LEFT_OP:
3405       return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3406                                 geniCodeRValue (right, FALSE));
3407
3408     case RIGHT_OP:
3409       return geniCodeRightShift (geniCodeRValue (left, FALSE),
3410                                  geniCodeRValue (right, FALSE));
3411     case CAST:
3412       return geniCodeCast (operandType (left),
3413                            geniCodeRValue (right, FALSE), FALSE);
3414
3415     case '~':
3416     case '!':
3417     case RRC:
3418     case RLC:
3419       return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3420
3421     case GETHBIT:
3422       {
3423         operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3424         setOperandType (op, UCHARTYPE);
3425         return op;
3426       }
3427     case '>':
3428     case '<':
3429     case LE_OP:
3430     case GE_OP:
3431     case EQ_OP:
3432     case NE_OP:
3433     case AND_OP:
3434     case OR_OP:
3435       return geniCodeLogic (geniCodeRValue (left, FALSE),
3436                             geniCodeRValue (right, FALSE),
3437                             tree->opval.op);
3438     case '?':
3439       return geniCodeConditional (tree,lvl);
3440
3441     case SIZEOF:
3442       return operandFromLit (getSize (tree->right->ftype));
3443
3444     case '=':
3445       {
3446         sym_link *rtype = operandType (right);
3447         sym_link *ltype = operandType (left);
3448         if (IS_PTR (rtype) && IS_ITEMP (right)
3449             && right->isaddr && compareType (rtype->next, ltype) == 1)
3450           right = geniCodeRValue (right, TRUE);
3451         else
3452           right = geniCodeRValue (right, FALSE);
3453
3454         geniCodeAssign (left, right, 0);
3455         return right;
3456       }
3457     case MUL_ASSIGN:
3458       return
3459         geniCodeAssign (left,
3460                 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3461                                                   FALSE),
3462                                   geniCodeRValue (right, FALSE),FALSE), 0);
3463
3464     case DIV_ASSIGN:
3465       return
3466         geniCodeAssign (left,
3467                 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3468                                                   FALSE),
3469                                   geniCodeRValue (right, FALSE)), 0);
3470     case MOD_ASSIGN:
3471       return
3472         geniCodeAssign (left,
3473                  geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3474                                                   FALSE),
3475                                   geniCodeRValue (right, FALSE)), 0);
3476     case ADD_ASSIGN:
3477       {
3478         sym_link *rtype = operandType (right);
3479         sym_link *ltype = operandType (left);
3480         if (IS_PTR (rtype) && IS_ITEMP (right)
3481             && right->isaddr && compareType (rtype->next, ltype) == 1)
3482           right = geniCodeRValue (right, TRUE);
3483         else
3484           right = geniCodeRValue (right, FALSE);
3485
3486
3487         return geniCodeAssign (left,
3488                      geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3489                                                   FALSE),
3490                                   right,lvl), 0);
3491       }
3492     case SUB_ASSIGN:
3493       {
3494         sym_link *rtype = operandType (right);
3495         sym_link *ltype = operandType (left);
3496         if (IS_PTR (rtype) && IS_ITEMP (right)
3497             && right->isaddr && compareType (rtype->next, ltype) == 1)
3498           {
3499             right = geniCodeRValue (right, TRUE);
3500           }
3501         else
3502           {
3503             right = geniCodeRValue (right, FALSE);
3504           }
3505         return
3506           geniCodeAssign (left,
3507                 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3508                                                   FALSE),
3509                                   right), 0);
3510       }
3511     case LEFT_ASSIGN:
3512       return
3513         geniCodeAssign (left,
3514                 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3515                                                    ,FALSE),
3516                                    geniCodeRValue (right, FALSE)), 0);
3517     case RIGHT_ASSIGN:
3518       return
3519         geniCodeAssign (left,
3520                geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3521                                                    ,FALSE),
3522                                    geniCodeRValue (right, FALSE)), 0);
3523     case AND_ASSIGN:
3524       return
3525         geniCodeAssign (left,
3526                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3527                                                   FALSE),
3528                                   geniCodeRValue (right, FALSE),
3529                                   BITWISEAND,
3530                                   operandType (left)), 0);
3531     case XOR_ASSIGN:
3532       return
3533         geniCodeAssign (left,
3534                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3535                                                   FALSE),
3536                                   geniCodeRValue (right, FALSE),
3537                                   '^',
3538                                   operandType (left)), 0);
3539     case OR_ASSIGN:
3540       return
3541         geniCodeAssign (left,
3542                   geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3543                                                    ,FALSE),
3544                                    geniCodeRValue (right, FALSE),
3545                                    '|',
3546                                    operandType (left)), 0);
3547     case ',':
3548       return geniCodeRValue (right, FALSE);
3549
3550     case CALL:
3551       return geniCodeCall (ast2iCode (tree->left,lvl+1),
3552                            tree->right,lvl);
3553     case LABEL:
3554       geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3555       return ast2iCode (tree->right,lvl+1);
3556
3557     case GOTO:
3558       geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3559       return ast2iCode (tree->right,lvl+1);
3560
3561     case FUNCTION:
3562       geniCodeFunctionBody (tree,lvl);
3563       return NULL;
3564
3565     case RETURN:
3566       geniCodeReturn (right);
3567       return NULL;
3568
3569     case IFX:
3570       geniCodeIfx (tree,lvl);
3571       return NULL;
3572
3573     case SWITCH:
3574       geniCodeSwitch (tree,lvl);
3575       return NULL;
3576
3577     case INLINEASM:
3578       geniCodeInline (tree);
3579       return NULL;
3580         
3581     case ARRAYINIT:
3582         geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3583         return NULL;
3584     }
3585
3586   return NULL;
3587 }
3588
3589 /*-----------------------------------------------------------------*/
3590 /* reverseICChain - gets from the list and creates a linkedlist    */
3591 /*-----------------------------------------------------------------*/
3592 iCode *
3593 reverseiCChain ()
3594 {
3595   iCode *loop = NULL;
3596   iCode *prev = NULL;
3597
3598   while ((loop = getSet (&iCodeChain)))
3599     {
3600       loop->next = prev;
3601       if (prev)
3602         prev->prev = loop;
3603       prev = loop;
3604     }
3605
3606   return prev;
3607 }
3608
3609
3610 /*-----------------------------------------------------------------*/
3611 /* iCodeFromAst - given an ast will convert it to iCode            */
3612 /*-----------------------------------------------------------------*/
3613 iCode *
3614 iCodeFromAst (ast * tree)
3615 {
3616   returnLabel = newiTempLabel ("_return");
3617   entryLabel = newiTempLabel ("_entry");
3618   ast2iCode (tree,0);
3619   return reverseiCChain ();
3620 }