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