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