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