fixed bug #436360 part 1 and 3
[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(OP_SYMBOL(condition)->type)) {
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       /* (!TARGET_IS_DS390)) && */
1270       (!(options.model == MODEL_FLAT24)) ) &&
1271       options.stackAuto == 0)
1272     ok = 0;
1273
1274   if (!IS_AGGREGATE (sym->type) &&      /* not an aggregate */
1275       !IS_FUNC (sym->type) &&   /* not a function   */
1276       !sym->_isparm &&          /* not a parameter  */
1277       sym->level &&             /* is a local variable */
1278       !sym->addrtaken &&        /* whose address has not been taken */
1279       !sym->reqv &&             /* does not already have a register euivalence */
1280       !IS_VOLATILE (sym->etype) &&      /* not declared as volatile */
1281       !IS_STATIC (sym->etype) &&        /* and not declared static  */
1282       !sym->islbl &&            /* not a label */
1283       ok &&                     /* farspace check */
1284       !IS_BITVAR (sym->etype)   /* not a bit variable */
1285     )
1286     {
1287
1288       /* we will use it after all optimizations
1289          and before liveRange calculation */
1290       sym->reqv = newiTempOperand (sym->type, 0);
1291       sym->reqv->key = sym->key;
1292       OP_SYMBOL (sym->reqv)->key = sym->key;
1293       OP_SYMBOL (sym->reqv)->isreqv = 1;
1294       OP_SYMBOL (sym->reqv)->islocal = 1;
1295       SPIL_LOC (sym->reqv) = sym;
1296     }
1297
1298   if (!IS_AGGREGATE (sym->type))
1299     {
1300       op = newOperand ();
1301       op->type = SYMBOL;
1302       op->operand.symOperand = sym;
1303       op->isaddr = 1;
1304       op->key = sym->key;
1305       op->isvolatile = isOperandVolatile (op, TRUE);
1306       op->isGlobal = isOperandGlobal (op);
1307       op->isPtr = IS_PTR (operandType (op));
1308       op->isParm = sym->_isparm;
1309       return op;
1310     }
1311
1312   /* create :-                     */
1313   /*    itemp = &[_symbol]         */
1314
1315   ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1316   IC_LEFT (ic)->type = SYMBOL;
1317   IC_LEFT (ic)->operand.symOperand = sym;
1318   IC_LEFT (ic)->key = sym->key;
1319   (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1320   (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1321   IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1322
1323   /* create result */
1324   IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1325   if (IS_ARRAY (sym->type))
1326     {
1327       IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1328       IC_RESULT (ic)->isaddr = 0;
1329     }
1330   else
1331     IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1332
1333   IC_RESULT (ic)->operand.symOperand->args = sym->args;
1334
1335   ADDTOCHAIN (ic);
1336
1337   return IC_RESULT (ic);
1338 }
1339
1340 /*-----------------------------------------------------------------*/
1341 /* operandFromValue - creates an operand from value                */
1342 /*-----------------------------------------------------------------*/
1343 operand *
1344 operandFromValue (value * val)
1345 {
1346   operand *op;
1347
1348   /* if this is a symbol then do the symbol thing */
1349   if (val->sym)
1350     return operandFromSymbol (val->sym);
1351
1352   /* this is not a symbol */
1353   op = newOperand ();
1354   op->type = VALUE;
1355   op->operand.valOperand = val;
1356   op->isLiteral = isOperandLiteral (op);
1357   return op;
1358 }
1359
1360 /*-----------------------------------------------------------------*/
1361 /* operandFromLink - operand from typeChain                        */
1362 /*-----------------------------------------------------------------*/
1363 operand *
1364 operandFromLink (sym_link * type)
1365 {
1366   operand *op;
1367
1368   /* operand from sym_link */
1369   if (!type)
1370     return NULL;
1371
1372   op = newOperand ();
1373   op->type = TYPE;
1374   op->operand.typeOperand = copyLinkChain (type);
1375   return op;
1376 }
1377
1378 /*-----------------------------------------------------------------*/
1379 /* operandFromLit - makes an operand from a literal value          */
1380 /*-----------------------------------------------------------------*/
1381 operand *
1382 operandFromLit (double i)
1383 {
1384   return operandFromValue (valueFromLit (i));
1385 }
1386
1387 /*-----------------------------------------------------------------*/
1388 /* operandFromAst - creates an operand from an ast                 */
1389 /*-----------------------------------------------------------------*/
1390 operand *
1391 operandFromAst (ast * tree,int lvl)
1392 {
1393
1394   if (!tree)
1395     return NULL;
1396
1397   /* depending on type do */
1398   switch (tree->type)
1399     {
1400     case EX_OP:
1401       return ast2iCode (tree,lvl+1);
1402       break;
1403
1404     case EX_VALUE:
1405       return operandFromValue (tree->opval.val);
1406       break;
1407
1408     case EX_LINK:
1409       return operandFromLink (tree->opval.lnk);
1410     }
1411
1412   assert (0);
1413   /*  Just to keep the comiler happy */
1414   return (operand *) 0;
1415 }
1416
1417 /*-----------------------------------------------------------------*/
1418 /* setOperandType - sets the operand's type to the given type      */
1419 /*-----------------------------------------------------------------*/
1420 void 
1421 setOperandType (operand * op, sym_link * type)
1422 {
1423   /* depending on the type of operand */
1424   switch (op->type)
1425     {
1426
1427     case VALUE:
1428       op->operand.valOperand->etype =
1429         getSpec (op->operand.valOperand->type =
1430                  copyLinkChain (type));
1431       return;
1432
1433     case SYMBOL:
1434       if (op->operand.symOperand->isitmp)
1435         op->operand.symOperand->etype =
1436           getSpec (op->operand.symOperand->type =
1437                    copyLinkChain (type));
1438       else
1439         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1440                 "attempt to modify type of source");
1441       return;
1442
1443     case TYPE:
1444       op->operand.typeOperand = copyLinkChain (type);
1445       return;
1446     }
1447
1448 }
1449 /*-----------------------------------------------------------------*/
1450 /* Get size in byte of ptr need to access an array                 */
1451 /*-----------------------------------------------------------------*/
1452 int
1453 getArraySizePtr (operand * op)
1454 {
1455   sym_link *ltype = operandType(op);
1456
1457   if(IS_PTR(ltype))
1458     {
1459       int size = getSize(ltype);
1460       return(IS_GENPTR(ltype)?(size-1):size);
1461     }
1462
1463   if(IS_ARRAY(ltype))
1464     {
1465       sym_link *letype = getSpec(ltype);
1466       switch (PTR_TYPE (SPEC_OCLS (letype)))
1467         {
1468         case IPOINTER:
1469         case PPOINTER:
1470         case POINTER:
1471           return (PTRSIZE);
1472         case EEPPOINTER:
1473         case FPOINTER:
1474         case CPOINTER:
1475         case FUNCTION:
1476           return (FPTRSIZE);
1477         case GPOINTER:
1478           return (GPTRSIZE-1);
1479
1480         default:
1481           return (FPTRSIZE);
1482         }
1483     }
1484   return (FPTRSIZE);
1485 }
1486
1487 /*-----------------------------------------------------------------*/
1488 /* perform "usual unary conversions"                               */
1489 /*-----------------------------------------------------------------*/
1490 operand *
1491 usualUnaryConversions (operand * op)
1492 {
1493   if (IS_INTEGRAL (operandType (op)))
1494     {
1495       if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1496         {
1497           /* Widen to int. */
1498           return geniCodeCast (INTTYPE, op, TRUE);
1499         }
1500     }
1501   return op;
1502 }
1503
1504 /*-----------------------------------------------------------------*/
1505 /* perform "usual binary conversions"                              */
1506 /*-----------------------------------------------------------------*/
1507 sym_link *
1508 usualBinaryConversions (operand ** op1, operand ** op2)
1509 {
1510   sym_link *ctype;
1511   sym_link *rtype = operandType (*op2);
1512   sym_link *ltype = operandType (*op1);
1513   
1514   ctype = computeType (ltype, rtype);
1515   *op1 = geniCodeCast (ctype, *op1, TRUE);
1516   *op2 = geniCodeCast (ctype, *op2, TRUE);
1517   
1518   return ctype;
1519 }
1520
1521 /*-----------------------------------------------------------------*/
1522 /* geniCodeValueAtAddress - generate intermeditate code for value  */
1523 /*                          at address                             */
1524 /*-----------------------------------------------------------------*/
1525 operand *
1526 geniCodeRValue (operand * op, bool force)
1527 {
1528   iCode *ic;
1529   sym_link *type = operandType (op);
1530   sym_link *etype = getSpec (type);
1531
1532   /* if this is an array & already */
1533   /* an address then return this   */
1534   if (IS_AGGREGATE (type) ||
1535       (IS_PTR (type) && !force && !op->isaddr))
1536     return operandFromOperand (op);
1537
1538   /* if this is not an address then must be */
1539   /* rvalue already so return this one      */
1540   if (!op->isaddr)
1541     return op;
1542
1543   /* if this is not a temp symbol then */
1544   if (!IS_ITEMP (op) &&
1545       !force &&
1546       !IN_FARSPACE (SPEC_OCLS (etype)))
1547     {
1548       op = operandFromOperand (op);
1549       op->isaddr = 0;
1550       return op;
1551     }
1552
1553   if (IS_SPEC (type) &&
1554       IS_TRUE_SYMOP (op) &&
1555       (!IN_FARSPACE (SPEC_OCLS (etype)) ||
1556       /* TARGET_IS_DS390)) */
1557       (options.model == MODEL_FLAT24) ))
1558     {
1559       op = operandFromOperand (op);
1560       op->isaddr = 0;
1561       return op;
1562     }
1563
1564   ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1565   if (IS_PTR (type) && op->isaddr && force)
1566     type = type->next;
1567
1568   type = copyLinkChain (type);
1569
1570   IC_RESULT (ic) = newiTempOperand (type, 1);
1571   IC_RESULT (ic)->isaddr = 0;
1572
1573 /*     ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1574
1575   /* if the right is a symbol */
1576   if (op->type == SYMBOL)
1577     IC_RESULT (ic)->operand.symOperand->args =
1578       op->operand.symOperand->args;
1579   ADDTOCHAIN (ic);
1580
1581   return IC_RESULT (ic);
1582 }
1583
1584 /*-----------------------------------------------------------------*/
1585 /* geniCodeCast - changes the value from one type to another       */
1586 /*-----------------------------------------------------------------*/
1587 operand *
1588 geniCodeCast (sym_link * type, operand * op, bool implicit)
1589 {
1590   iCode *ic;
1591   sym_link *optype;
1592   sym_link *opetype = getSpec (optype = operandType (op));
1593   sym_link *restype;
1594   int errors=0;
1595
1596   /* one of them has size zero then error */
1597   if (IS_VOID (optype))
1598     {
1599       werror (E_CAST_ZERO);
1600       return op;
1601     }
1602
1603   /* if the operand is already the desired type then do nothing */
1604   if (compareType (type, optype) == 1)
1605     return op;
1606
1607   /* if this is a literal then just change the type & return */
1608   if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1609     return operandFromValue (valCastLiteral (type,
1610                                              operandLitValue (op)));
1611
1612   /* if casting to/from pointers, do some checking */
1613   if (IS_PTR(type)) { // to a pointer
1614     if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1615       if (IS_INTEGRAL(optype)) { 
1616         // maybe this is NULL, than it's ok.
1617         if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1618           if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
1619             // no way to set the storage
1620             if (IS_LITERAL(optype)) {
1621               werror(E_LITERAL_GENERIC);
1622               errors++;
1623             } else {
1624               werror(E_NONPTR2_GENPTR);
1625               errors++;
1626             }
1627           } else if (implicit) {
1628             werror(W_INTEGRAL2PTR_NOCAST);
1629             errors++;
1630           }
1631         }
1632       } else { 
1633         // shouldn't do that with float, array or structure unless to void
1634         if (!IS_VOID(getSpec(type)) && 
1635             !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1636           werror(E_INCOMPAT_TYPES);
1637           errors++;
1638         }
1639       }
1640     } else { // from a pointer to a pointer
1641       if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
1642         // if not a pointer to a function
1643         if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1644           if (implicit) { // if not to generic, they have to match 
1645             if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1646               werror(E_INCOMPAT_PTYPES);
1647               errors++;
1648             }
1649           }
1650         }
1651       }
1652     }
1653   } else { // to a non pointer
1654     if (IS_PTR(optype)) { // from a pointer
1655       if (implicit) { // sneaky
1656         if (IS_INTEGRAL(type)) {
1657           werror(W_PTR2INTEGRAL_NOCAST);
1658           errors++;
1659         } else { // shouldn't do that with float, array or structure
1660           werror(E_INCOMPAT_TYPES);
1661           errors++;
1662         }
1663       }
1664     }
1665   }
1666   if (errors) {
1667     /* fprintf (stderr, "%s%s %d: ", op->operand.symOperand->name,
1668        implicit?"(implicit)":"", errors); */
1669     fprintf (stderr, "from type '");
1670     printTypeChain (optype, stderr);
1671     fprintf (stderr, "' to type '");
1672     printTypeChain (type, stderr);
1673     fprintf (stderr, "'\n");
1674   }
1675
1676   /* if they are the same size create an assignment */
1677   if (getSize (type) == getSize (optype) &&
1678       !IS_BITFIELD (type) &&
1679       !IS_FLOAT (type) &&
1680       !IS_FLOAT (optype) &&
1681       ((IS_SPEC (type) && IS_SPEC (optype)) ||
1682        (!IS_SPEC (type) && !IS_SPEC (optype))))
1683     {
1684
1685       ic = newiCode ('=', NULL, op);
1686       IC_RESULT (ic) = newiTempOperand (type, 0);
1687       SPIL_LOC (IC_RESULT (ic)) =
1688         (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1689       IC_RESULT (ic)->isaddr = 0;
1690     }
1691   else
1692     {
1693       ic = newiCode (CAST, operandFromLink (type),
1694                      geniCodeRValue (op, FALSE));
1695
1696       IC_RESULT (ic) = newiTempOperand (type, 0);
1697     }
1698
1699   /* preserve the storage class & output class */
1700   /* of the original variable                  */
1701   restype = getSpec (operandType (IC_RESULT (ic)));
1702   SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1703   SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1704
1705   ADDTOCHAIN (ic);
1706   return IC_RESULT (ic);
1707 }
1708
1709 /*-----------------------------------------------------------------*/
1710 /* geniCodeLabel - will create a Label                             */
1711 /*-----------------------------------------------------------------*/
1712 void 
1713 geniCodeLabel (symbol * label)
1714 {
1715   iCode *ic;
1716
1717   ic = newiCodeLabelGoto (LABEL, label);
1718   ADDTOCHAIN (ic);
1719 }
1720
1721 /*-----------------------------------------------------------------*/
1722 /* geniCodeGoto  - will create a Goto                              */
1723 /*-----------------------------------------------------------------*/
1724 void 
1725 geniCodeGoto (symbol * label)
1726 {
1727   iCode *ic;
1728
1729   ic = newiCodeLabelGoto (GOTO, label);
1730   ADDTOCHAIN (ic);
1731 }
1732
1733 /*-----------------------------------------------------------------*/
1734 /* geniCodeMultiply - gen intermediate code for multiplication     */
1735 /*-----------------------------------------------------------------*/
1736 operand *
1737 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1738 {
1739   iCode *ic;
1740   int p2 = 0;
1741   sym_link *resType;
1742   LRTYPE;
1743
1744   /* if they are both literal then we know the result */
1745   if (IS_LITERAL (letype) && IS_LITERAL (retype))
1746     return operandFromValue (valMult (left->operand.valOperand,
1747                                       right->operand.valOperand));
1748
1749   if (IS_LITERAL(retype)) {
1750     p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1751   }
1752
1753   resType = usualBinaryConversions (&left, &right);
1754 #if 1
1755   rtype = operandType (right);
1756   retype = getSpec (rtype);
1757   ltype = operandType (left);
1758   letype = getSpec (ltype);
1759 #endif
1760   if (resultIsInt)
1761     {
1762       SPEC_NOUN(getSpec(resType))=V_INT;
1763     }
1764
1765   /* if the right is a literal & power of 2 */
1766   /* then make it a left shift              */
1767   /* code generated for 1 byte * 1 byte literal = 2 bytes result is more 
1768      efficient in most cases than 2 bytes result = 2 bytes << literal 
1769      if port has 1 byte muldiv */
1770   if (p2 && !IS_FLOAT (letype) &&
1771       !((resultIsInt) && (getSize (resType) != getSize (ltype)) && 
1772         (port->support.muldiv == 1)))
1773     {
1774       if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1775         {
1776           /* LEFT_OP need same size for left and result, */
1777           left = geniCodeCast (resType, left, TRUE);
1778           ltype = operandType (left);
1779         }
1780       ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1781     }
1782   else
1783     {
1784       ic = newiCode ('*', left, right);         /* normal multiplication */
1785       /* if the size left or right > 1 then support routine */
1786       if (getSize (ltype) > 1 || getSize (rtype) > 1)
1787         ic->supportRtn = 1;
1788
1789     }
1790   IC_RESULT (ic) = newiTempOperand (resType, 1);
1791
1792   ADDTOCHAIN (ic);
1793   return IC_RESULT (ic);
1794 }
1795
1796 /*-----------------------------------------------------------------*/
1797 /* geniCodeDivision - gen intermediate code for division           */
1798 /*-----------------------------------------------------------------*/
1799 operand *
1800 geniCodeDivision (operand * left, operand * right)
1801 {
1802   iCode *ic;
1803   int p2 = 0;
1804   sym_link *resType;
1805   sym_link *rtype = operandType (right);
1806   sym_link *retype = getSpec (rtype);
1807   sym_link *ltype = operandType (left);
1808   sym_link *letype = getSpec (ltype);
1809
1810   resType = usualBinaryConversions (&left, &right);
1811
1812   /* if the right is a literal & power of 2 */
1813   /* then make it a right shift             */
1814   if (IS_LITERAL (retype) &&
1815       !IS_FLOAT (letype) &&
1816       (p2 = powof2 ((unsigned long)
1817                     floatFromVal (right->operand.valOperand)))) {
1818     ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1819   }
1820   else
1821     {
1822       ic = newiCode ('/', left, right);         /* normal division */
1823       /* if the size left or right > 1 then support routine */
1824       if (getSize (ltype) > 1 || getSize (rtype) > 1)
1825         ic->supportRtn = 1;
1826     }
1827   IC_RESULT (ic) = newiTempOperand (resType, 0);
1828
1829   ADDTOCHAIN (ic);
1830   return IC_RESULT (ic);
1831 }
1832 /*-----------------------------------------------------------------*/
1833 /* geniCodeModulus  - gen intermediate code for modulus            */
1834 /*-----------------------------------------------------------------*/
1835 operand *
1836 geniCodeModulus (operand * left, operand * right)
1837 {
1838   iCode *ic;
1839   sym_link *resType;
1840   LRTYPE;
1841
1842   /* if they are both literal then we know the result */
1843   if (IS_LITERAL (letype) && IS_LITERAL (retype))
1844     return operandFromValue (valMod (left->operand.valOperand,
1845                                      right->operand.valOperand));
1846
1847   resType = usualBinaryConversions (&left, &right);
1848
1849   /* now they are the same size */
1850   ic = newiCode ('%', left, right);
1851
1852   /* if the size left or right > 1 then support routine */
1853   if (getSize (ltype) > 1 || getSize (rtype) > 1)
1854     ic->supportRtn = 1;
1855   IC_RESULT (ic) = newiTempOperand (resType, 0);
1856
1857   ADDTOCHAIN (ic);
1858   return IC_RESULT (ic);
1859 }
1860
1861 /*-----------------------------------------------------------------*/
1862 /* geniCodePtrPtrSubtract - subtracts pointer from pointer         */
1863 /*-----------------------------------------------------------------*/
1864 operand *
1865 geniCodePtrPtrSubtract (operand * left, operand * right)
1866 {
1867   iCode *ic;
1868   operand *result;
1869   LRTYPE;
1870
1871   /* if they are both literals then */
1872   if (IS_LITERAL (letype) && IS_LITERAL (retype))
1873     {
1874       result = operandFromValue (valMinus (left->operand.valOperand,
1875                                            right->operand.valOperand));
1876       goto subtractExit;
1877     }
1878
1879   ic = newiCode ('-', left, right);
1880
1881   IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1882   ADDTOCHAIN (ic);
1883
1884 subtractExit:
1885   return geniCodeDivision (result,
1886                            operandFromLit (getSize (ltype->next)));
1887 }
1888
1889 /*-----------------------------------------------------------------*/
1890 /* geniCodeSubtract - generates code for subtraction               */
1891 /*-----------------------------------------------------------------*/
1892 operand *
1893 geniCodeSubtract (operand * left, operand * right)
1894 {
1895   iCode *ic;
1896   int isarray = 0;
1897   sym_link *resType;
1898   LRTYPE;
1899
1900   /* if they both pointers then */
1901   if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
1902       (IS_PTR (rtype) || IS_ARRAY (rtype)))
1903     return geniCodePtrPtrSubtract (left, right);
1904
1905   /* if they are both literal then we know the result */
1906   if (IS_LITERAL (letype) && IS_LITERAL (retype)
1907       && left->isLiteral && right->isLiteral)
1908     return operandFromValue (valMinus (left->operand.valOperand,
1909                                        right->operand.valOperand));
1910
1911   /* if left is an array or pointer */
1912   if (IS_PTR (ltype) || IS_ARRAY (ltype))
1913     {
1914       isarray = left->isaddr;
1915       right = geniCodeMultiply (right,
1916                                 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
1917       resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
1918     }
1919   else
1920     {                           /* make them the same size */
1921       resType = usualBinaryConversions (&left, &right);
1922     }
1923
1924   ic = newiCode ('-', left, right);
1925
1926   IC_RESULT (ic) = newiTempOperand (resType, 1);
1927   IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1928
1929   /* if left or right is a float */
1930   if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1931     ic->supportRtn = 1;
1932
1933   ADDTOCHAIN (ic);
1934   return IC_RESULT (ic);
1935 }
1936
1937 /*-----------------------------------------------------------------*/
1938 /* geniCodeAdd - generates iCode for addition                      */
1939 /*-----------------------------------------------------------------*/
1940 operand *
1941 geniCodeAdd (operand * left, operand * right,int lvl)
1942 {
1943   iCode *ic;
1944   sym_link *resType;
1945   operand *size;
1946   int isarray = 0;
1947   LRTYPE;
1948
1949   /* if left is an array then array access */
1950   if (IS_ARRAY (ltype))
1951     return geniCodeArray (left, right,lvl);
1952
1953   /* if the right side is LITERAL zero */
1954   /* return the left side              */
1955   if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
1956     return left;
1957
1958   /* if left is literal zero return right */
1959   if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
1960     return right;
1961
1962   /* if left is an array or pointer then size */
1963   if (IS_PTR (ltype))
1964     {
1965       isarray = left->isaddr;
1966       // there is no need to multiply with 1
1967       if (getSize(ltype->next)!=1) {
1968         size  = operandFromLit (getSize (ltype->next));
1969         right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
1970       }
1971       resType = copyLinkChain (ltype);
1972     }
1973   else
1974     {                           /* make them the same size */
1975       resType = usualBinaryConversions (&left, &right);
1976     }
1977
1978   /* if they are both literals then we know */
1979   if (IS_LITERAL (letype) && IS_LITERAL (retype)
1980       && left->isLiteral && right->isLiteral)
1981     return operandFromValue (valPlus (valFromType (letype),
1982                                       valFromType (retype)));
1983
1984   ic = newiCode ('+', left, right);
1985
1986   IC_RESULT (ic) = newiTempOperand (resType, 1);
1987   IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1988
1989   /* if left or right is a float then support
1990      routine */
1991   if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1992     ic->supportRtn = 1;
1993
1994   ADDTOCHAIN (ic);
1995
1996   return IC_RESULT (ic);
1997
1998 }
1999
2000 /*-----------------------------------------------------------------*/
2001 /* aggrToPtr - changes an aggregate to pointer to an aggregate     */
2002 /*-----------------------------------------------------------------*/
2003 sym_link *
2004 aggrToPtr (sym_link * type, bool force)
2005 {
2006   sym_link *etype;
2007   sym_link *ptype;
2008
2009
2010   if (IS_PTR (type) && !force)
2011     return type;
2012
2013   etype = getSpec (type);
2014   ptype = newLink ();
2015
2016   ptype->next = type;
2017   /* if the output class is generic */
2018   if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
2019     DCL_PTR_CONST (ptype) = port->mem.code_ro;
2020
2021   /* if the variable was declared a constant */
2022   /* then the pointer points to a constant */
2023   if (IS_CONSTANT (etype))
2024     DCL_PTR_CONST (ptype) = 1;
2025
2026   /* the variable was volatile then pointer to volatile */
2027   if (IS_VOLATILE (etype))
2028     DCL_PTR_VOLATILE (ptype) = 1;
2029   return ptype;
2030 }
2031
2032 /*-----------------------------------------------------------------*/
2033 /* geniCodeArray2Ptr - array to pointer                            */
2034 /*-----------------------------------------------------------------*/
2035 operand *
2036 geniCodeArray2Ptr (operand * op)
2037 {
2038   sym_link *optype = operandType (op);
2039   sym_link *opetype = getSpec (optype);
2040
2041   /* set the pointer depending on the storage class */
2042   if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2043     DCL_PTR_CONST (optype) = port->mem.code_ro;
2044
2045
2046   /* if the variable was declared a constant */
2047   /* then the pointer points to a constant */
2048   if (IS_CONSTANT (opetype))
2049     DCL_PTR_CONST (optype) = 1;
2050
2051   /* the variable was volatile then pointer to volatile */
2052   if (IS_VOLATILE (opetype))
2053     DCL_PTR_VOLATILE (optype) = 1;
2054   op->isaddr = 0;
2055   return op;
2056 }
2057
2058
2059 /*-----------------------------------------------------------------*/
2060 /* geniCodeArray - array access                                    */
2061 /*-----------------------------------------------------------------*/
2062 operand *
2063 geniCodeArray (operand * left, operand * right,int lvl)
2064 {
2065   iCode *ic;
2066   sym_link *ltype = operandType (left);
2067
2068   if (IS_PTR (ltype))
2069     {
2070       if (IS_PTR (ltype->next) && left->isaddr)
2071         {
2072           left = geniCodeRValue (left, FALSE);
2073         }
2074       return geniCodeDerefPtr (geniCodeAdd (left, right,lvl),lvl);
2075     }
2076
2077   right = geniCodeMultiply (right,
2078                             operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2079
2080   /* we can check for limits here */
2081   if (isOperandLiteral (right) &&
2082       IS_ARRAY (ltype) &&
2083       DCL_ELEM (ltype) &&
2084       (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2085     {
2086       werror (E_ARRAY_BOUND);
2087       right = operandFromLit (0);
2088     }
2089
2090   ic = newiCode ('+', left, right);
2091
2092   IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2093                                       !IS_AGGREGATE (ltype->next) &&
2094                                       !IS_PTR (ltype->next))
2095                                      ? ltype : ltype->next), 0);
2096
2097   IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2098   ADDTOCHAIN (ic);
2099   return IC_RESULT (ic);
2100 }
2101
2102 /*-----------------------------------------------------------------*/
2103 /* geniCodeStruct - generates intermediate code for structres      */
2104 /*-----------------------------------------------------------------*/
2105 operand *
2106 geniCodeStruct (operand * left, operand * right, bool islval)
2107 {
2108   iCode *ic;
2109   sym_link *type = operandType (left);
2110   sym_link *etype = getSpec (type);
2111   sym_link *retype;
2112   symbol *element = getStructElement (SPEC_STRUCT (etype),
2113                                       right->operand.symOperand);
2114
2115   /* add the offset */
2116   ic = newiCode ('+', left, operandFromLit (element->offset));
2117
2118   IC_RESULT (ic) = newiTempOperand (element->type, 0);
2119
2120   /* preserve the storage & output class of the struct */
2121   /* as well as the volatile attribute */
2122   retype = getSpec (operandType (IC_RESULT (ic)));
2123   SPEC_SCLS (retype) = SPEC_SCLS (etype);
2124   SPEC_OCLS (retype) = SPEC_OCLS (etype);
2125   SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2126
2127   if (IS_PTR (element->type))
2128     setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2129
2130   IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2131
2132
2133   ADDTOCHAIN (ic);
2134   return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2135 }
2136
2137 /*-----------------------------------------------------------------*/
2138 /* geniCodePostInc - generate int code for Post increment          */
2139 /*-----------------------------------------------------------------*/
2140 operand *
2141 geniCodePostInc (operand * op)
2142 {
2143   iCode *ic;
2144   operand *rOp;
2145   sym_link *optype = operandType (op);
2146   operand *result;
2147   operand *rv = (IS_ITEMP (op) ?
2148                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2149                  op);
2150   sym_link *rvtype = operandType (rv);
2151   int size = 0;
2152
2153   /* if this is not an address we have trouble */
2154   if (!op->isaddr)
2155     {
2156       werror (E_LVALUE_REQUIRED, "++");
2157       return op;
2158     }
2159
2160   rOp = newiTempOperand (rvtype, 0);
2161   OP_SYMBOL(rOp)->noSpilLoc = 1;
2162
2163   if (IS_ITEMP (rv))
2164     OP_SYMBOL(rv)->noSpilLoc = 1;
2165
2166   geniCodeAssign (rOp, rv, 0);
2167
2168   size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2169   if (IS_FLOAT (rvtype))
2170     ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2171   else
2172     ic = newiCode ('+', rv, operandFromLit (size));
2173
2174   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2175   ADDTOCHAIN (ic);
2176
2177   geniCodeAssign (op, result, 0);
2178
2179   return rOp;
2180
2181 }
2182
2183 /*-----------------------------------------------------------------*/
2184 /* geniCodePreInc - generate code for preIncrement                 */
2185 /*-----------------------------------------------------------------*/
2186 operand *
2187 geniCodePreInc (operand * op)
2188 {
2189   iCode *ic;
2190   sym_link *optype = operandType (op);
2191   operand *rop = (IS_ITEMP (op) ?
2192                   geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2193                   op);
2194   sym_link *roptype = operandType (rop);
2195   operand *result;
2196   int size = 0;
2197
2198   if (!op->isaddr)
2199     {
2200       werror (E_LVALUE_REQUIRED, "++");
2201       return op;
2202     }
2203
2204
2205   size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2206   if (IS_FLOAT (roptype))
2207     ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2208   else
2209     ic = newiCode ('+', rop, operandFromLit (size));
2210   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2211   ADDTOCHAIN (ic);
2212
2213
2214   return geniCodeAssign (op, result, 0);
2215 }
2216
2217 /*-----------------------------------------------------------------*/
2218 /* geniCodePostDec - generates code for Post decrement             */
2219 /*-----------------------------------------------------------------*/
2220 operand *
2221 geniCodePostDec (operand * op)
2222 {
2223   iCode *ic;
2224   operand *rOp;
2225   sym_link *optype = operandType (op);
2226   operand *result;
2227   operand *rv = (IS_ITEMP (op) ?
2228                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2229                  op);
2230   sym_link *rvtype = operandType (rv);
2231   int size = 0;
2232
2233   /* if this is not an address we have trouble */
2234   if (!op->isaddr)
2235     {
2236       werror (E_LVALUE_REQUIRED, "--");
2237       return op;
2238     }
2239
2240   rOp = newiTempOperand (rvtype, 0);
2241   OP_SYMBOL(rOp)->noSpilLoc = 1;
2242
2243   if (IS_ITEMP (rv))
2244     OP_SYMBOL(rv)->noSpilLoc = 1;
2245
2246   geniCodeAssign (rOp, rv, 0);
2247
2248   size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2249   if (IS_FLOAT (rvtype))
2250     ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2251   else
2252     ic = newiCode ('-', rv, operandFromLit (size));
2253
2254   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2255   ADDTOCHAIN (ic);
2256
2257   geniCodeAssign (op, result, 0);
2258
2259   return rOp;
2260
2261 }
2262
2263 /*-----------------------------------------------------------------*/
2264 /* geniCodePreDec - generate code for pre  decrement               */
2265 /*-----------------------------------------------------------------*/
2266 operand *
2267 geniCodePreDec (operand * op)
2268 {
2269   iCode *ic;
2270   sym_link *optype = operandType (op);
2271   operand *rop = (IS_ITEMP (op) ?
2272                   geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2273                   op);
2274   sym_link *roptype = operandType (rop);
2275   operand *result;
2276   int size = 0;
2277
2278   if (!op->isaddr)
2279     {
2280       werror (E_LVALUE_REQUIRED, "--");
2281       return op;
2282     }
2283
2284
2285   size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2286   if (IS_FLOAT (roptype))
2287     ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2288   else
2289     ic = newiCode ('-', rop, operandFromLit (size));
2290   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2291   ADDTOCHAIN (ic);
2292
2293
2294   return geniCodeAssign (op, result, 0);
2295 }
2296
2297
2298 /*-----------------------------------------------------------------*/
2299 /* geniCodeBitwise - gen int code for bitWise  operators           */
2300 /*-----------------------------------------------------------------*/
2301 operand *
2302 geniCodeBitwise (operand * left, operand * right,
2303                  int oper, sym_link * resType)
2304 {
2305   iCode *ic;
2306
2307   left = geniCodeCast (resType, left, TRUE);
2308   right = geniCodeCast (resType, right, TRUE);
2309
2310   ic = newiCode (oper, left, right);
2311   IC_RESULT (ic) = newiTempOperand (resType, 0);
2312
2313   ADDTOCHAIN (ic);
2314   return IC_RESULT (ic);
2315 }
2316
2317 /*-----------------------------------------------------------------*/
2318 /* geniCodeAddressOf - gens icode for '&' address of operator      */
2319 /*-----------------------------------------------------------------*/
2320 operand *
2321 geniCodeAddressOf (operand * op)
2322 {
2323   iCode *ic;
2324   sym_link *p;
2325   sym_link *optype = operandType (op);
2326   sym_link *opetype = getSpec (optype);
2327
2328   /* lvalue check already done in decorateType */
2329   /* this must be a lvalue */
2330 /*     if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2331 /*  werror (E_LVALUE_REQUIRED,"&"); */
2332 /*  return op; */
2333 /*     } */
2334
2335   p = newLink ();
2336   p->class = DECLARATOR;
2337
2338   /* set the pointer depending on the storage class */
2339   if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2340     DCL_PTR_CONST (p) = port->mem.code_ro;
2341
2342   /* make sure we preserve the const & volatile */
2343   if (IS_CONSTANT (opetype))
2344     DCL_PTR_CONST (p) = 1;
2345
2346   if (IS_VOLATILE (opetype))
2347     DCL_PTR_VOLATILE (p) = 1;
2348
2349   p->next = copyLinkChain (optype);
2350
2351   /* if already a temp */
2352   if (IS_ITEMP (op))
2353     {
2354       setOperandType (op, p);
2355       op->isaddr = 0;
2356       return op;
2357     }
2358
2359   /* other wise make this of the type coming in */
2360   ic = newiCode (ADDRESS_OF, op, NULL);
2361   IC_RESULT (ic) = newiTempOperand (p, 1);
2362   IC_RESULT (ic)->isaddr = 0;
2363   ADDTOCHAIN (ic);
2364   return IC_RESULT (ic);
2365 }
2366 /*-----------------------------------------------------------------*/
2367 /* setOClass - sets the output class depending on the pointer type */
2368 /*-----------------------------------------------------------------*/
2369 void 
2370 setOClass (sym_link * ptr, sym_link * spec)
2371 {
2372   switch (DCL_TYPE (ptr))
2373     {
2374     case POINTER:
2375       SPEC_OCLS (spec) = data;
2376       break;
2377
2378     case GPOINTER:
2379       SPEC_OCLS (spec) = generic;
2380       break;
2381
2382     case FPOINTER:
2383       SPEC_OCLS (spec) = xdata;
2384       break;
2385
2386     case CPOINTER:
2387       SPEC_OCLS (spec) = code;
2388       break;
2389
2390     case IPOINTER:
2391       SPEC_OCLS (spec) = idata;
2392       break;
2393
2394     case PPOINTER:
2395       SPEC_OCLS (spec) = xstack;
2396       break;
2397
2398     case EEPPOINTER:
2399       SPEC_OCLS (spec) = eeprom;
2400       break;
2401
2402     default:
2403       break;
2404
2405     }
2406 }
2407
2408 /*-----------------------------------------------------------------*/
2409 /* geniCodeDerefPtr - dereference pointer with '*'                 */
2410 /*-----------------------------------------------------------------*/
2411 operand *
2412 geniCodeDerefPtr (operand * op,int lvl)
2413 {
2414   sym_link *rtype, *retype;
2415   sym_link *optype = operandType (op);
2416
2417   /* if this is a pointer then generate the rvalue */
2418   if (IS_PTR (optype))
2419     {
2420       if (IS_TRUE_SYMOP (op))
2421         {
2422           op->isaddr = 1;
2423           op = geniCodeRValue (op, TRUE);
2424         }
2425       else
2426         op = geniCodeRValue (op, TRUE);
2427     }
2428
2429   /* now get rid of the pointer part */
2430   if (isLvaluereq(lvl) && IS_ITEMP (op))
2431     {
2432       retype = getSpec (rtype = copyLinkChain (optype));
2433     }
2434   else
2435     {
2436       retype = getSpec (rtype = copyLinkChain (optype->next));
2437     }
2438
2439   /* if this is a pointer then outputclass needs 2b updated */
2440   if (IS_PTR (optype))
2441     setOClass (optype, retype);
2442
2443   op->isGptr = IS_GENPTR (optype);
2444
2445   /* if the pointer was declared as a constant */
2446   /* then we cannot allow assignment to the derefed */
2447   if (IS_PTR_CONST (optype))
2448     SPEC_CONST (retype) = 1;
2449
2450   op->isaddr = (IS_PTR (rtype) ||
2451                 IS_STRUCT (rtype) ||
2452                 IS_INT (rtype) ||
2453                 IS_CHAR (rtype) ||
2454                 IS_FLOAT (rtype));
2455
2456   if (!isLvaluereq(lvl))
2457     op = geniCodeRValue (op, TRUE);
2458
2459   setOperandType (op, rtype);
2460
2461   return op;
2462 }
2463
2464 /*-----------------------------------------------------------------*/
2465 /* geniCodeUnaryMinus - does a unary minus of the operand          */
2466 /*-----------------------------------------------------------------*/
2467 operand *
2468 geniCodeUnaryMinus (operand * op)
2469 {
2470   iCode *ic;
2471   sym_link *optype = operandType (op);
2472
2473   if (IS_LITERAL (optype))
2474     return operandFromLit (-floatFromVal (op->operand.valOperand));
2475
2476   ic = newiCode (UNARYMINUS, op, NULL);
2477   IC_RESULT (ic) = newiTempOperand (optype, 0);
2478   ADDTOCHAIN (ic);
2479   return IC_RESULT (ic);
2480 }
2481
2482 /*-----------------------------------------------------------------*/
2483 /* geniCodeLeftShift - gen i code for left shift                   */
2484 /*-----------------------------------------------------------------*/
2485 operand *
2486 geniCodeLeftShift (operand * left, operand * right)
2487 {
2488   iCode *ic;
2489
2490   ic = newiCode (LEFT_OP, left, right);
2491   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2492   ADDTOCHAIN (ic);
2493   return IC_RESULT (ic);
2494 }
2495
2496 /*-----------------------------------------------------------------*/
2497 /* geniCodeRightShift - gen i code for right shift                 */
2498 /*-----------------------------------------------------------------*/
2499 operand *
2500 geniCodeRightShift (operand * left, operand * right)
2501 {
2502   iCode *ic;
2503
2504   ic = newiCode (RIGHT_OP, left, right);
2505   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2506   ADDTOCHAIN (ic);
2507   return IC_RESULT (ic);
2508 }
2509
2510 /*-----------------------------------------------------------------*/
2511 /* geniCodeLogic- logic code                                       */
2512 /*-----------------------------------------------------------------*/
2513 operand *
2514 geniCodeLogic (operand * left, operand * right, int op)
2515 {
2516   iCode *ic;
2517   sym_link *ctype;
2518   sym_link *rtype = operandType (right);
2519   sym_link *ltype = operandType (left);
2520
2521   /* left is integral type and right is literal then
2522      check if the literal value is within bounds */
2523   if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2524     {
2525       checkConstantRange(ltype, 
2526                          OP_VALUE(right), "compare operation", 1);
2527     }
2528
2529   ctype = usualBinaryConversions (&left, &right);
2530
2531   ic = newiCode (op, left, right);
2532   IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2533
2534   /* if comparing float
2535      and not a '==' || '!=' || '&&' || '||' (these
2536      will be inlined */
2537   if (IS_FLOAT(ctype) &&
2538       op != EQ_OP &&
2539       op != NE_OP &&
2540       op != AND_OP &&
2541       op != OR_OP)
2542     ic->supportRtn = 1;
2543
2544   ADDTOCHAIN (ic);
2545   return IC_RESULT (ic);
2546 }
2547
2548 /*-----------------------------------------------------------------*/
2549 /* geniCodeUnary - for a a generic unary operation                 */
2550 /*-----------------------------------------------------------------*/
2551 operand *
2552 geniCodeUnary (operand * op, int oper)
2553 {
2554   iCode *ic = newiCode (oper, op, NULL);
2555
2556   IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2557   ADDTOCHAIN (ic);
2558   return IC_RESULT (ic);
2559 }
2560
2561 /*-----------------------------------------------------------------*/
2562 /* geniCodeConditional - geniCode for '?' ':' operation            */
2563 /*-----------------------------------------------------------------*/
2564 operand *
2565 geniCodeConditional (ast * tree,int lvl)
2566 {
2567   iCode *ic;
2568   symbol *falseLabel = newiTempLabel (NULL);
2569   symbol *exitLabel = newiTempLabel (NULL);
2570   operand *cond = ast2iCode (tree->left,lvl+1);
2571   operand *true, *false, *result;
2572
2573   ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2574                           NULL, falseLabel);
2575   ADDTOCHAIN (ic);
2576
2577   true = ast2iCode (tree->right->left,lvl+1);
2578
2579   /* move the value to a new Operand */
2580   result = newiTempOperand (operandType (true), 0);
2581   geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2582
2583   /* generate an unconditional goto */
2584   geniCodeGoto (exitLabel);
2585
2586   /* now for the right side */
2587   geniCodeLabel (falseLabel);
2588
2589   false = ast2iCode (tree->right->right,lvl+1);
2590   geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2591
2592   /* create the exit label */
2593   geniCodeLabel (exitLabel);
2594
2595   return result;
2596 }
2597
2598 /*-----------------------------------------------------------------*/
2599 /* geniCodeAssign - generate code for assignment                   */
2600 /*-----------------------------------------------------------------*/
2601 operand *
2602 geniCodeAssign (operand * left, operand * right, int nosupdate)
2603 {
2604   iCode *ic;
2605   sym_link *ltype = operandType (left);
2606   sym_link *rtype = operandType (right);
2607
2608   if (!left->isaddr && !IS_ITEMP (left))
2609     {
2610       werror (E_LVALUE_REQUIRED, "assignment");
2611       return left;
2612     }
2613
2614   /* left is integral type and right is literal then
2615      check if the literal value is within bounds */
2616   if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2617     {
2618       checkConstantRange(ltype, 
2619                          OP_VALUE(right), "= operation", 0);
2620     }
2621
2622   /* if the left & right type don't exactly match */
2623   /* if pointer set then make sure the check is
2624      done with the type & not the pointer */
2625   /* then cast rights type to left */
2626
2627   /* first check the type for pointer assignement */
2628   if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2629       compareType (ltype, rtype) < 0)
2630     {
2631       if (compareType (ltype->next, rtype) < 0)
2632         right = geniCodeCast (ltype->next, right, TRUE);
2633     }
2634   else if (compareType (ltype, rtype) < 0)
2635     right = geniCodeCast (ltype, right, TRUE);
2636
2637   /* if left is a true symbol & ! volatile
2638      create an assignment to temporary for
2639      the right & then assign this temporary
2640      to the symbol this is SSA . isn't it simple
2641      and folks have published mountains of paper on it */
2642   if (IS_TRUE_SYMOP (left) &&
2643       !isOperandVolatile (left, FALSE) &&
2644       isOperandGlobal (left))
2645     {
2646       symbol *sym = NULL;
2647
2648       if (IS_TRUE_SYMOP (right))
2649         sym = OP_SYMBOL (right);
2650       ic = newiCode ('=', NULL, right);
2651       IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2652       SPIL_LOC (right) = sym;
2653       ADDTOCHAIN (ic);
2654     }
2655
2656   ic = newiCode ('=', NULL, right);
2657   IC_RESULT (ic) = left;
2658   ADDTOCHAIN (ic);
2659
2660   /* if left isgptr flag is set then support
2661      routine will be required */
2662   if (left->isGptr)
2663     ic->supportRtn = 1;
2664
2665   ic->nosupdate = nosupdate;
2666   return left;
2667 }
2668
2669 /*-----------------------------------------------------------------*/
2670 /* geniCodeSEParms - generate code for side effecting fcalls       */
2671 /*-----------------------------------------------------------------*/
2672 static void 
2673 geniCodeSEParms (ast * parms,int lvl)
2674 {
2675   if (!parms)
2676     return;
2677
2678   if (parms->type == EX_OP && parms->opval.op == PARAM)
2679     {
2680       geniCodeSEParms (parms->left,lvl);
2681       geniCodeSEParms (parms->right,lvl);
2682       return;
2683     }
2684
2685   /* hack don't like this but too lazy to think of
2686      something better */
2687   if (IS_ADDRESS_OF_OP (parms))
2688     parms->left->lvalue = 1;
2689
2690   if (IS_CAST_OP (parms) &&
2691       IS_PTR (parms->ftype) &&
2692       IS_ADDRESS_OF_OP (parms->right))
2693     parms->right->left->lvalue = 1;
2694
2695   parms->opval.oprnd =
2696     geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2697
2698   parms->type = EX_OPERAND;
2699 }
2700
2701 /*-----------------------------------------------------------------*/
2702 /* geniCodeParms - generates parameters                            */
2703 /*-----------------------------------------------------------------*/
2704 static void 
2705 geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func,int lvl)
2706 {
2707   iCode *ic;
2708   operand *pval;
2709
2710   if (!parms)
2711     return;
2712
2713   /* if this is a param node then do the left & right */
2714   if (parms->type == EX_OP && parms->opval.op == PARAM)
2715     {
2716       geniCodeParms (parms->left, stack, fetype, func,lvl);
2717       geniCodeParms (parms->right, stack, fetype, func,lvl);
2718       return;
2719     }
2720
2721   /* get the parameter value */
2722   if (parms->type == EX_OPERAND)
2723     pval = parms->opval.oprnd;
2724   else
2725     {
2726       /* maybe this else should go away ?? */
2727       /* hack don't like this but too lazy to think of
2728          something better */
2729       if (IS_ADDRESS_OF_OP (parms))
2730         parms->left->lvalue = 1;
2731
2732       if (IS_CAST_OP (parms) &&
2733           IS_PTR (parms->ftype) &&
2734           IS_ADDRESS_OF_OP (parms->right))
2735         parms->right->left->lvalue = 1;
2736
2737       pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2738     }
2739
2740   /* if register parm then make it a send */
2741   if (((parms->argSym && IS_REGPARM (parms->argSym->etype)) ||
2742        IS_REGPARM (parms->etype)) && !func->hasVargs)
2743     {
2744       ic = newiCode (SEND, pval, NULL);
2745       ADDTOCHAIN (ic);
2746     }
2747   else
2748     {
2749       /* now decide whether to push or assign */
2750       if (!(options.stackAuto || IS_RENT (fetype)))
2751         {
2752
2753           /* assign */
2754           operand *top = operandFromSymbol (parms->argSym);
2755           geniCodeAssign (top, pval, 1);
2756         }
2757       else
2758         {
2759           sym_link *p = operandType (pval);
2760           /* push */
2761           ic = newiCode (IPUSH, pval, NULL);
2762           ic->parmPush = 1;
2763           /* update the stack adjustment */
2764           *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2765           ADDTOCHAIN (ic);
2766         }
2767     }
2768
2769 }
2770
2771 /*-----------------------------------------------------------------*/
2772 /* geniCodeCall - generates temp code for calling                  */
2773 /*-----------------------------------------------------------------*/
2774 operand *
2775 geniCodeCall (operand * left, ast * parms,int lvl)
2776 {
2777   iCode *ic;
2778   operand *result;
2779   sym_link *type, *etype;
2780   int stack = 0;
2781
2782   if (!IS_FUNC(OP_SYMBOL(left)->type) && 
2783       !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2784     werror (E_FUNCTION_EXPECTED);
2785     return NULL;
2786   }
2787
2788   /* take care of parameters with side-effecting
2789      function calls in them, this is required to take care
2790      of overlaying function parameters */
2791   geniCodeSEParms (parms,lvl);
2792
2793   /* first the parameters */
2794   geniCodeParms (parms, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2795
2796   /* now call : if symbol then pcall */
2797   if (IS_OP_POINTER (left) || IS_ITEMP(left))
2798     ic = newiCode (PCALL, left, NULL);
2799   else
2800     ic = newiCode (CALL, left, NULL);
2801
2802   IC_ARGS (ic) = left->operand.symOperand->args;
2803   type = copyLinkChain (operandType (left)->next);
2804   etype = getSpec (type);
2805   SPEC_EXTR (etype) = 0;
2806   IC_RESULT (ic) = result = newiTempOperand (type, 1);
2807
2808   ADDTOCHAIN (ic);
2809
2810   /* stack adjustment after call */
2811   ic->parmBytes = stack;
2812
2813   return result;
2814 }
2815
2816 /*-----------------------------------------------------------------*/
2817 /* geniCodeReceive - generate intermediate code for "receive"      */
2818 /*-----------------------------------------------------------------*/
2819 static void 
2820 geniCodeReceive (value * args)
2821 {
2822   /* for all arguments that are passed in registers */
2823   while (args)
2824     {
2825
2826       if (IS_REGPARM (args->etype))
2827         {
2828           operand *opr = operandFromValue (args);
2829           operand *opl;
2830           symbol *sym = OP_SYMBOL (opr);
2831           iCode *ic;
2832
2833           /* we will use it after all optimizations
2834              and before liveRange calculation */
2835           if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2836             {
2837
2838               if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2839                   options.stackAuto == 0 &&
2840                   /* !TARGET_IS_DS390) */
2841                   (!(options.model == MODEL_FLAT24)) )
2842                 {
2843                 }
2844               else
2845                 {
2846                   opl = newiTempOperand (args->type, 0);
2847                   sym->reqv = opl;
2848                   sym->reqv->key = sym->key;
2849                   OP_SYMBOL (sym->reqv)->key = sym->key;
2850                   OP_SYMBOL (sym->reqv)->isreqv = 1;
2851                   OP_SYMBOL (sym->reqv)->islocal = 0;
2852                   SPIL_LOC (sym->reqv) = sym;
2853                 }
2854             }
2855
2856           ic = newiCode (RECEIVE, NULL, NULL);
2857           currFunc->recvSize = getSize (sym->etype);
2858           IC_RESULT (ic) = opr;
2859           ADDTOCHAIN (ic);
2860         }
2861
2862       args = args->next;
2863     }
2864 }
2865
2866 /*-----------------------------------------------------------------*/
2867 /* geniCodeFunctionBody - create the function body                 */
2868 /*-----------------------------------------------------------------*/
2869 void 
2870 geniCodeFunctionBody (ast * tree,int lvl)
2871 {
2872   iCode *ic;
2873   operand *func;
2874   sym_link *fetype;
2875   int savelineno;
2876
2877   /* reset the auto generation */
2878   /* numbers */
2879   iTempNum = 0;
2880   iTempLblNum = 0;
2881   operandKey = 0;
2882   iCodeKey = 0;
2883   func = ast2iCode (tree->left,lvl+1);
2884   fetype = getSpec (operandType (func));
2885
2886   savelineno = lineno;
2887   lineno = OP_SYMBOL (func)->lineDef;
2888   /* create an entry label */
2889   geniCodeLabel (entryLabel);
2890   lineno = savelineno;
2891
2892   /* create a proc icode */
2893   ic = newiCode (FUNCTION, func, NULL);
2894   /* if the function has parmas   then */
2895   /* save the parameters information    */
2896   ic->argLabel.args = tree->values.args;
2897   ic->lineno = OP_SYMBOL (func)->lineDef;
2898
2899   ADDTOCHAIN (ic);
2900
2901   /* for all parameters that are passed
2902      on registers add a "receive" */
2903   geniCodeReceive (tree->values.args);
2904
2905   /* generate code for the body */
2906   ast2iCode (tree->right,lvl+1);
2907
2908   /* create a label for return */
2909   geniCodeLabel (returnLabel);
2910
2911   /* now generate the end proc */
2912   ic = newiCode (ENDFUNCTION, func, NULL);
2913   ADDTOCHAIN (ic);
2914   return;
2915 }
2916
2917 /*-----------------------------------------------------------------*/
2918 /* geniCodeReturn - gen icode for 'return' statement               */
2919 /*-----------------------------------------------------------------*/
2920 void 
2921 geniCodeReturn (operand * op)
2922 {
2923   iCode *ic;
2924
2925   /* if the operand is present force an rvalue */
2926   if (op)
2927     op = geniCodeRValue (op, FALSE);
2928
2929   ic = newiCode (RETURN, op, NULL);
2930   ADDTOCHAIN (ic);
2931 }
2932
2933 /*-----------------------------------------------------------------*/
2934 /* geniCodeIfx - generates code for extended if statement          */
2935 /*-----------------------------------------------------------------*/
2936 void 
2937 geniCodeIfx (ast * tree,int lvl)
2938 {
2939   iCode *ic;
2940   operand *condition = ast2iCode (tree->left,lvl+1);
2941   sym_link *cetype;
2942
2943   /* if condition is null then exit */
2944   if (!condition)
2945     goto exit;
2946   else
2947     condition = geniCodeRValue (condition, FALSE);
2948
2949   cetype = getSpec (operandType (condition));
2950   /* if the condition is a literal */
2951   if (IS_LITERAL (cetype))
2952     {
2953       if (floatFromVal (condition->operand.valOperand))
2954         {
2955           if (tree->trueLabel)
2956             geniCodeGoto (tree->trueLabel);
2957           else
2958             assert (1);
2959         }
2960       else
2961         {
2962           if (tree->falseLabel)
2963             geniCodeGoto (tree->falseLabel);
2964           else
2965             assert (1);
2966         }
2967       goto exit;
2968     }
2969
2970   if (tree->trueLabel)
2971     {
2972       ic = newiCodeCondition (condition,
2973                               tree->trueLabel,
2974                               NULL);
2975       ADDTOCHAIN (ic);
2976
2977       if (tree->falseLabel)
2978         geniCodeGoto (tree->falseLabel);
2979     }
2980   else
2981     {
2982       ic = newiCodeCondition (condition,
2983                               NULL,
2984                               tree->falseLabel);
2985       ADDTOCHAIN (ic);
2986     }
2987
2988 exit:
2989   ast2iCode (tree->right,lvl+1);
2990 }
2991
2992 /*-----------------------------------------------------------------*/
2993 /* geniCodeJumpTable - tries to create a jump table for switch     */
2994 /*-----------------------------------------------------------------*/
2995 int 
2996 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
2997 {
2998   int min = 0, max = 0, t, cnt = 0;
2999   value *vch;
3000   iCode *ic;
3001   operand *boundary;
3002   symbol *falseLabel;
3003   set *labels = NULL;
3004
3005   if (!tree || !caseVals)
3006     return 0;
3007
3008   /* the criteria for creating a jump table is */
3009   /* all integer numbers between the maximum & minimum must */
3010   /* be present , the maximum value should not exceed 255 */
3011   min = max = (int) floatFromVal (vch = caseVals);
3012   sprintf (buffer, "_case_%d_%d",
3013            tree->values.switchVals.swNum,
3014            min);
3015   addSet (&labels, newiTempLabel (buffer));
3016
3017   /* if there is only one case value then no need */
3018   if (!(vch = vch->next))
3019     return 0;
3020
3021   while (vch)
3022     {
3023       if (((t = (int) floatFromVal (vch)) - max) != 1)
3024         return 0;
3025       sprintf (buffer, "_case_%d_%d",
3026                tree->values.switchVals.swNum,
3027                t);
3028       addSet (&labels, newiTempLabel (buffer));
3029       max = t;
3030       cnt++;
3031       vch = vch->next;
3032     }
3033
3034   /* if the number of case statements <= 2 then */
3035   /* it is not economical to create the jump table */
3036   /* since two compares are needed for boundary conditions */
3037   if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3038     return 0;
3039
3040   if (tree->values.switchVals.swDefault)
3041     sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3042   else
3043     sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3044
3045   falseLabel = newiTempLabel (buffer);
3046
3047   /* so we can create a jumptable */
3048   /* first we rule out the boundary conditions */
3049   /* if only optimization says so */
3050   if (!optimize.noJTabBoundary)
3051     {
3052       sym_link *cetype = getSpec (operandType (cond));
3053       /* no need to check the lower bound if
3054          the condition is unsigned & minimum value is zero */
3055       if (!(min == 0 && SPEC_USIGN (cetype)))
3056         {
3057           boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3058           ic = newiCodeCondition (boundary, falseLabel, NULL);
3059           ADDTOCHAIN (ic);
3060         }
3061
3062       /* now for upper bounds */
3063       boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3064       ic = newiCodeCondition (boundary, falseLabel, NULL);
3065       ADDTOCHAIN (ic);
3066     }
3067
3068   /* if the min is not zero then we no make it zero */
3069   if (min)
3070     {
3071       cond = geniCodeSubtract (cond, operandFromLit (min));
3072       setOperandType (cond, UCHARTYPE);
3073     }
3074
3075   /* now create the jumptable */
3076   ic = newiCode (JUMPTABLE, NULL, NULL);
3077   IC_JTCOND (ic) = cond;
3078   IC_JTLABELS (ic) = labels;
3079   ADDTOCHAIN (ic);
3080   return 1;
3081 }
3082
3083 /*-----------------------------------------------------------------*/
3084 /* geniCodeSwitch - changes a switch to a if statement             */
3085 /*-----------------------------------------------------------------*/
3086 void 
3087 geniCodeSwitch (ast * tree,int lvl)
3088 {
3089   iCode *ic;
3090   operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3091   value *caseVals = tree->values.switchVals.swVals;
3092   symbol *trueLabel, *falseLabel;
3093
3094   /* if we can make this a jump table */
3095   if (geniCodeJumpTable (cond, caseVals, tree))
3096     goto jumpTable;             /* no need for the comparison */
3097
3098   /* for the cases defined do */
3099   while (caseVals)
3100     {
3101
3102       operand *compare = geniCodeLogic (cond,
3103                                         operandFromValue (caseVals),
3104                                         EQ_OP);
3105
3106       sprintf (buffer, "_case_%d_%d",
3107                tree->values.switchVals.swNum,
3108                (int) floatFromVal (caseVals));
3109       trueLabel = newiTempLabel (buffer);
3110
3111       ic = newiCodeCondition (compare, trueLabel, NULL);
3112       ADDTOCHAIN (ic);
3113       caseVals = caseVals->next;
3114     }
3115
3116
3117
3118   /* if default is present then goto break else break */
3119   if (tree->values.switchVals.swDefault)
3120     sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3121   else
3122     sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3123
3124   falseLabel = newiTempLabel (buffer);
3125   geniCodeGoto (falseLabel);
3126
3127 jumpTable:
3128   ast2iCode (tree->right,lvl+1);
3129 }
3130
3131 /*-----------------------------------------------------------------*/
3132 /* geniCodeInline - intermediate code for inline assembler         */
3133 /*-----------------------------------------------------------------*/
3134 static void 
3135 geniCodeInline (ast * tree)
3136 {
3137   iCode *ic;
3138
3139   ic = newiCode (INLINEASM, NULL, NULL);
3140   IC_INLINE (ic) = tree->values.inlineasm;
3141   ADDTOCHAIN (ic);
3142 }
3143
3144 /*-----------------------------------------------------------------*/
3145 /* geniCodeArrayInit - intermediate code for array initializer     */
3146 /*-----------------------------------------------------------------*/
3147 static void 
3148 geniCodeArrayInit (ast * tree, operand *array)
3149 {
3150   iCode *ic;
3151
3152   if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3153     ic = newiCode (ARRAYINIT, array, NULL);
3154     IC_ARRAYILIST (ic) = tree->values.constlist;
3155   } else {
3156     operand *left=newOperand(), *right=newOperand();
3157     left->type=right->type=SYMBOL;
3158     OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3159     OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3160     ic = newiCode (ARRAYINIT, left, right);
3161   }
3162   ADDTOCHAIN (ic);
3163 }
3164
3165 /*-----------------------------------------------------------------*/
3166 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some      */
3167 /* particular case. Ie : assigning or dereferencing array or ptr   */
3168 /*-----------------------------------------------------------------*/
3169 set * lvaluereqSet = NULL;
3170 typedef struct lvalItem
3171   {
3172     int req;
3173     int lvl;
3174   }
3175 lvalItem;
3176
3177 /*-----------------------------------------------------------------*/
3178 /* addLvaluereq - add a flag for lvalreq for current ast level     */
3179 /*-----------------------------------------------------------------*/
3180 void addLvaluereq(int lvl)
3181 {
3182   lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3183   lpItem->req=1;
3184   lpItem->lvl=lvl;
3185   addSetHead(&lvaluereqSet,lpItem);
3186
3187 }
3188 /*-----------------------------------------------------------------*/
3189 /* delLvaluereq - del a flag for lvalreq for current ast level     */
3190 /*-----------------------------------------------------------------*/
3191 void delLvaluereq()
3192 {
3193   lvalItem * lpItem;
3194   lpItem = getSet(&lvaluereqSet);
3195   if(lpItem) Safe_free(lpItem);
3196 }
3197 /*-----------------------------------------------------------------*/
3198 /* clearLvaluereq - clear lvalreq flag                             */
3199 /*-----------------------------------------------------------------*/
3200 void clearLvaluereq()
3201 {
3202   lvalItem * lpItem;
3203   lpItem = peekSet(lvaluereqSet);
3204   if(lpItem) lpItem->req = 0;
3205 }
3206 /*-----------------------------------------------------------------*/
3207 /* getLvaluereq - get the last lvalreq level                       */
3208 /*-----------------------------------------------------------------*/
3209 int getLvaluereqLvl()
3210 {
3211   lvalItem * lpItem;
3212   lpItem = peekSet(lvaluereqSet);
3213   if(lpItem) return lpItem->lvl;
3214   return 0;
3215 }
3216 /*-----------------------------------------------------------------*/
3217 /* isLvaluereq - is lvalreq valid for this level ?                 */
3218 /*-----------------------------------------------------------------*/
3219 int isLvaluereq(int lvl)
3220 {
3221   lvalItem * lpItem;
3222   lpItem = peekSet(lvaluereqSet);
3223   if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3224   return 0;
3225 }
3226
3227 /*-----------------------------------------------------------------*/
3228 /* ast2iCode - creates an icodeList from an ast                    */
3229 /*-----------------------------------------------------------------*/
3230 operand *
3231 ast2iCode (ast * tree,int lvl)
3232 {
3233   operand *left = NULL;
3234   operand *right = NULL;
3235   if (!tree)
3236     return NULL;
3237   /* set the global variables for filename & line number */
3238   if (tree->filename)
3239     filename = tree->filename;
3240   if (tree->lineno)
3241     lineno = tree->lineno;
3242   if (tree->block)
3243     block = tree->block;
3244   if (tree->level)
3245     scopeLevel = tree->level;
3246
3247   if (tree->type == EX_VALUE)
3248     return operandFromValue (tree->opval.val);
3249
3250   if (tree->type == EX_LINK)
3251     return operandFromLink (tree->opval.lnk);
3252
3253   /* if we find a nullop */
3254   if (tree->type == EX_OP &&
3255      (tree->opval.op == NULLOP ||
3256      tree->opval.op == BLOCK))
3257     {
3258       ast2iCode (tree->left,lvl+1);
3259       ast2iCode (tree->right,lvl+1);
3260       return NULL;
3261     }
3262
3263   /* special cases for not evaluating */
3264   if (tree->opval.op != ':' &&
3265       tree->opval.op != '?' &&
3266       tree->opval.op != CALL &&
3267       tree->opval.op != IFX &&
3268       tree->opval.op != LABEL &&
3269       tree->opval.op != GOTO &&
3270       tree->opval.op != SWITCH &&
3271       tree->opval.op != FUNCTION &&
3272       tree->opval.op != INLINEASM)
3273     {
3274
3275         if (IS_ASSIGN_OP (tree->opval.op) ||
3276            IS_DEREF_OP (tree) ||
3277            (tree->opval.op == '&' && !tree->right) ||
3278            tree->opval.op == PTR_OP)
3279           {
3280             addLvaluereq(lvl);
3281             if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3282                (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3283               clearLvaluereq();
3284
3285             left = operandFromAst (tree->left,lvl);
3286             delLvaluereq();
3287             if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3288               left = geniCodeRValue (left, TRUE);
3289           }
3290         else
3291           {
3292             left = operandFromAst (tree->left,lvl);
3293           }
3294         if (tree->opval.op == INC_OP ||
3295             tree->opval.op == DEC_OP)
3296           {
3297             addLvaluereq(lvl);
3298             right = operandFromAst (tree->right,lvl);
3299             delLvaluereq();
3300           }
3301         else
3302           {
3303             right = operandFromAst (tree->right,lvl);
3304           }
3305       }
3306
3307   /* now depending on the type of operand */
3308   /* this will be a biggy                 */
3309   switch (tree->opval.op)
3310     {
3311
3312     case '[':                   /* array operation */
3313       {
3314         //sym_link *ltype = operandType (left);
3315         //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3316         left = geniCodeRValue (left, FALSE);
3317         right = geniCodeRValue (right, TRUE);
3318       }
3319
3320       return geniCodeArray (left, right,lvl);
3321
3322     case '.':                   /* structure dereference */
3323       if (IS_PTR (operandType (left)))
3324         left = geniCodeRValue (left, TRUE);
3325       else
3326         left = geniCodeRValue (left, FALSE);
3327
3328       return geniCodeStruct (left, right, tree->lvalue);
3329
3330     case PTR_OP:                /* structure pointer dereference */
3331       {
3332         sym_link *pType;
3333         pType = operandType (left);
3334         left = geniCodeRValue (left, TRUE);
3335
3336         setOClass (pType, getSpec (operandType (left)));
3337       }
3338
3339       return geniCodeStruct (left, right, tree->lvalue);
3340
3341     case INC_OP:                /* increment operator */
3342       if (left)
3343         return geniCodePostInc (left);
3344       else
3345         return geniCodePreInc (right);
3346
3347     case DEC_OP:                /* decrement operator */
3348       if (left)
3349         return geniCodePostDec (left);
3350       else
3351         return geniCodePreDec (right);
3352
3353     case '&':                   /* bitwise and or address of operator */
3354       if (right)
3355         {                       /* this is a bitwise operator   */
3356           left = geniCodeRValue (left, FALSE);
3357           right = geniCodeRValue (right, FALSE);
3358           return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3359         }
3360       else
3361         return geniCodeAddressOf (left);
3362
3363     case '|':                   /* bitwise or & xor */
3364     case '^':
3365       return geniCodeBitwise (geniCodeRValue (left, FALSE),
3366                               geniCodeRValue (right, FALSE),
3367                               tree->opval.op,
3368                               tree->ftype);
3369
3370     case '/':
3371       return geniCodeDivision (geniCodeRValue (left, FALSE),
3372                                geniCodeRValue (right, FALSE));
3373
3374     case '%':
3375       return geniCodeModulus (geniCodeRValue (left, FALSE),
3376                               geniCodeRValue (right, FALSE));
3377     case '*':
3378       if (right)
3379         return geniCodeMultiply (geniCodeRValue (left, FALSE),
3380                                  geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3381       else
3382         return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3383
3384     case '-':
3385       if (right)
3386         return geniCodeSubtract (geniCodeRValue (left, FALSE),
3387                                  geniCodeRValue (right, FALSE));
3388       else
3389         return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3390
3391     case '+':
3392       if (right)
3393         return geniCodeAdd (geniCodeRValue (left, FALSE),
3394                             geniCodeRValue (right, FALSE),lvl);
3395       else
3396         return geniCodeRValue (left, FALSE);    /* unary '+' has no meaning */
3397
3398     case LEFT_OP:
3399       return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3400                                 geniCodeRValue (right, FALSE));
3401
3402     case RIGHT_OP:
3403       return geniCodeRightShift (geniCodeRValue (left, FALSE),
3404                                  geniCodeRValue (right, FALSE));
3405     case CAST:
3406       return geniCodeCast (operandType (left),
3407                            geniCodeRValue (right, FALSE), FALSE);
3408
3409     case '~':
3410     case '!':
3411     case RRC:
3412     case RLC:
3413       return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3414
3415     case GETHBIT:
3416       {
3417         operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3418         setOperandType (op, UCHARTYPE);
3419         return op;
3420       }
3421     case '>':
3422     case '<':
3423     case LE_OP:
3424     case GE_OP:
3425     case EQ_OP:
3426     case NE_OP:
3427     case AND_OP:
3428     case OR_OP:
3429       return geniCodeLogic (geniCodeRValue (left, FALSE),
3430                             geniCodeRValue (right, FALSE),
3431                             tree->opval.op);
3432     case '?':
3433       return geniCodeConditional (tree,lvl);
3434
3435     case SIZEOF:
3436       return operandFromLit (getSize (tree->right->ftype));
3437
3438     case '=':
3439       {
3440         sym_link *rtype = operandType (right);
3441         sym_link *ltype = operandType (left);
3442         if (IS_PTR (rtype) && IS_ITEMP (right)
3443             && right->isaddr && compareType (rtype->next, ltype) == 1)
3444           right = geniCodeRValue (right, TRUE);
3445         else
3446           right = geniCodeRValue (right, FALSE);
3447
3448         geniCodeAssign (left, right, 0);
3449         return right;
3450       }
3451     case MUL_ASSIGN:
3452       return
3453         geniCodeAssign (left,
3454                 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3455                                                   FALSE),
3456                                   geniCodeRValue (right, FALSE),FALSE), 0);
3457
3458     case DIV_ASSIGN:
3459       return
3460         geniCodeAssign (left,
3461                 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3462                                                   FALSE),
3463                                   geniCodeRValue (right, FALSE)), 0);
3464     case MOD_ASSIGN:
3465       return
3466         geniCodeAssign (left,
3467                  geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3468                                                   FALSE),
3469                                   geniCodeRValue (right, FALSE)), 0);
3470     case ADD_ASSIGN:
3471       {
3472         sym_link *rtype = operandType (right);
3473         sym_link *ltype = operandType (left);
3474         if (IS_PTR (rtype) && IS_ITEMP (right)
3475             && right->isaddr && compareType (rtype->next, ltype) == 1)
3476           right = geniCodeRValue (right, TRUE);
3477         else
3478           right = geniCodeRValue (right, FALSE);
3479
3480
3481         return geniCodeAssign (left,
3482                      geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3483                                                   FALSE),
3484                                   right,lvl), 0);
3485       }
3486     case SUB_ASSIGN:
3487       {
3488         sym_link *rtype = operandType (right);
3489         sym_link *ltype = operandType (left);
3490         if (IS_PTR (rtype) && IS_ITEMP (right)
3491             && right->isaddr && compareType (rtype->next, ltype) == 1)
3492           {
3493             right = geniCodeRValue (right, TRUE);
3494           }
3495         else
3496           {
3497             right = geniCodeRValue (right, FALSE);
3498           }
3499         return
3500           geniCodeAssign (left,
3501                 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3502                                                   FALSE),
3503                                   right), 0);
3504       }
3505     case LEFT_ASSIGN:
3506       return
3507         geniCodeAssign (left,
3508                 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3509                                                    ,FALSE),
3510                                    geniCodeRValue (right, FALSE)), 0);
3511     case RIGHT_ASSIGN:
3512       return
3513         geniCodeAssign (left,
3514                geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3515                                                    ,FALSE),
3516                                    geniCodeRValue (right, FALSE)), 0);
3517     case AND_ASSIGN:
3518       return
3519         geniCodeAssign (left,
3520                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3521                                                   FALSE),
3522                                   geniCodeRValue (right, FALSE),
3523                                   BITWISEAND,
3524                                   operandType (left)), 0);
3525     case XOR_ASSIGN:
3526       return
3527         geniCodeAssign (left,
3528                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3529                                                   FALSE),
3530                                   geniCodeRValue (right, FALSE),
3531                                   '^',
3532                                   operandType (left)), 0);
3533     case OR_ASSIGN:
3534       return
3535         geniCodeAssign (left,
3536                   geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3537                                                    ,FALSE),
3538                                    geniCodeRValue (right, FALSE),
3539                                    '|',
3540                                    operandType (left)), 0);
3541     case ',':
3542       return geniCodeRValue (right, FALSE);
3543
3544     case CALL:
3545       return geniCodeCall (ast2iCode (tree->left,lvl+1),
3546                            tree->right,lvl);
3547     case LABEL:
3548       geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3549       return ast2iCode (tree->right,lvl+1);
3550
3551     case GOTO:
3552       geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3553       return ast2iCode (tree->right,lvl+1);
3554
3555     case FUNCTION:
3556       geniCodeFunctionBody (tree,lvl);
3557       return NULL;
3558
3559     case RETURN:
3560       geniCodeReturn (right);
3561       return NULL;
3562
3563     case IFX:
3564       geniCodeIfx (tree,lvl);
3565       return NULL;
3566
3567     case SWITCH:
3568       geniCodeSwitch (tree,lvl);
3569       return NULL;
3570
3571     case INLINEASM:
3572       geniCodeInline (tree);
3573       return NULL;
3574         
3575     case ARRAYINIT:
3576         geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3577         return NULL;
3578     }
3579
3580   return NULL;
3581 }
3582
3583 /*-----------------------------------------------------------------*/
3584 /* reverseICChain - gets from the list and creates a linkedlist    */
3585 /*-----------------------------------------------------------------*/
3586 iCode *
3587 reverseiCChain ()
3588 {
3589   iCode *loop = NULL;
3590   iCode *prev = NULL;
3591
3592   while ((loop = getSet (&iCodeChain)))
3593     {
3594       loop->next = prev;
3595       if (prev)
3596         prev->prev = loop;
3597       prev = loop;
3598     }
3599
3600   return prev;
3601 }
3602
3603
3604 /*-----------------------------------------------------------------*/
3605 /* iCodeFromAst - given an ast will convert it to iCode            */
3606 /*-----------------------------------------------------------------*/
3607 iCode *
3608 iCodeFromAst (ast * tree)
3609 {
3610   returnLabel = newiTempLabel ("_return");
3611   entryLabel = newiTempLabel ("_entry");
3612   ast2iCode (tree,0);
3613   return reverseiCChain ();
3614 }