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