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