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