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