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