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