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