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