Fixed pointer post increment problem
[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 nos%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,OP_SYMBOL(op)->noSpilLoc
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->usesDefs = op->usesDefs;
1093   nop->isParm = op->isParm;
1094   return nop;
1095 }
1096
1097 /*-----------------------------------------------------------------*/
1098 /* operand from operand - creates an operand holder for the type   */
1099 /*-----------------------------------------------------------------*/
1100 operand *
1101 operandFromOperand (operand * op)
1102 {
1103   operand *nop;
1104
1105   if (!op)
1106     return NULL;
1107   nop = newOperand ();
1108   nop->type = op->type;
1109   nop->isaddr = op->isaddr;
1110   nop->key = op->key;
1111   nop->isvolatile = op->isvolatile;
1112   nop->isGlobal = op->isGlobal;
1113   nop->isLiteral = op->isLiteral;
1114   nop->usesDefs = op->usesDefs;
1115   nop->isParm = op->isParm;
1116
1117   switch (nop->type)
1118     {
1119     case SYMBOL:
1120       nop->operand.symOperand = op->operand.symOperand;
1121       break;
1122     case VALUE:
1123       nop->operand.valOperand = op->operand.valOperand;
1124       break;
1125     case TYPE:
1126       nop->operand.typeOperand = op->operand.typeOperand;
1127       break;
1128     }
1129
1130   return nop;
1131 }
1132
1133 /*-----------------------------------------------------------------*/
1134 /* opFromOpWithDU - makes a copy of the operand and DU chains      */
1135 /*-----------------------------------------------------------------*/
1136 operand *
1137 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1138 {
1139   operand *nop = operandFromOperand (op);
1140
1141   if (nop->type == SYMBOL)
1142     {
1143       OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1144       OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1145     }
1146
1147   return nop;
1148 }
1149
1150 /*-----------------------------------------------------------------*/
1151 /* operandFromSymbol - creates an operand from a symbol            */
1152 /*-----------------------------------------------------------------*/
1153 operand *
1154 operandFromSymbol (symbol * sym)
1155 {
1156   operand *op;
1157   iCode *ic;
1158   int ok = 1;
1159   /* if the symbol's type is a literal */
1160   /* then it is an enumerator type     */
1161   if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1162     return operandFromValue (valFromType (sym->etype));
1163
1164   if (!sym->key)
1165     sym->key = ++operandKey;
1166
1167   /* if this an implicit variable, means struct/union */
1168   /* member so just return it                         */
1169   if (sym->implicit || IS_FUNC (sym->type))
1170     {
1171       op = newOperand ();
1172       op->type = SYMBOL;
1173       op->operand.symOperand = sym;
1174       op->key = sym->key;
1175       op->isvolatile = isOperandVolatile (op, TRUE);
1176       op->isGlobal = isOperandGlobal (op);
1177       return op;
1178     }
1179
1180   /* under the following conditions create a
1181      register equivalent for a local symbol */
1182   if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1183       (IN_FARSPACE (SPEC_OCLS (sym->etype)) && (!TARGET_IS_DS390)) &&
1184       options.stackAuto == 0)
1185     ok = 0;
1186
1187   if (!IS_AGGREGATE (sym->type) &&      /* not an aggregate */
1188       !IS_FUNC (sym->type) &&   /* not a function   */
1189       !sym->_isparm &&          /* not a parameter  */
1190       sym->level &&             /* is a local variable */
1191       !sym->addrtaken &&        /* whose address has not been taken */
1192       !sym->reqv &&             /* does not already have a register euivalence */
1193       !IS_VOLATILE (sym->etype) &&      /* not declared as volatile */
1194       !IS_STATIC (sym->etype) &&        /* and not declared static  */
1195       !sym->islbl &&            /* not a label */
1196       ok &&                     /* farspace check */
1197       !IS_BITVAR (sym->etype)   /* not a bit variable */
1198     )
1199     {
1200
1201       /* we will use it after all optimizations
1202          and before liveRange calculation */
1203       sym->reqv = newiTempOperand (sym->type, 0);
1204       sym->reqv->key = sym->key;
1205       OP_SYMBOL (sym->reqv)->key = sym->key;
1206       OP_SYMBOL (sym->reqv)->isreqv = 1;
1207       OP_SYMBOL (sym->reqv)->islocal = 1;
1208       SPIL_LOC (sym->reqv) = sym;
1209     }
1210
1211   if (!IS_AGGREGATE (sym->type))
1212     {
1213       op = newOperand ();
1214       op->type = SYMBOL;
1215       op->operand.symOperand = sym;
1216       op->isaddr = 1;
1217       op->key = sym->key;
1218       op->isvolatile = isOperandVolatile (op, TRUE);
1219       op->isGlobal = isOperandGlobal (op);
1220       op->isPtr = IS_PTR (operandType (op));
1221       op->isParm = sym->_isparm;
1222       return op;
1223     }
1224
1225   /* create :-                     */
1226   /*    itemp = &[_symbol]         */
1227
1228   ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1229   IC_LEFT (ic)->type = SYMBOL;
1230   IC_LEFT (ic)->operand.symOperand = sym;
1231   IC_LEFT (ic)->key = sym->key;
1232   (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1233   (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1234   IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1235
1236   /* create result */
1237   IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1238   if (IS_ARRAY (sym->type))
1239     {
1240       IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1241       IC_RESULT (ic)->isaddr = 0;
1242     }
1243   else
1244     IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1245
1246   IC_RESULT (ic)->operand.symOperand->args = sym->args;
1247
1248   ADDTOCHAIN (ic);
1249
1250   return IC_RESULT (ic);
1251 }
1252
1253 /*-----------------------------------------------------------------*/
1254 /* operandFromValue - creates an operand from value                */
1255 /*-----------------------------------------------------------------*/
1256 operand *
1257 operandFromValue (value * val)
1258 {
1259   operand *op;
1260
1261   /* if this is a symbol then do the symbol thing */
1262   if (val->sym)
1263     return operandFromSymbol (val->sym);
1264
1265   /* this is not a symbol */
1266   op = newOperand ();
1267   op->type = VALUE;
1268   op->operand.valOperand = val;
1269   op->isLiteral = isOperandLiteral (op);
1270   return op;
1271 }
1272
1273 /*-----------------------------------------------------------------*/
1274 /* operandFromLink - operand from typeChain                        */
1275 /*-----------------------------------------------------------------*/
1276 operand *
1277 operandFromLink (sym_link * type)
1278 {
1279   operand *op;
1280
1281   /* operand from sym_link */
1282   if (!type)
1283     return NULL;
1284
1285   op = newOperand ();
1286   op->type = TYPE;
1287   op->operand.typeOperand = copyLinkChain (type);
1288   return op;
1289 }
1290
1291 /*-----------------------------------------------------------------*/
1292 /* operandFromLit - makes an operand from a literal value          */
1293 /*-----------------------------------------------------------------*/
1294 operand *
1295 operandFromLit (double i)
1296 {
1297   return operandFromValue (valueFromLit (i));
1298 }
1299
1300 /*-----------------------------------------------------------------*/
1301 /* operandFromAst - creates an operand from an ast                 */
1302 /*-----------------------------------------------------------------*/
1303 operand *
1304 operandFromAst (ast * tree,int lvl)
1305 {
1306
1307   if (!tree)
1308     return NULL;
1309
1310   /* depending on type do */
1311   switch (tree->type)
1312     {
1313     case EX_OP:
1314       return ast2iCode (tree,lvl+1);
1315       break;
1316
1317     case EX_VALUE:
1318       return operandFromValue (tree->opval.val);
1319       break;
1320
1321     case EX_LINK:
1322       return operandFromLink (tree->opval.lnk);
1323     }
1324
1325   assert (0);
1326   /*  Just to keep the comiler happy */
1327   return (operand *) 0;
1328 }
1329
1330 /*-----------------------------------------------------------------*/
1331 /* setOperandType - sets the operand's type to the given type      */
1332 /*-----------------------------------------------------------------*/
1333 void 
1334 setOperandType (operand * op, sym_link * type)
1335 {
1336   /* depending on the type of operand */
1337   switch (op->type)
1338     {
1339
1340     case VALUE:
1341       op->operand.valOperand->etype =
1342         getSpec (op->operand.valOperand->type =
1343                  copyLinkChain (type));
1344       return;
1345
1346     case SYMBOL:
1347       if (op->operand.symOperand->isitmp)
1348         op->operand.symOperand->etype =
1349           getSpec (op->operand.symOperand->type =
1350                    copyLinkChain (type));
1351       else
1352         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1353                 "attempt to modify type of source");
1354       return;
1355
1356     case TYPE:
1357       op->operand.typeOperand = copyLinkChain (type);
1358       return;
1359     }
1360
1361 }
1362 /*-----------------------------------------------------------------*/
1363 /* Get size in byte of ptr need to access an array                 */
1364 /*-----------------------------------------------------------------*/
1365 int
1366 getArraySizePtr (operand * op)
1367 {
1368   sym_link *ltype = operandType(op);
1369
1370   if(IS_PTR(ltype))
1371     {
1372       int size = getSize(ltype);
1373       return(IS_GENPTR(ltype)?(size-1):size);
1374     }
1375
1376   if(IS_ARRAY(ltype))
1377     {
1378       sym_link *letype = getSpec(ltype);
1379       switch (PTR_TYPE (SPEC_OCLS (letype)))
1380         {
1381         case IPOINTER:
1382         case PPOINTER:
1383         case POINTER:
1384           return (PTRSIZE);
1385         case EEPPOINTER:
1386         case FPOINTER:
1387         case CPOINTER:
1388         case FUNCTION:
1389           return (FPTRSIZE);
1390         case GPOINTER:
1391           return (GPTRSIZE-1);
1392
1393         default:
1394           return (FPTRSIZE);
1395         }
1396     }
1397   return (FPTRSIZE);
1398 }
1399
1400 /*-----------------------------------------------------------------*/
1401 /* perform "usual unary conversions"                               */
1402 /*-----------------------------------------------------------------*/
1403 operand *
1404 usualUnaryConversions (operand * op)
1405 {
1406   if (IS_INTEGRAL (operandType (op)))
1407     {
1408       if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1409         {
1410           /* Widen to int. */
1411           return geniCodeCast (INTTYPE, op, TRUE);
1412         }
1413     }
1414   return op;
1415 }
1416
1417 /*-----------------------------------------------------------------*/
1418 /* perform "usual binary conversions"                              */
1419 /*-----------------------------------------------------------------*/
1420 sym_link *
1421 usualBinaryConversions (operand ** op1, operand ** op2)
1422 {
1423   sym_link *ctype;
1424   sym_link *rtype = operandType (*op2);
1425   sym_link *ltype = operandType (*op1);
1426   
1427   ctype = computeType (ltype, rtype);
1428   *op1 = geniCodeCast (ctype, *op1, TRUE);
1429   *op2 = geniCodeCast (ctype, *op2, TRUE);
1430   
1431   return ctype;
1432 }
1433
1434 /*-----------------------------------------------------------------*/
1435 /* geniCodeValueAtAddress - generate intermeditate code for value  */
1436 /*                          at address                             */
1437 /*-----------------------------------------------------------------*/
1438 operand *
1439 geniCodeRValue (operand * op, bool force)
1440 {
1441   iCode *ic;
1442   sym_link *type = operandType (op);
1443   sym_link *etype = getSpec (type);
1444
1445   /* if this is an array & already */
1446   /* an address then return this   */
1447   if (IS_AGGREGATE (type) ||
1448       (IS_PTR (type) && !force && !op->isaddr))
1449     return operandFromOperand (op);
1450
1451   /* if this is not an address then must be */
1452   /* rvalue already so return this one      */
1453   if (!op->isaddr)
1454     return op;
1455
1456   /* if this is not a temp symbol then */
1457   if (!IS_ITEMP (op) &&
1458       !force &&
1459       !IN_FARSPACE (SPEC_OCLS (etype)))
1460     {
1461       op = operandFromOperand (op);
1462       op->isaddr = 0;
1463       return op;
1464     }
1465
1466   if (IS_SPEC (type) &&
1467       IS_TRUE_SYMOP (op) &&
1468       (!IN_FARSPACE (SPEC_OCLS (etype)) || TARGET_IS_DS390))
1469     {
1470       op = operandFromOperand (op);
1471       op->isaddr = 0;
1472       return op;
1473     }
1474
1475   ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1476   if (IS_PTR (type) && op->isaddr && force)
1477     type = type->next;
1478
1479   type = copyLinkChain (type);
1480
1481   IC_RESULT (ic) = newiTempOperand (type, 1);
1482   IC_RESULT (ic)->isaddr = 0;
1483
1484 /*     ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1485
1486   /* if the right is a symbol */
1487   if (op->type == SYMBOL)
1488     IC_RESULT (ic)->operand.symOperand->args =
1489       op->operand.symOperand->args;
1490   ADDTOCHAIN (ic);
1491
1492   return IC_RESULT (ic);
1493 }
1494
1495 /*-----------------------------------------------------------------*/
1496 /* geniCodeCast - changes the value from one type to another       */
1497 /*-----------------------------------------------------------------*/
1498 operand *
1499 geniCodeCast (sym_link * type, operand * op, bool implicit)
1500 {
1501   iCode *ic;
1502   sym_link *optype;
1503   sym_link *opetype = getSpec (optype = operandType (op));
1504   sym_link *restype;
1505
1506   /* one of them has size zero then error */
1507   if (IS_VOID (optype))
1508     {
1509       werror (E_CAST_ZERO);
1510       return op;
1511     }
1512
1513   /* if the operand is already the desired type then do nothing */
1514   if (compareType (type, optype) == 1)
1515     return op;
1516
1517   /* if this is a literal then just change the type & return */
1518   if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1519     return operandFromValue (valCastLiteral (type,
1520                                              operandLitValue (op)));
1521
1522   /* if casting to some pointer type &&
1523      the destination is not a generic pointer
1524      then give a warning : (only for implicit casts) */
1525   if (IS_PTR (optype) && implicit &&
1526       (DCL_TYPE (optype) != DCL_TYPE (type)) &&
1527       !IS_GENPTR (type))
1528     {
1529       werror (E_INCOMPAT_CAST);
1530       fprintf (stderr, "from type '");
1531       printTypeChain (optype, stderr);
1532       fprintf (stderr, "' to type '");
1533       printTypeChain (type, stderr);
1534       fprintf (stderr, "'\n");
1535     }
1536
1537   /* if they are the same size create an assignment */
1538   if (getSize (type) == getSize (optype) &&
1539       !IS_BITFIELD (type) &&
1540       !IS_FLOAT (type) &&
1541       !IS_FLOAT (optype) &&
1542       ((IS_SPEC (type) && IS_SPEC (optype)) ||
1543        (!IS_SPEC (type) && !IS_SPEC (optype))))
1544     {
1545
1546       ic = newiCode ('=', NULL, op);
1547       IC_RESULT (ic) = newiTempOperand (type, 0);
1548       SPIL_LOC (IC_RESULT (ic)) =
1549         (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1550       IC_RESULT (ic)->isaddr = 0;
1551     }
1552   else
1553     {
1554       ic = newiCode (CAST, operandFromLink (type),
1555                      geniCodeRValue (op, FALSE));
1556
1557       IC_RESULT (ic) = newiTempOperand (type, 0);
1558     }
1559
1560   /* preserve the storage class & output class */
1561   /* of the original variable                  */
1562   restype = getSpec (operandType (IC_RESULT (ic)));
1563   SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1564   SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1565
1566   ADDTOCHAIN (ic);
1567   return IC_RESULT (ic);
1568 }
1569
1570 /*-----------------------------------------------------------------*/
1571 /* geniCodeLabel - will create a Label                             */
1572 /*-----------------------------------------------------------------*/
1573 void 
1574 geniCodeLabel (symbol * label)
1575 {
1576   iCode *ic;
1577
1578   ic = newiCodeLabelGoto (LABEL, label);
1579   ADDTOCHAIN (ic);
1580 }
1581
1582 /*-----------------------------------------------------------------*/
1583 /* geniCodeGoto  - will create a Goto                              */
1584 /*-----------------------------------------------------------------*/
1585 void 
1586 geniCodeGoto (symbol * label)
1587 {
1588   iCode *ic;
1589
1590   ic = newiCodeLabelGoto (GOTO, label);
1591   ADDTOCHAIN (ic);
1592 }
1593
1594 /*-----------------------------------------------------------------*/
1595 /* geniCodeMultiply - gen intermediate code for multiplication     */
1596 /*-----------------------------------------------------------------*/
1597 operand *
1598 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1599 {
1600   iCode *ic;
1601   int p2 = 0;
1602   sym_link *resType;
1603   LRTYPE;
1604
1605   /* if they are both literal then we know the result */
1606   if (IS_LITERAL (letype) && IS_LITERAL (retype))
1607     return operandFromValue (valMult (left->operand.valOperand,
1608                                       right->operand.valOperand));
1609
1610   if (IS_LITERAL(retype)) {
1611     p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1612   }
1613
1614   resType = usualBinaryConversions (&left, &right);
1615 #if 1
1616   rtype = operandType (right);
1617   retype = getSpec (rtype);
1618   ltype = operandType (left);
1619   letype = getSpec (ltype);
1620 #endif
1621   if (resultIsInt)
1622     {
1623       SPEC_NOUN(getSpec(resType))=V_INT;
1624     }
1625
1626   /* if the right is a literal & power of 2 */
1627   /* then make it a left shift              */
1628   /* code generated for 1 byte * 1 byte literal = 2 bytes result is more 
1629      efficient in most cases than 2 bytes result = 2 bytes << literal 
1630      if port has 1 byte muldiv */
1631   if (p2 && !IS_FLOAT (letype) &&
1632       !((resultIsInt) && (getSize (resType) != getSize (ltype)) && 
1633         (port->support.muldiv == 1)))
1634     {
1635       if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1636         {
1637           /* LEFT_OP need same size for left and result, */
1638           left = geniCodeCast (resType, left, TRUE);
1639           ltype = operandType (left);
1640         }
1641       ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1642     }
1643   else
1644     {
1645       ic = newiCode ('*', left, right);         /* normal multiplication */
1646       /* if the size left or right > 1 then support routine */
1647       if (getSize (ltype) > 1 || getSize (rtype) > 1)
1648         ic->supportRtn = 1;
1649
1650     }
1651   IC_RESULT (ic) = newiTempOperand (resType, 1);
1652
1653   ADDTOCHAIN (ic);
1654   return IC_RESULT (ic);
1655 }
1656
1657 /*-----------------------------------------------------------------*/
1658 /* geniCodeDivision - gen intermediate code for division           */
1659 /*-----------------------------------------------------------------*/
1660 operand *
1661 geniCodeDivision (operand * left, operand * right)
1662 {
1663   iCode *ic;
1664   int p2 = 0;
1665   sym_link *resType;
1666   sym_link *rtype = operandType (right);
1667   sym_link *retype = getSpec (rtype);
1668   sym_link *ltype = operandType (left);
1669   sym_link *letype = getSpec (ltype);
1670
1671   resType = usualBinaryConversions (&left, &right);
1672
1673   /* if the right is a literal & power of 2 */
1674   /* then make it a right shift             */
1675   if (IS_LITERAL (retype) &&
1676       !IS_FLOAT (letype) &&
1677       (p2 = powof2 ((unsigned long)
1678                     floatFromVal (right->operand.valOperand)))) {
1679     ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1680   }
1681   else
1682     {
1683       ic = newiCode ('/', left, right);         /* normal division */
1684       /* if the size left or right > 1 then support routine */
1685       if (getSize (ltype) > 1 || getSize (rtype) > 1)
1686         ic->supportRtn = 1;
1687     }
1688   IC_RESULT (ic) = newiTempOperand (resType, 0);
1689
1690   ADDTOCHAIN (ic);
1691   return IC_RESULT (ic);
1692 }
1693 /*-----------------------------------------------------------------*/
1694 /* geniCodeModulus  - gen intermediate code for modulus            */
1695 /*-----------------------------------------------------------------*/
1696 operand *
1697 geniCodeModulus (operand * left, operand * right)
1698 {
1699   iCode *ic;
1700   sym_link *resType;
1701   LRTYPE;
1702
1703   /* if they are both literal then we know the result */
1704   if (IS_LITERAL (letype) && IS_LITERAL (retype))
1705     return operandFromValue (valMod (left->operand.valOperand,
1706                                      right->operand.valOperand));
1707
1708   resType = usualBinaryConversions (&left, &right);
1709
1710   /* now they are the same size */
1711   ic = newiCode ('%', left, right);
1712
1713   /* if the size left or right > 1 then support routine */
1714   if (getSize (ltype) > 1 || getSize (rtype) > 1)
1715     ic->supportRtn = 1;
1716   IC_RESULT (ic) = newiTempOperand (resType, 0);
1717
1718   ADDTOCHAIN (ic);
1719   return IC_RESULT (ic);
1720 }
1721
1722 /*-----------------------------------------------------------------*/
1723 /* geniCodePtrPtrSubtract - subtracts pointer from pointer         */
1724 /*-----------------------------------------------------------------*/
1725 operand *
1726 geniCodePtrPtrSubtract (operand * left, operand * right)
1727 {
1728   iCode *ic;
1729   operand *result;
1730   LRTYPE;
1731
1732   /* if they are both literals then */
1733   if (IS_LITERAL (letype) && IS_LITERAL (retype))
1734     {
1735       result = operandFromValue (valMinus (left->operand.valOperand,
1736                                            right->operand.valOperand));
1737       goto subtractExit;
1738     }
1739
1740   ic = newiCode ('-', left, right);
1741
1742   IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1743   ADDTOCHAIN (ic);
1744
1745 subtractExit:
1746   return geniCodeDivision (result,
1747                            operandFromLit (getSize (ltype->next)));
1748 }
1749
1750 /*-----------------------------------------------------------------*/
1751 /* geniCodeSubtract - generates code for subtraction               */
1752 /*-----------------------------------------------------------------*/
1753 operand *
1754 geniCodeSubtract (operand * left, operand * right)
1755 {
1756   iCode *ic;
1757   int isarray = 0;
1758   sym_link *resType;
1759   LRTYPE;
1760
1761   /* if they both pointers then */
1762   if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
1763       (IS_PTR (rtype) || IS_ARRAY (rtype)))
1764     return geniCodePtrPtrSubtract (left, right);
1765
1766   /* if they are both literal then we know the result */
1767   if (IS_LITERAL (letype) && IS_LITERAL (retype)
1768       && left->isLiteral && right->isLiteral)
1769     return operandFromValue (valMinus (left->operand.valOperand,
1770                                        right->operand.valOperand));
1771
1772   /* if left is an array or pointer */
1773   if (IS_PTR (ltype) || IS_ARRAY (ltype))
1774     {
1775       isarray = left->isaddr;
1776       right = geniCodeMultiply (right,
1777                                 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
1778       resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
1779     }
1780   else
1781     {                           /* make them the same size */
1782       resType = usualBinaryConversions (&left, &right);
1783     }
1784
1785   ic = newiCode ('-', left, right);
1786
1787   IC_RESULT (ic) = newiTempOperand (resType, 1);
1788   IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1789
1790   /* if left or right is a float */
1791   if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1792     ic->supportRtn = 1;
1793
1794   ADDTOCHAIN (ic);
1795   return IC_RESULT (ic);
1796 }
1797
1798 /*-----------------------------------------------------------------*/
1799 /* geniCodeAdd - generates iCode for addition                      */
1800 /*-----------------------------------------------------------------*/
1801 operand *
1802 geniCodeAdd (operand * left, operand * right,int lvl)
1803 {
1804   iCode *ic;
1805   sym_link *resType;
1806   operand *size;
1807   int isarray = 0;
1808   LRTYPE;
1809
1810   /* if left is an array then array access */
1811   if (IS_ARRAY (ltype))
1812     return geniCodeArray (left, right,lvl);
1813
1814   /* if the right side is LITERAL zero */
1815   /* return the left side              */
1816   if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
1817     return left;
1818
1819   /* if left is literal zero return right */
1820   if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
1821     return right;
1822
1823   /* if left is an array or pointer then size */
1824   if (IS_PTR (ltype))
1825     {
1826       isarray = left->isaddr;
1827       // there is no need to multiply with 1
1828       if (getSize(ltype->next)!=1) {
1829         size  = operandFromLit (getSize (ltype->next));
1830         right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
1831       }
1832       resType = copyLinkChain (ltype);
1833     }
1834   else
1835     {                           /* make them the same size */
1836       resType = usualBinaryConversions (&left, &right);
1837     }
1838
1839   /* if they are both literals then we know */
1840   if (IS_LITERAL (letype) && IS_LITERAL (retype)
1841       && left->isLiteral && right->isLiteral)
1842     return operandFromValue (valPlus (valFromType (letype),
1843                                       valFromType (retype)));
1844
1845   ic = newiCode ('+', left, right);
1846
1847   IC_RESULT (ic) = newiTempOperand (resType, 1);
1848   IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1849
1850   /* if left or right is a float then support
1851      routine */
1852   if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1853     ic->supportRtn = 1;
1854
1855   ADDTOCHAIN (ic);
1856
1857   return IC_RESULT (ic);
1858
1859 }
1860
1861 /*-----------------------------------------------------------------*/
1862 /* aggrToPtr - changes an aggregate to pointer to an aggregate     */
1863 /*-----------------------------------------------------------------*/
1864 sym_link *
1865 aggrToPtr (sym_link * type, bool force)
1866 {
1867   sym_link *etype;
1868   sym_link *ptype;
1869
1870
1871   if (IS_PTR (type) && !force)
1872     return type;
1873
1874   etype = getSpec (type);
1875   ptype = newLink ();
1876
1877   ptype->next = type;
1878   /* if the output class is generic */
1879   if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
1880     DCL_PTR_CONST (ptype) = port->mem.code_ro;
1881
1882   /* if the variable was declared a constant */
1883   /* then the pointer points to a constant */
1884   if (IS_CONSTANT (etype))
1885     DCL_PTR_CONST (ptype) = 1;
1886
1887   /* the variable was volatile then pointer to volatile */
1888   if (IS_VOLATILE (etype))
1889     DCL_PTR_VOLATILE (ptype) = 1;
1890   return ptype;
1891 }
1892
1893 /*-----------------------------------------------------------------*/
1894 /* geniCodeArray2Ptr - array to pointer                            */
1895 /*-----------------------------------------------------------------*/
1896 operand *
1897 geniCodeArray2Ptr (operand * op)
1898 {
1899   sym_link *optype = operandType (op);
1900   sym_link *opetype = getSpec (optype);
1901
1902   /* set the pointer depending on the storage class */
1903   if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
1904     DCL_PTR_CONST (optype) = port->mem.code_ro;
1905
1906
1907   /* if the variable was declared a constant */
1908   /* then the pointer points to a constant */
1909   if (IS_CONSTANT (opetype))
1910     DCL_PTR_CONST (optype) = 1;
1911
1912   /* the variable was volatile then pointer to volatile */
1913   if (IS_VOLATILE (opetype))
1914     DCL_PTR_VOLATILE (optype) = 1;
1915   op->isaddr = 0;
1916   return op;
1917 }
1918
1919
1920 /*-----------------------------------------------------------------*/
1921 /* geniCodeArray - array access                                    */
1922 /*-----------------------------------------------------------------*/
1923 operand *
1924 geniCodeArray (operand * left, operand * right,int lvl)
1925 {
1926   iCode *ic;
1927   sym_link *ltype = operandType (left);
1928
1929   if (IS_PTR (ltype))
1930     {
1931       if (IS_PTR (ltype->next) && left->isaddr)
1932         {
1933           left = geniCodeRValue (left, FALSE);
1934         }
1935       return geniCodeDerefPtr (geniCodeAdd (left, right,lvl),lvl);
1936     }
1937
1938   right = geniCodeMultiply (right,
1939                             operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
1940
1941   /* we can check for limits here */
1942   if (isOperandLiteral (right) &&
1943       IS_ARRAY (ltype) &&
1944       DCL_ELEM (ltype) &&
1945       (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
1946     {
1947       werror (E_ARRAY_BOUND);
1948       right = operandFromLit (0);
1949     }
1950
1951   ic = newiCode ('+', left, right);
1952
1953   IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
1954                                       !IS_AGGREGATE (ltype->next) &&
1955                                       !IS_PTR (ltype->next))
1956                                      ? ltype : ltype->next), 0);
1957
1958   IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
1959   ADDTOCHAIN (ic);
1960   return IC_RESULT (ic);
1961 }
1962
1963 /*-----------------------------------------------------------------*/
1964 /* geniCodeStruct - generates intermediate code for structres      */
1965 /*-----------------------------------------------------------------*/
1966 operand *
1967 geniCodeStruct (operand * left, operand * right, bool islval)
1968 {
1969   iCode *ic;
1970   sym_link *type = operandType (left);
1971   sym_link *etype = getSpec (type);
1972   sym_link *retype;
1973   symbol *element = getStructElement (SPEC_STRUCT (etype),
1974                                       right->operand.symOperand);
1975
1976   /* add the offset */
1977   ic = newiCode ('+', left, operandFromLit (element->offset));
1978
1979   IC_RESULT (ic) = newiTempOperand (element->type, 0);
1980
1981   /* preserve the storage & output class of the struct */
1982   /* as well as the volatile attribute */
1983   retype = getSpec (operandType (IC_RESULT (ic)));
1984   SPEC_SCLS (retype) = SPEC_SCLS (etype);
1985   SPEC_OCLS (retype) = SPEC_OCLS (etype);
1986   SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
1987
1988   if (IS_PTR (element->type))
1989     setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
1990
1991   IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
1992
1993
1994   ADDTOCHAIN (ic);
1995   return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
1996 }
1997
1998 /*-----------------------------------------------------------------*/
1999 /* geniCodePostInc - generate int code for Post increment          */
2000 /*-----------------------------------------------------------------*/
2001 operand *
2002 geniCodePostInc (operand * op)
2003 {
2004   iCode *ic;
2005   operand *rOp;
2006   sym_link *optype = operandType (op);
2007   operand *result;
2008   operand *rv = (IS_ITEMP (op) ?
2009                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2010                  op);
2011   sym_link *rvtype = operandType (rv);
2012   int size = 0;
2013
2014   /* if this is not an address we have trouble */
2015   if (!op->isaddr)
2016     {
2017       werror (E_LVALUE_REQUIRED, "++");
2018       return op;
2019     }
2020
2021   rOp = newiTempOperand (rvtype, 0);
2022   OP_SYMBOL(rOp)->noSpilLoc = 1;
2023
2024   if (IS_ITEMP (rv))
2025     OP_SYMBOL(rv)->noSpilLoc = 1;
2026
2027   geniCodeAssign (rOp, rv, 0);
2028
2029   size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2030   if (IS_FLOAT (rvtype))
2031     ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2032   else
2033     ic = newiCode ('+', rv, operandFromLit (size));
2034
2035   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2036   ADDTOCHAIN (ic);
2037
2038   geniCodeAssign (op, result, 0);
2039
2040   return rOp;
2041
2042 }
2043
2044 /*-----------------------------------------------------------------*/
2045 /* geniCodePreInc - generate code for preIncrement                 */
2046 /*-----------------------------------------------------------------*/
2047 operand *
2048 geniCodePreInc (operand * op)
2049 {
2050   iCode *ic;
2051   sym_link *optype = operandType (op);
2052   operand *rop = (IS_ITEMP (op) ?
2053                   geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2054                   op);
2055   sym_link *roptype = operandType (rop);
2056   operand *result;
2057   int size = 0;
2058
2059   if (!op->isaddr)
2060     {
2061       werror (E_LVALUE_REQUIRED, "++");
2062       return op;
2063     }
2064
2065
2066   size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2067   if (IS_FLOAT (roptype))
2068     ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2069   else
2070     ic = newiCode ('+', rop, operandFromLit (size));
2071   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2072   ADDTOCHAIN (ic);
2073
2074
2075   return geniCodeAssign (op, result, 0);
2076 }
2077
2078 /*-----------------------------------------------------------------*/
2079 /* geniCodePostDec - generates code for Post decrement             */
2080 /*-----------------------------------------------------------------*/
2081 operand *
2082 geniCodePostDec (operand * op)
2083 {
2084   iCode *ic;
2085   operand *rOp;
2086   sym_link *optype = operandType (op);
2087   operand *result;
2088   operand *rv = (IS_ITEMP (op) ?
2089                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2090                  op);
2091   sym_link *rvtype = operandType (rv);
2092   int size = 0;
2093
2094   /* if this is not an address we have trouble */
2095   if (!op->isaddr)
2096     {
2097       werror (E_LVALUE_REQUIRED, "++");
2098       return op;
2099     }
2100
2101   rOp = newiTempOperand (rvtype, 0);
2102   OP_SYMBOL(rOp)->noSpilLoc = 1;
2103
2104   if (IS_ITEMP (rv))
2105     OP_SYMBOL(rv)->noSpilLoc = 1;
2106
2107   geniCodeAssign (rOp, rv, 0);
2108
2109   size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2110   if (IS_FLOAT (rvtype))
2111     ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2112   else
2113     ic = newiCode ('-', rv, operandFromLit (size));
2114
2115   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2116   ADDTOCHAIN (ic);
2117
2118   geniCodeAssign (op, result, 0);
2119
2120   return rOp;
2121
2122 }
2123
2124 /*-----------------------------------------------------------------*/
2125 /* geniCodePreDec - generate code for pre  decrement               */
2126 /*-----------------------------------------------------------------*/
2127 operand *
2128 geniCodePreDec (operand * op)
2129 {
2130   iCode *ic;
2131   sym_link *optype = operandType (op);
2132   operand *rop = (IS_ITEMP (op) ?
2133                   geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2134                   op);
2135   sym_link *roptype = operandType (rop);
2136   operand *result;
2137   int size = 0;
2138
2139   if (!op->isaddr)
2140     {
2141       werror (E_LVALUE_REQUIRED, "++");
2142       return op;
2143     }
2144
2145
2146   size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2147   if (IS_FLOAT (roptype))
2148     ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2149   else
2150     ic = newiCode ('-', rop, operandFromLit (size));
2151   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2152   ADDTOCHAIN (ic);
2153
2154
2155   return geniCodeAssign (op, result, 0);
2156 }
2157
2158
2159 /*-----------------------------------------------------------------*/
2160 /* geniCodeBitwise - gen int code for bitWise  operators           */
2161 /*-----------------------------------------------------------------*/
2162 operand *
2163 geniCodeBitwise (operand * left, operand * right,
2164                  int oper, sym_link * resType)
2165 {
2166   iCode *ic;
2167
2168   left = geniCodeCast (resType, left, TRUE);
2169   right = geniCodeCast (resType, right, TRUE);
2170
2171   ic = newiCode (oper, left, right);
2172   IC_RESULT (ic) = newiTempOperand (resType, 0);
2173
2174   ADDTOCHAIN (ic);
2175   return IC_RESULT (ic);
2176 }
2177
2178 /*-----------------------------------------------------------------*/
2179 /* geniCodeAddressOf - gens icode for '&' address of operator      */
2180 /*-----------------------------------------------------------------*/
2181 operand *
2182 geniCodeAddressOf (operand * op)
2183 {
2184   iCode *ic;
2185   sym_link *p;
2186   sym_link *optype = operandType (op);
2187   sym_link *opetype = getSpec (optype);
2188
2189   /* lvalue check already done in decorateType */
2190   /* this must be a lvalue */
2191 /*     if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2192 /*  werror (E_LVALUE_REQUIRED,"&"); */
2193 /*  return op; */
2194 /*     } */
2195
2196   p = newLink ();
2197   p->class = DECLARATOR;
2198
2199   /* set the pointer depending on the storage class */
2200   if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2201     DCL_PTR_CONST (p) = port->mem.code_ro;
2202
2203   /* make sure we preserve the const & volatile */
2204   if (IS_CONSTANT (opetype))
2205     DCL_PTR_CONST (p) = 1;
2206
2207   if (IS_VOLATILE (opetype))
2208     DCL_PTR_VOLATILE (p) = 1;
2209
2210   p->next = copyLinkChain (optype);
2211
2212   /* if already a temp */
2213   if (IS_ITEMP (op))
2214     {
2215       setOperandType (op, p);
2216       op->isaddr = 0;
2217       return op;
2218     }
2219
2220   /* other wise make this of the type coming in */
2221   ic = newiCode (ADDRESS_OF, op, NULL);
2222   IC_RESULT (ic) = newiTempOperand (p, 1);
2223   IC_RESULT (ic)->isaddr = 0;
2224   ADDTOCHAIN (ic);
2225   return IC_RESULT (ic);
2226 }
2227 /*-----------------------------------------------------------------*/
2228 /* setOClass - sets the output class depending on the pointer type */
2229 /*-----------------------------------------------------------------*/
2230 void 
2231 setOClass (sym_link * ptr, sym_link * spec)
2232 {
2233   switch (DCL_TYPE (ptr))
2234     {
2235     case POINTER:
2236       SPEC_OCLS (spec) = data;
2237       break;
2238
2239     case GPOINTER:
2240       SPEC_OCLS (spec) = generic;
2241       break;
2242
2243     case FPOINTER:
2244       SPEC_OCLS (spec) = xdata;
2245       break;
2246
2247     case CPOINTER:
2248       SPEC_OCLS (spec) = code;
2249       break;
2250
2251     case IPOINTER:
2252       SPEC_OCLS (spec) = idata;
2253       break;
2254
2255     case PPOINTER:
2256       SPEC_OCLS (spec) = xstack;
2257       break;
2258
2259     case EEPPOINTER:
2260       SPEC_OCLS (spec) = eeprom;
2261       break;
2262
2263     default:
2264       break;
2265
2266     }
2267 }
2268
2269 /*-----------------------------------------------------------------*/
2270 /* geniCodeDerefPtr - dereference pointer with '*'                 */
2271 /*-----------------------------------------------------------------*/
2272 operand *
2273 geniCodeDerefPtr (operand * op,int lvl)
2274 {
2275   sym_link *rtype, *retype;
2276   sym_link *optype = operandType (op);
2277
2278   /* if this is a pointer then generate the rvalue */
2279   if (IS_PTR (optype))
2280     {
2281       if (IS_TRUE_SYMOP (op))
2282         {
2283           op->isaddr = 1;
2284           op = geniCodeRValue (op, TRUE);
2285         }
2286       else
2287         op = geniCodeRValue (op, TRUE);
2288     }
2289
2290   /* now get rid of the pointer part */
2291   if (isLvaluereq(lvl) && IS_ITEMP (op))
2292     {
2293       retype = getSpec (rtype = copyLinkChain (optype));
2294     }
2295   else
2296     {
2297       retype = getSpec (rtype = copyLinkChain (optype->next));
2298     }
2299
2300   /* if this is a pointer then outputclass needs 2b updated */
2301   if (IS_PTR (optype))
2302     setOClass (optype, retype);
2303
2304   op->isGptr = IS_GENPTR (optype);
2305
2306   /* if the pointer was declared as a constant */
2307   /* then we cannot allow assignment to the derefed */
2308   if (IS_PTR_CONST (optype))
2309     SPEC_CONST (retype) = 1;
2310
2311   op->isaddr = (IS_PTR (rtype) ||
2312                 IS_STRUCT (rtype) ||
2313                 IS_INT (rtype) ||
2314                 IS_CHAR (rtype) ||
2315                 IS_FLOAT (rtype));
2316
2317   if (!isLvaluereq(lvl))
2318     op = geniCodeRValue (op, TRUE);
2319
2320   setOperandType (op, rtype);
2321
2322   return op;
2323 }
2324
2325 /*-----------------------------------------------------------------*/
2326 /* geniCodeUnaryMinus - does a unary minus of the operand          */
2327 /*-----------------------------------------------------------------*/
2328 operand *
2329 geniCodeUnaryMinus (operand * op)
2330 {
2331   iCode *ic;
2332   sym_link *optype = operandType (op);
2333
2334   if (IS_LITERAL (optype))
2335     return operandFromLit (-floatFromVal (op->operand.valOperand));
2336
2337   ic = newiCode (UNARYMINUS, op, NULL);
2338   IC_RESULT (ic) = newiTempOperand (optype, 0);
2339   ADDTOCHAIN (ic);
2340   return IC_RESULT (ic);
2341 }
2342
2343 /*-----------------------------------------------------------------*/
2344 /* geniCodeLeftShift - gen i code for left shift                   */
2345 /*-----------------------------------------------------------------*/
2346 operand *
2347 geniCodeLeftShift (operand * left, operand * right)
2348 {
2349   iCode *ic;
2350
2351   ic = newiCode (LEFT_OP, left, right);
2352   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2353   ADDTOCHAIN (ic);
2354   return IC_RESULT (ic);
2355 }
2356
2357 /*-----------------------------------------------------------------*/
2358 /* geniCodeRightShift - gen i code for right shift                 */
2359 /*-----------------------------------------------------------------*/
2360 operand *
2361 geniCodeRightShift (operand * left, operand * right)
2362 {
2363   iCode *ic;
2364
2365   ic = newiCode (RIGHT_OP, left, right);
2366   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2367   ADDTOCHAIN (ic);
2368   return IC_RESULT (ic);
2369 }
2370
2371 #if defined(__BORLANDC__) || defined(_MSC_VER)
2372 #define LONG_LONG __int64
2373 #else
2374 #define LONG_LONG long long
2375 #endif
2376
2377 /*-----------------------------------------------------------------*/
2378 /* geniCodeLogic- logic code                                       */
2379 /*-----------------------------------------------------------------*/
2380 operand *
2381 geniCodeLogic (operand * left, operand * right, int op)
2382 {
2383   iCode *ic;
2384   sym_link *ctype;
2385   sym_link *rtype = operandType (right);
2386   sym_link *ltype = operandType (left);
2387
2388   /* left is integral type and right is literal then
2389      check if the literal value is within bounds */
2390   if (IS_INTEGRAL (ltype) && IS_LITERAL (rtype))
2391     {
2392       int nbits = bitsForType (ltype);
2393       long v = (long) operandLitValue (right);
2394
2395       if (v >= ((LONG_LONG) 1 << nbits) && v > 0)
2396         werror (W_CONST_RANGE, " compare operation ");
2397     }
2398
2399   ctype = usualBinaryConversions (&left, &right);
2400
2401   ic = newiCode (op, left, right);
2402   IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2403
2404   /* if comparing float
2405      and not a '==' || '!=' || '&&' || '||' (these
2406      will be inlined */
2407   if (IS_FLOAT(ctype) &&
2408       op != EQ_OP &&
2409       op != NE_OP &&
2410       op != AND_OP &&
2411       op != OR_OP)
2412     ic->supportRtn = 1;
2413
2414   ADDTOCHAIN (ic);
2415   return IC_RESULT (ic);
2416 }
2417
2418 /*-----------------------------------------------------------------*/
2419 /* geniCodeUnary - for a a generic unary operation                 */
2420 /*-----------------------------------------------------------------*/
2421 operand *
2422 geniCodeUnary (operand * op, int oper)
2423 {
2424   iCode *ic = newiCode (oper, op, NULL);
2425
2426   IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2427   ADDTOCHAIN (ic);
2428   return IC_RESULT (ic);
2429 }
2430
2431 /*-----------------------------------------------------------------*/
2432 /* geniCodeConditional - geniCode for '?' ':' operation            */
2433 /*-----------------------------------------------------------------*/
2434 operand *
2435 geniCodeConditional (ast * tree,int lvl)
2436 {
2437   iCode *ic;
2438   symbol *falseLabel = newiTempLabel (NULL);
2439   symbol *exitLabel = newiTempLabel (NULL);
2440   operand *cond = ast2iCode (tree->left,lvl+1);
2441   operand *true, *false, *result;
2442
2443   ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2444                           NULL, falseLabel);
2445   ADDTOCHAIN (ic);
2446
2447   true = ast2iCode (tree->right->left,lvl+1);
2448
2449   /* move the value to a new Operand */
2450   result = newiTempOperand (operandType (true), 0);
2451   geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2452
2453   /* generate an unconditional goto */
2454   geniCodeGoto (exitLabel);
2455
2456   /* now for the right side */
2457   geniCodeLabel (falseLabel);
2458
2459   false = ast2iCode (tree->right->right,lvl+1);
2460   geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2461
2462   /* create the exit label */
2463   geniCodeLabel (exitLabel);
2464
2465   return result;
2466 }
2467
2468 /*-----------------------------------------------------------------*/
2469 /* geniCodeAssign - generate code for assignment                   */
2470 /*-----------------------------------------------------------------*/
2471 operand *
2472 geniCodeAssign (operand * left, operand * right, int nosupdate)
2473 {
2474   iCode *ic;
2475   sym_link *ltype = operandType (left);
2476   sym_link *rtype = operandType (right);
2477
2478   if (!left->isaddr && !IS_ITEMP (left))
2479     {
2480       werror (E_LVALUE_REQUIRED, "assignment");
2481       return left;
2482     }
2483
2484   /* left is integral type and right is literal then
2485      check if the literal value is within bounds */
2486   if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2487     {
2488       int nbits = bitsForType (ltype);
2489       long v = (long) operandLitValue (right);
2490
2491       if (v >= ((LONG_LONG) 1 << nbits) && v > 0)
2492         werror (W_CONST_RANGE, " = operation");
2493     }
2494
2495   /* if the left & right type don't exactly match */
2496   /* if pointer set then make sure the check is
2497      done with the type & not the pointer */
2498   /* then cast rights type to left */
2499
2500   /* first check the type for pointer assignement */
2501   if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2502       compareType (ltype, rtype) < 0)
2503     {
2504       if (compareType (ltype->next, rtype) < 0)
2505         right = geniCodeCast (ltype->next, right, TRUE);
2506     }
2507   else if (compareType (ltype, rtype) < 0)
2508     right = geniCodeCast (ltype, right, TRUE);
2509
2510   /* if left is a true symbol & ! volatile
2511      create an assignment to temporary for
2512      the right & then assign this temporary
2513      to the symbol this is SSA . isn't it simple
2514      and folks have published mountains of paper on it */
2515   if (IS_TRUE_SYMOP (left) &&
2516       !isOperandVolatile (left, FALSE) &&
2517       isOperandGlobal (left))
2518     {
2519       symbol *sym = NULL;
2520
2521       if (IS_TRUE_SYMOP (right))
2522         sym = OP_SYMBOL (right);
2523       ic = newiCode ('=', NULL, right);
2524       IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2525       SPIL_LOC (right) = sym;
2526       ADDTOCHAIN (ic);
2527     }
2528
2529   ic = newiCode ('=', NULL, right);
2530   IC_RESULT (ic) = left;
2531   ADDTOCHAIN (ic);
2532
2533   /* if left isgptr flag is set then support
2534      routine will be required */
2535   if (left->isGptr)
2536     ic->supportRtn = 1;
2537
2538   ic->nosupdate = nosupdate;
2539   return left;
2540 }
2541
2542 /*-----------------------------------------------------------------*/
2543 /* geniCodeSEParms - generate code for side effecting fcalls       */
2544 /*-----------------------------------------------------------------*/
2545 static void 
2546 geniCodeSEParms (ast * parms,int lvl)
2547 {
2548   if (!parms)
2549     return;
2550
2551   if (parms->type == EX_OP && parms->opval.op == PARAM)
2552     {
2553       geniCodeSEParms (parms->left,lvl);
2554       geniCodeSEParms (parms->right,lvl);
2555       return;
2556     }
2557
2558   /* hack don't like this but too lazy to think of
2559      something better */
2560   if (IS_ADDRESS_OF_OP (parms))
2561     parms->left->lvalue = 1;
2562
2563   if (IS_CAST_OP (parms) &&
2564       IS_PTR (parms->ftype) &&
2565       IS_ADDRESS_OF_OP (parms->right))
2566     parms->right->left->lvalue = 1;
2567
2568   parms->opval.oprnd =
2569     geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2570
2571   parms->type = EX_OPERAND;
2572 }
2573
2574 /*-----------------------------------------------------------------*/
2575 /* geniCodeParms - generates parameters                            */
2576 /*-----------------------------------------------------------------*/
2577 static void 
2578 geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func,int lvl)
2579 {
2580   iCode *ic;
2581   operand *pval;
2582
2583   if (!parms)
2584     return;
2585
2586   /* if this is a param node then do the left & right */
2587   if (parms->type == EX_OP && parms->opval.op == PARAM)
2588     {
2589       geniCodeParms (parms->left, stack, fetype, func,lvl);
2590       geniCodeParms (parms->right, stack, fetype, func,lvl);
2591       return;
2592     }
2593
2594   /* get the parameter value */
2595   if (parms->type == EX_OPERAND)
2596     pval = parms->opval.oprnd;
2597   else
2598     {
2599       /* maybe this else should go away ?? */
2600       /* hack don't like this but too lazy to think of
2601          something better */
2602       if (IS_ADDRESS_OF_OP (parms))
2603         parms->left->lvalue = 1;
2604
2605       if (IS_CAST_OP (parms) &&
2606           IS_PTR (parms->ftype) &&
2607           IS_ADDRESS_OF_OP (parms->right))
2608         parms->right->left->lvalue = 1;
2609
2610       pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2611     }
2612
2613   /* if register parm then make it a send */
2614   if (((parms->argSym && IS_REGPARM (parms->argSym->etype)) ||
2615        IS_REGPARM (parms->etype)) && !func->hasVargs)
2616     {
2617       ic = newiCode (SEND, pval, NULL);
2618       ADDTOCHAIN (ic);
2619     }
2620   else
2621     {
2622       /* now decide whether to push or assign */
2623       if (!(options.stackAuto || IS_RENT (fetype)))
2624         {
2625
2626           /* assign */
2627           operand *top = operandFromSymbol (parms->argSym);
2628           geniCodeAssign (top, pval, 1);
2629         }
2630       else
2631         {
2632           sym_link *p = operandType (pval);
2633           /* push */
2634           ic = newiCode (IPUSH, pval, NULL);
2635           ic->parmPush = 1;
2636           /* update the stack adjustment */
2637           *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2638           ADDTOCHAIN (ic);
2639         }
2640     }
2641
2642 }
2643
2644 /*-----------------------------------------------------------------*/
2645 /* geniCodeCall - generates temp code for calling                  */
2646 /*-----------------------------------------------------------------*/
2647 operand *
2648 geniCodeCall (operand * left, ast * parms,int lvl)
2649 {
2650   iCode *ic;
2651   operand *result;
2652   sym_link *type, *etype;
2653   int stack = 0;
2654
2655   /* take care of parameters with side-effecting
2656      function calls in them, this is required to take care
2657      of overlaying function parameters */
2658   geniCodeSEParms (parms,lvl);
2659
2660   /* first the parameters */
2661   geniCodeParms (parms, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2662
2663   /* now call : if symbol then pcall */
2664   if (IS_OP_POINTER (left) || IS_ITEMP(left))
2665     ic = newiCode (PCALL, left, NULL);
2666   else
2667     ic = newiCode (CALL, left, NULL);
2668
2669   IC_ARGS (ic) = left->operand.symOperand->args;
2670   type = copyLinkChain (operandType (left)->next);
2671   etype = getSpec (type);
2672   SPEC_EXTR (etype) = 0;
2673   IC_RESULT (ic) = result = newiTempOperand (type, 1);
2674
2675   ADDTOCHAIN (ic);
2676
2677   /* stack adjustment after call */
2678   ic->parmBytes = stack;
2679
2680   return result;
2681 }
2682
2683 /*-----------------------------------------------------------------*/
2684 /* geniCodeReceive - generate intermediate code for "receive"      */
2685 /*-----------------------------------------------------------------*/
2686 static void 
2687 geniCodeReceive (value * args)
2688 {
2689   /* for all arguments that are passed in registers */
2690   while (args)
2691     {
2692
2693       if (IS_REGPARM (args->etype))
2694         {
2695           operand *opr = operandFromValue (args);
2696           operand *opl;
2697           symbol *sym = OP_SYMBOL (opr);
2698           iCode *ic;
2699
2700           /* we will use it after all optimizations
2701              and before liveRange calculation */
2702           if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2703             {
2704
2705               if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2706                   options.stackAuto == 0 &&
2707                   !TARGET_IS_DS390)
2708                 {
2709                 }
2710               else
2711                 {
2712                   opl = newiTempOperand (args->type, 0);
2713                   sym->reqv = opl;
2714                   sym->reqv->key = sym->key;
2715                   OP_SYMBOL (sym->reqv)->key = sym->key;
2716                   OP_SYMBOL (sym->reqv)->isreqv = 1;
2717                   OP_SYMBOL (sym->reqv)->islocal = 0;
2718                   SPIL_LOC (sym->reqv) = sym;
2719                 }
2720             }
2721
2722           ic = newiCode (RECEIVE, NULL, NULL);
2723           currFunc->recvSize = getSize (sym->etype);
2724           IC_RESULT (ic) = opr;
2725           ADDTOCHAIN (ic);
2726         }
2727
2728       args = args->next;
2729     }
2730 }
2731
2732 /*-----------------------------------------------------------------*/
2733 /* geniCodeFunctionBody - create the function body                 */
2734 /*-----------------------------------------------------------------*/
2735 void 
2736 geniCodeFunctionBody (ast * tree,int lvl)
2737 {
2738   iCode *ic;
2739   operand *func;
2740   sym_link *fetype;
2741   int savelineno;
2742
2743   /* reset the auto generation */
2744   /* numbers */
2745   iTempNum = 0;
2746   iTempLblNum = 0;
2747   operandKey = 0;
2748   iCodeKey = 0;
2749   func = ast2iCode (tree->left,lvl+1);
2750   fetype = getSpec (operandType (func));
2751
2752   savelineno = lineno;
2753   lineno = OP_SYMBOL (func)->lineDef;
2754   /* create an entry label */
2755   geniCodeLabel (entryLabel);
2756   lineno = savelineno;
2757
2758   /* create a proc icode */
2759   ic = newiCode (FUNCTION, func, NULL);
2760   /* if the function has parmas   then */
2761   /* save the parameters information    */
2762   ic->argLabel.args = tree->values.args;
2763   ic->lineno = OP_SYMBOL (func)->lineDef;
2764
2765   ADDTOCHAIN (ic);
2766
2767   /* for all parameters that are passed
2768      on registers add a "receive" */
2769   geniCodeReceive (tree->values.args);
2770
2771   /* generate code for the body */
2772   ast2iCode (tree->right,lvl+1);
2773
2774   /* create a label for return */
2775   geniCodeLabel (returnLabel);
2776
2777   /* now generate the end proc */
2778   ic = newiCode (ENDFUNCTION, func, NULL);
2779   ADDTOCHAIN (ic);
2780   return;
2781 }
2782
2783 /*-----------------------------------------------------------------*/
2784 /* geniCodeReturn - gen icode for 'return' statement               */
2785 /*-----------------------------------------------------------------*/
2786 void 
2787 geniCodeReturn (operand * op)
2788 {
2789   iCode *ic;
2790
2791   /* if the operand is present force an rvalue */
2792   if (op)
2793     op = geniCodeRValue (op, FALSE);
2794
2795   ic = newiCode (RETURN, op, NULL);
2796   ADDTOCHAIN (ic);
2797 }
2798
2799 /*-----------------------------------------------------------------*/
2800 /* geniCodeIfx - generates code for extended if statement          */
2801 /*-----------------------------------------------------------------*/
2802 void 
2803 geniCodeIfx (ast * tree,int lvl)
2804 {
2805   iCode *ic;
2806   operand *condition = ast2iCode (tree->left,lvl+1);
2807   sym_link *cetype;
2808
2809   /* if condition is null then exit */
2810   if (!condition)
2811     goto exit;
2812   else
2813     condition = geniCodeRValue (condition, FALSE);
2814
2815   cetype = getSpec (operandType (condition));
2816   /* if the condition is a literal */
2817   if (IS_LITERAL (cetype))
2818     {
2819       if (floatFromVal (condition->operand.valOperand))
2820         {
2821           if (tree->trueLabel)
2822             geniCodeGoto (tree->trueLabel);
2823           else
2824             assert (1);
2825         }
2826       else
2827         {
2828           if (tree->falseLabel)
2829             geniCodeGoto (tree->falseLabel);
2830           else
2831             assert (1);
2832         }
2833       goto exit;
2834     }
2835
2836   if (tree->trueLabel)
2837     {
2838       ic = newiCodeCondition (condition,
2839                               tree->trueLabel,
2840                               NULL);
2841       ADDTOCHAIN (ic);
2842
2843       if (tree->falseLabel)
2844         geniCodeGoto (tree->falseLabel);
2845     }
2846   else
2847     {
2848       ic = newiCodeCondition (condition,
2849                               NULL,
2850                               tree->falseLabel);
2851       ADDTOCHAIN (ic);
2852     }
2853
2854 exit:
2855   ast2iCode (tree->right,lvl+1);
2856 }
2857
2858 /*-----------------------------------------------------------------*/
2859 /* geniCodeJumpTable - tries to create a jump table for switch     */
2860 /*-----------------------------------------------------------------*/
2861 int 
2862 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
2863 {
2864   int min = 0, max = 0, t, cnt = 0;
2865   value *vch;
2866   iCode *ic;
2867   operand *boundary;
2868   symbol *falseLabel;
2869   set *labels = NULL;
2870
2871   if (!tree || !caseVals)
2872     return 0;
2873
2874   /* the criteria for creating a jump table is */
2875   /* all integer numbers between the maximum & minimum must */
2876   /* be present , the maximum value should not exceed 255 */
2877   min = max = (int) floatFromVal (vch = caseVals);
2878   sprintf (buffer, "_case_%d_%d",
2879            tree->values.switchVals.swNum,
2880            min);
2881   addSet (&labels, newiTempLabel (buffer));
2882
2883   /* if there is only one case value then no need */
2884   if (!(vch = vch->next))
2885     return 0;
2886
2887   while (vch)
2888     {
2889       if (((t = (int) floatFromVal (vch)) - max) != 1)
2890         return 0;
2891       sprintf (buffer, "_case_%d_%d",
2892                tree->values.switchVals.swNum,
2893                t);
2894       addSet (&labels, newiTempLabel (buffer));
2895       max = t;
2896       cnt++;
2897       vch = vch->next;
2898     }
2899
2900   /* if the number of case statements <= 2 then */
2901   /* it is not economical to create the jump table */
2902   /* since two compares are needed for boundary conditions */
2903   if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
2904     return 0;
2905
2906   if (tree->values.switchVals.swDefault)
2907     sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
2908   else
2909     sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
2910
2911   falseLabel = newiTempLabel (buffer);
2912
2913   /* so we can create a jumptable */
2914   /* first we rule out the boundary conditions */
2915   /* if only optimization says so */
2916   if (!optimize.noJTabBoundary)
2917     {
2918       sym_link *cetype = getSpec (operandType (cond));
2919       /* no need to check the lower bound if
2920          the condition is unsigned & minimum value is zero */
2921       if (!(min == 0 && SPEC_USIGN (cetype)))
2922         {
2923           boundary = geniCodeLogic (cond, operandFromLit (min), '<');
2924           ic = newiCodeCondition (boundary, falseLabel, NULL);
2925           ADDTOCHAIN (ic);
2926         }
2927
2928       /* now for upper bounds */
2929       boundary = geniCodeLogic (cond, operandFromLit (max), '>');
2930       ic = newiCodeCondition (boundary, falseLabel, NULL);
2931       ADDTOCHAIN (ic);
2932     }
2933
2934   /* if the min is not zero then we no make it zero */
2935   if (min)
2936     {
2937       cond = geniCodeSubtract (cond, operandFromLit (min));
2938       setOperandType (cond, UCHARTYPE);
2939     }
2940
2941   /* now create the jumptable */
2942   ic = newiCode (JUMPTABLE, NULL, NULL);
2943   IC_JTCOND (ic) = cond;
2944   IC_JTLABELS (ic) = labels;
2945   ADDTOCHAIN (ic);
2946   return 1;
2947 }
2948
2949 /*-----------------------------------------------------------------*/
2950 /* geniCodeSwitch - changes a switch to a if statement             */
2951 /*-----------------------------------------------------------------*/
2952 void 
2953 geniCodeSwitch (ast * tree,int lvl)
2954 {
2955   iCode *ic;
2956   operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
2957   value *caseVals = tree->values.switchVals.swVals;
2958   symbol *trueLabel, *falseLabel;
2959
2960   /* if we can make this a jump table */
2961   if (geniCodeJumpTable (cond, caseVals, tree))
2962     goto jumpTable;             /* no need for the comparison */
2963
2964   /* for the cases defined do */
2965   while (caseVals)
2966     {
2967
2968       operand *compare = geniCodeLogic (cond,
2969                                         operandFromValue (caseVals),
2970                                         EQ_OP);
2971
2972       sprintf (buffer, "_case_%d_%d",
2973                tree->values.switchVals.swNum,
2974                (int) floatFromVal (caseVals));
2975       trueLabel = newiTempLabel (buffer);
2976
2977       ic = newiCodeCondition (compare, trueLabel, NULL);
2978       ADDTOCHAIN (ic);
2979       caseVals = caseVals->next;
2980     }
2981
2982
2983
2984   /* if default is present then goto break else break */
2985   if (tree->values.switchVals.swDefault)
2986     sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
2987   else
2988     sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
2989
2990   falseLabel = newiTempLabel (buffer);
2991   geniCodeGoto (falseLabel);
2992
2993 jumpTable:
2994   ast2iCode (tree->right,lvl+1);
2995 }
2996
2997 /*-----------------------------------------------------------------*/
2998 /* geniCodeInline - intermediate code for inline assembler         */
2999 /*-----------------------------------------------------------------*/
3000 static void 
3001 geniCodeInline (ast * tree)
3002 {
3003   iCode *ic;
3004
3005   ic = newiCode (INLINEASM, NULL, NULL);
3006   IC_INLINE (ic) = tree->values.inlineasm;
3007   ADDTOCHAIN (ic);
3008 }
3009
3010 /*-----------------------------------------------------------------*/
3011 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some      */
3012 /* particular case. Ie : assigning or dereferencing array or ptr   */
3013 /*-----------------------------------------------------------------*/
3014 set * lvaluereqSet = NULL;
3015 typedef struct lvalItem
3016   {
3017     int req;
3018     int lvl;
3019   }
3020 lvalItem;
3021
3022 /*-----------------------------------------------------------------*/
3023 /* addLvaluereq - add a flag for lvalreq for current ast level     */
3024 /*-----------------------------------------------------------------*/
3025 void addLvaluereq(int lvl)
3026 {
3027   lvalItem * lpItem = (lvalItem *)Safe_calloc (1, sizeof (lvalItem));
3028   lpItem->req=1;
3029   lpItem->lvl=lvl;
3030   addSetHead(&lvaluereqSet,lpItem);
3031
3032 }
3033 /*-----------------------------------------------------------------*/
3034 /* delLvaluereq - del a flag for lvalreq for current ast level     */
3035 /*-----------------------------------------------------------------*/
3036 void delLvaluereq()
3037 {
3038   lvalItem * lpItem;
3039   lpItem = getSet(&lvaluereqSet);
3040   if(lpItem) free(lpItem);
3041 }
3042 /*-----------------------------------------------------------------*/
3043 /* clearLvaluereq - clear lvalreq flag                             */
3044 /*-----------------------------------------------------------------*/
3045 void clearLvaluereq()
3046 {
3047   lvalItem * lpItem;
3048   lpItem = peekSet(lvaluereqSet);
3049   if(lpItem) lpItem->req = 0;
3050 }
3051 /*-----------------------------------------------------------------*/
3052 /* getLvaluereq - get the last lvalreq level                       */
3053 /*-----------------------------------------------------------------*/
3054 int getLvaluereqLvl()
3055 {
3056   lvalItem * lpItem;
3057   lpItem = peekSet(lvaluereqSet);
3058   if(lpItem) return lpItem->lvl;
3059   return 0;
3060 }
3061 /*-----------------------------------------------------------------*/
3062 /* isLvaluereq - is lvalreq valid for this level ?                 */
3063 /*-----------------------------------------------------------------*/
3064 int isLvaluereq(int lvl)
3065 {
3066   lvalItem * lpItem;
3067   lpItem = peekSet(lvaluereqSet);
3068   if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3069   return 0;
3070 }
3071
3072 /*-----------------------------------------------------------------*/
3073 /* ast2iCode - creates an icodeList from an ast                    */
3074 /*-----------------------------------------------------------------*/
3075 operand *
3076 ast2iCode (ast * tree,int lvl)
3077 {
3078   operand *left = NULL;
3079   operand *right = NULL;
3080   if (!tree)
3081     return NULL;
3082   /* set the global variables for filename & line number */
3083   if (tree->filename)
3084     filename = tree->filename;
3085   if (tree->lineno)
3086     lineno = tree->lineno;
3087   if (tree->block)
3088     block = tree->block;
3089   if (tree->level)
3090     scopeLevel = tree->level;
3091
3092   if (tree->type == EX_VALUE)
3093     return operandFromValue (tree->opval.val);
3094
3095   if (tree->type == EX_LINK)
3096     return operandFromLink (tree->opval.lnk);
3097
3098   /* if we find a nullop */
3099   if (tree->type == EX_OP &&
3100      (tree->opval.op == NULLOP ||
3101      tree->opval.op == BLOCK))
3102     {
3103       ast2iCode (tree->left,lvl+1);
3104       ast2iCode (tree->right,lvl+1);
3105       return NULL;
3106     }
3107
3108   /* special cases for not evaluating */
3109   if (tree->opval.op != ':' &&
3110       tree->opval.op != '?' &&
3111       tree->opval.op != CALL &&
3112       tree->opval.op != IFX &&
3113       tree->opval.op != LABEL &&
3114       tree->opval.op != GOTO &&
3115       tree->opval.op != SWITCH &&
3116       tree->opval.op != FUNCTION &&
3117       tree->opval.op != INLINEASM)
3118     {
3119
3120         if (IS_ASSIGN_OP (tree->opval.op) ||
3121            IS_DEREF_OP (tree) ||
3122            (tree->opval.op == '&' && !tree->right) ||
3123            tree->opval.op == PTR_OP)
3124           {
3125             addLvaluereq(lvl);
3126             if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3127                (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3128               clearLvaluereq();
3129
3130             left = operandFromAst (tree->left,lvl);
3131             delLvaluereq();
3132             if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3133               left = geniCodeRValue (left, TRUE);
3134           }
3135         else
3136           {
3137             left = operandFromAst (tree->left,lvl);
3138           }
3139         if (tree->opval.op == INC_OP ||
3140             tree->opval.op == DEC_OP)
3141           {
3142             addLvaluereq(lvl);
3143             right = operandFromAst (tree->right,lvl);
3144             delLvaluereq();
3145           }
3146         else
3147           {
3148             right = operandFromAst (tree->right,lvl);
3149           }
3150       }
3151
3152   /* now depending on the type of operand */
3153   /* this will be a biggy                 */
3154   switch (tree->opval.op)
3155     {
3156
3157     case '[':                   /* array operation */
3158       {
3159         sym_link *ltype = operandType (left);
3160         left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3161         right = geniCodeRValue (right, TRUE);
3162       }
3163
3164       return geniCodeArray (left, right,lvl);
3165
3166     case '.':                   /* structure dereference */
3167       if (IS_PTR (operandType (left)))
3168         left = geniCodeRValue (left, TRUE);
3169       else
3170         left = geniCodeRValue (left, FALSE);
3171
3172       return geniCodeStruct (left, right, tree->lvalue);
3173
3174     case PTR_OP:                /* structure pointer dereference */
3175       {
3176         sym_link *pType;
3177         pType = operandType (left);
3178         left = geniCodeRValue (left, TRUE);
3179
3180         setOClass (pType, getSpec (operandType (left)));
3181       }
3182
3183       return geniCodeStruct (left, right, tree->lvalue);
3184
3185     case INC_OP:                /* increment operator */
3186       if (left)
3187         return geniCodePostInc (left);
3188       else
3189         return geniCodePreInc (right);
3190
3191     case DEC_OP:                /* decrement operator */
3192       if (left)
3193         return geniCodePostDec (left);
3194       else
3195         return geniCodePreDec (right);
3196
3197     case '&':                   /* bitwise and or address of operator */
3198       if (right)
3199         {                       /* this is a bitwise operator   */
3200           left = geniCodeRValue (left, FALSE);
3201           right = geniCodeRValue (right, FALSE);
3202           return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3203         }
3204       else
3205         return geniCodeAddressOf (left);
3206
3207     case '|':                   /* bitwise or & xor */
3208     case '^':
3209       return geniCodeBitwise (geniCodeRValue (left, FALSE),
3210                               geniCodeRValue (right, FALSE),
3211                               tree->opval.op,
3212                               tree->ftype);
3213
3214     case '/':
3215       return geniCodeDivision (geniCodeRValue (left, FALSE),
3216                                geniCodeRValue (right, FALSE));
3217
3218     case '%':
3219       return geniCodeModulus (geniCodeRValue (left, FALSE),
3220                               geniCodeRValue (right, FALSE));
3221     case '*':
3222       if (right)
3223         return geniCodeMultiply (geniCodeRValue (left, FALSE),
3224                                  geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3225       else
3226         return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3227
3228     case '-':
3229       if (right)
3230         return geniCodeSubtract (geniCodeRValue (left, FALSE),
3231                                  geniCodeRValue (right, FALSE));
3232       else
3233         return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3234
3235     case '+':
3236       if (right)
3237         return geniCodeAdd (geniCodeRValue (left, FALSE),
3238                             geniCodeRValue (right, FALSE),lvl);
3239       else
3240         return geniCodeRValue (left, FALSE);    /* unary '+' has no meaning */
3241
3242     case LEFT_OP:
3243       return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3244                                 geniCodeRValue (right, FALSE));
3245
3246     case RIGHT_OP:
3247       return geniCodeRightShift (geniCodeRValue (left, FALSE),
3248                                  geniCodeRValue (right, FALSE));
3249     case CAST:
3250       return geniCodeCast (operandType (left),
3251                            geniCodeRValue (right, FALSE), FALSE);
3252
3253     case '~':
3254     case '!':
3255     case RRC:
3256     case RLC:
3257       return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3258
3259     case GETHBIT:
3260       {
3261         operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3262         setOperandType (op, UCHARTYPE);
3263         return op;
3264       }
3265     case '>':
3266     case '<':
3267     case LE_OP:
3268     case GE_OP:
3269     case EQ_OP:
3270     case NE_OP:
3271     case AND_OP:
3272     case OR_OP:
3273       return geniCodeLogic (geniCodeRValue (left, FALSE),
3274                             geniCodeRValue (right, FALSE),
3275                             tree->opval.op);
3276     case '?':
3277       return geniCodeConditional (tree,lvl);
3278
3279     case SIZEOF:
3280       return operandFromLit (getSize (tree->right->ftype));
3281
3282     case '=':
3283       {
3284         sym_link *rtype = operandType (right);
3285         sym_link *ltype = operandType (left);
3286         if (IS_PTR (rtype) && IS_ITEMP (right)
3287             && right->isaddr && compareType (rtype->next, ltype) == 1)
3288           right = geniCodeRValue (right, TRUE);
3289         else
3290           right = geniCodeRValue (right, FALSE);
3291
3292         geniCodeAssign (left, right, 0);
3293         return right;
3294       }
3295     case MUL_ASSIGN:
3296       return
3297         geniCodeAssign (left,
3298                 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3299                                                   FALSE),
3300                                   geniCodeRValue (right, FALSE),FALSE), 0);
3301
3302     case DIV_ASSIGN:
3303       return
3304         geniCodeAssign (left,
3305                 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3306                                                   FALSE),
3307                                   geniCodeRValue (right, FALSE)), 0);
3308     case MOD_ASSIGN:
3309       return
3310         geniCodeAssign (left,
3311                  geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3312                                                   FALSE),
3313                                   geniCodeRValue (right, FALSE)), 0);
3314     case ADD_ASSIGN:
3315       {
3316         sym_link *rtype = operandType (right);
3317         sym_link *ltype = operandType (left);
3318         if (IS_PTR (rtype) && IS_ITEMP (right)
3319             && right->isaddr && compareType (rtype->next, ltype) == 1)
3320           right = geniCodeRValue (right, TRUE);
3321         else
3322           right = geniCodeRValue (right, FALSE);
3323
3324
3325         return geniCodeAssign (left,
3326                      geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3327                                                   FALSE),
3328                                   right,lvl), 0);
3329       }
3330     case SUB_ASSIGN:
3331       {
3332         sym_link *rtype = operandType (right);
3333         sym_link *ltype = operandType (left);
3334         if (IS_PTR (rtype) && IS_ITEMP (right)
3335             && right->isaddr && compareType (rtype->next, ltype) == 1)
3336           {
3337             right = geniCodeRValue (right, TRUE);
3338           }
3339         else
3340           {
3341             right = geniCodeRValue (right, FALSE);
3342           }
3343         return
3344           geniCodeAssign (left,
3345                 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3346                                                   FALSE),
3347                                   right), 0);
3348       }
3349     case LEFT_ASSIGN:
3350       return
3351         geniCodeAssign (left,
3352                 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3353                                                    ,FALSE),
3354                                    geniCodeRValue (right, FALSE)), 0);
3355     case RIGHT_ASSIGN:
3356       return
3357         geniCodeAssign (left,
3358                geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3359                                                    ,FALSE),
3360                                    geniCodeRValue (right, FALSE)), 0);
3361     case AND_ASSIGN:
3362       return
3363         geniCodeAssign (left,
3364                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3365                                                   FALSE),
3366                                   geniCodeRValue (right, FALSE),
3367                                   BITWISEAND,
3368                                   operandType (left)), 0);
3369     case XOR_ASSIGN:
3370       return
3371         geniCodeAssign (left,
3372                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3373                                                   FALSE),
3374                                   geniCodeRValue (right, FALSE),
3375                                   '^',
3376                                   operandType (left)), 0);
3377     case OR_ASSIGN:
3378       return
3379         geniCodeAssign (left,
3380                   geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3381                                                    ,FALSE),
3382                                    geniCodeRValue (right, FALSE),
3383                                    '|',
3384                                    operandType (left)), 0);
3385     case ',':
3386       return geniCodeRValue (right, FALSE);
3387
3388     case CALL:
3389       return geniCodeCall (ast2iCode (tree->left,lvl+1),
3390                            tree->right,lvl);
3391     case LABEL:
3392       geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3393       return ast2iCode (tree->right,lvl+1);
3394
3395     case GOTO:
3396       geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3397       return ast2iCode (tree->right,lvl+1);
3398
3399     case FUNCTION:
3400       geniCodeFunctionBody (tree,lvl);
3401       return NULL;
3402
3403     case RETURN:
3404       geniCodeReturn (right);
3405       return NULL;
3406
3407     case IFX:
3408       geniCodeIfx (tree,lvl);
3409       return NULL;
3410
3411     case SWITCH:
3412       geniCodeSwitch (tree,lvl);
3413       return NULL;
3414
3415     case INLINEASM:
3416       geniCodeInline (tree);
3417       return NULL;
3418     }
3419
3420   return NULL;
3421 }
3422
3423 /*-----------------------------------------------------------------*/
3424 /* reverseICChain - gets from the list and creates a linkedlist    */
3425 /*-----------------------------------------------------------------*/
3426 iCode *
3427 reverseiCChain ()
3428 {
3429   iCode *loop = NULL;
3430   iCode *prev = NULL;
3431
3432   while ((loop = getSet (&iCodeChain)))
3433     {
3434       loop->next = prev;
3435       if (prev)
3436         prev->prev = loop;
3437       prev = loop;
3438     }
3439
3440   return prev;
3441 }
3442
3443
3444 /*-----------------------------------------------------------------*/
3445 /* iCodeFromAst - given an ast will convert it to iCode            */
3446 /*-----------------------------------------------------------------*/
3447 iCode *
3448 iCodeFromAst (ast * tree)
3449 {
3450   returnLabel = newiTempLabel ("_return");
3451   entryLabel = newiTempLabel ("_entry");
3452   ast2iCode (tree,0);
3453   return reverseiCChain ();
3454 }