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