Added routine PICC - short for piCodeCChain
[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 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)) && (!IS_DS390_PORT)) &&
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)) || IS_DS390_PORT))
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 (IS_DS390_PORT) { */
1682           /* jwk char*char=int
1683              Now be can use the 16bit result of "mul a,b" instead of explicit
1684              casts and support function calls as with --ansiint
1685           */
1686           /*       if ((IS_CHAR(letype) || IS_SHORT(letype)) &&  */
1687           /*       (IS_CHAR(retype) || IS_SHORT(retype))) { */
1688           if (resultIsInt) {
1689                   SPEC_NOUN(getSpec(resType))=V_INT;
1690                   SPEC_SHORT(getSpec(resType))=0;
1691           }
1692   }
1693 /*   } */
1694
1695   /* if the right is a literal & power of 2 */
1696   /* then make it a left shift              */
1697   /*If we are computing  ptr size then normal multiplication */
1698   /*code generated for 1 byte * 1 byte literal = 2 bytes result is more efficient in most cases */
1699   /*than 2 bytes result = 2 bytes << literal if port as 1 byte muldiv */
1700   if (IS_LITERAL (retype) && !IS_FLOAT (letype) &&
1701       !((ptrSizeCalculation) && (getSize (resType) != getSize (ltype)) && (1 == port->muldiv.native_below)) &&
1702    (p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand))))
1703     {
1704       if ((ptrSizeCalculation) && (getSize (resType) != getSize (ltype)))
1705         {
1706           /* LEFT_OP need same size for left and result, */
1707           left = geniCodeCast (resType, left, TRUE);
1708           ltype = operandType (left);
1709         }
1710       ic = newiCode (LEFT_OP, left, operandFromLit (p2));       /* left shift */
1711     }
1712   else
1713     {
1714       ic = newiCode ('*', left, right);         /* normal multiplication */
1715       /* if the size left or right > 1 then support routine */
1716       if (getSize (ltype) > 1 || getSize (rtype) > 1)
1717         ic->supportRtn = 1;
1718
1719     }
1720   IC_RESULT (ic) = newiTempOperand (resType, 1);
1721
1722   ADDTOCHAIN (ic);
1723   return IC_RESULT (ic);
1724 }
1725
1726 /*-----------------------------------------------------------------*/
1727 /* geniCodeDivision - gen intermediate code for division           */
1728 /*-----------------------------------------------------------------*/
1729 operand *
1730 geniCodeDivision (operand * left, operand * right)
1731 {
1732   iCode *ic;
1733   int p2 = 0;
1734   sym_link *resType;
1735   sym_link *rtype = operandType (right);
1736   sym_link *retype = getSpec (rtype);
1737   sym_link *ltype = operandType (left);
1738   sym_link *letype = getSpec (ltype);
1739
1740   resType = usualBinaryConversions (&left, &right);
1741
1742   /* if the right is a literal & power of 2 */
1743   /* then make it a right shift             */
1744   if (IS_LITERAL (retype) &&
1745       !IS_FLOAT (letype) &&
1746       (p2 = powof2 ((unsigned long)
1747                     floatFromVal (right->operand.valOperand))))
1748     ic = newiCode (RIGHT_OP, left, operandFromLit (p2));        /* right shift */
1749   else
1750     {
1751       ic = newiCode ('/', left, right);         /* normal division */
1752       /* if the size left or right > 1 then support routine */
1753       if (getSize (ltype) > 1 || getSize (rtype) > 1)
1754         ic->supportRtn = 1;
1755     }
1756   IC_RESULT (ic) = newiTempOperand (resType, 0);
1757
1758   ADDTOCHAIN (ic);
1759   return IC_RESULT (ic);
1760 }
1761 /*-----------------------------------------------------------------*/
1762 /* geniCodeModulus  - gen intermediate code for modulus            */
1763 /*-----------------------------------------------------------------*/
1764 operand *
1765 geniCodeModulus (operand * left, operand * right)
1766 {
1767   iCode *ic;
1768   sym_link *resType;
1769   LRTYPE;
1770
1771   /* if they are both literal then we know the result */
1772   if (IS_LITERAL (letype) && IS_LITERAL (retype))
1773     return operandFromValue (valMod (left->operand.valOperand,
1774                                      right->operand.valOperand));
1775
1776   resType = usualBinaryConversions (&left, &right);
1777
1778   /* now they are the same size */
1779   ic = newiCode ('%', left, right);
1780
1781   /* if the size left or right > 1 then support routine */
1782   if (getSize (ltype) > 1 || getSize (rtype) > 1)
1783     ic->supportRtn = 1;
1784   IC_RESULT (ic) = newiTempOperand (resType, 0);
1785
1786   ADDTOCHAIN (ic);
1787   return IC_RESULT (ic);
1788 }
1789
1790 /*-----------------------------------------------------------------*/
1791 /* geniCodePtrPtrSubtract - subtracts pointer from pointer         */
1792 /*-----------------------------------------------------------------*/
1793 operand *
1794 geniCodePtrPtrSubtract (operand * left, operand * right)
1795 {
1796   iCode *ic;
1797   operand *result;
1798   LRTYPE;
1799
1800   /* if they are both literals then */
1801   if (IS_LITERAL (letype) && IS_LITERAL (retype))
1802     {
1803       result = operandFromValue (valMinus (left->operand.valOperand,
1804                                            right->operand.valOperand));
1805       goto subtractExit;
1806     }
1807
1808   ic = newiCode ('-', left, right);
1809
1810   IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1811   ADDTOCHAIN (ic);
1812
1813 subtractExit:
1814   return geniCodeDivision (result,
1815                            operandFromLit (getSize (ltype->next)));
1816 }
1817
1818 /*-----------------------------------------------------------------*/
1819 /* geniCodeSubtract - generates code for subtraction               */
1820 /*-----------------------------------------------------------------*/
1821 operand *
1822 geniCodeSubtract (operand * left, operand * right)
1823 {
1824   iCode *ic;
1825   int isarray = 0;
1826   sym_link *resType;
1827   LRTYPE;
1828
1829   /* if they both pointers then */
1830   if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
1831       (IS_PTR (rtype) || IS_ARRAY (rtype)))
1832     return geniCodePtrPtrSubtract (left, right);
1833
1834   /* if they are both literal then we know the result */
1835   if (IS_LITERAL (letype) && IS_LITERAL (retype)
1836       && left->isLiteral && right->isLiteral)
1837     return operandFromValue (valMinus (left->operand.valOperand,
1838                                        right->operand.valOperand));
1839
1840   /* if left is an array or pointer */
1841   if (IS_PTR (ltype) || IS_ARRAY (ltype))
1842     {
1843       isarray = left->isaddr;
1844       right = geniCodeMultiply (right,
1845                               operandFromLit (getSize (ltype->next)), TRUE, FALSE);
1846       resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
1847     }
1848   else
1849     {                           /* make them the same size */
1850       resType = usualBinaryConversions (&left, &right);
1851     }
1852
1853   ic = newiCode ('-', left, right);
1854
1855   IC_RESULT (ic) = newiTempOperand (resType, 1);
1856   IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1857
1858   /* if left or right is a float */
1859   if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1860     ic->supportRtn = 1;
1861
1862   ADDTOCHAIN (ic);
1863   return IC_RESULT (ic);
1864 }
1865
1866 /*-----------------------------------------------------------------*/
1867 /* geniCodeAdd - generates iCode for addition                      */
1868 /*-----------------------------------------------------------------*/
1869 operand *
1870 geniCodeAdd (operand * left, operand * right)
1871 {
1872   iCode *ic;
1873   sym_link *resType;
1874   operand *size;
1875   int isarray = 0;
1876   LRTYPE;
1877
1878   /* if left is an array then array access */
1879   if (IS_ARRAY (ltype))
1880     return geniCodeArray (left, right);
1881
1882   /* if the right side is LITERAL zero */
1883   /* return the left side              */
1884   if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
1885     return left;
1886
1887   /* if left is literal zero return right */
1888   if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
1889     return right;
1890
1891   /* if left is an array or pointer then size */
1892   if (IS_PTR (ltype))
1893     {
1894
1895       isarray = left->isaddr;
1896       size =
1897         operandFromLit (getSize (ltype->next));
1898
1899       right = geniCodeMultiply (right, size, (getSize (ltype) != 1),FALSE);
1900
1901       resType = copyLinkChain (ltype);
1902     }
1903   else
1904     {                           /* make them the same size */
1905       resType = usualBinaryConversions (&left, &right);
1906     }
1907
1908   /* if they are both literals then we know */
1909   if (IS_LITERAL (letype) && IS_LITERAL (retype)
1910       && left->isLiteral && right->isLiteral)
1911     return operandFromValue (valPlus (valFromType (letype),
1912                                       valFromType (retype)));
1913
1914   ic = newiCode ('+', left, right);
1915
1916   IC_RESULT (ic) = newiTempOperand (resType, 1);
1917   IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
1918
1919   /* if left or right is a float then support
1920      routine */
1921   if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
1922     ic->supportRtn = 1;
1923
1924   ADDTOCHAIN (ic);
1925
1926   return IC_RESULT (ic);
1927
1928 }
1929
1930 /*-----------------------------------------------------------------*/
1931 /* aggrToPtr - changes an aggregate to pointer to an aggregate     */
1932 /*-----------------------------------------------------------------*/
1933 sym_link *
1934 aggrToPtr (sym_link * type, bool force)
1935 {
1936   sym_link *etype;
1937   sym_link *ptype;
1938
1939
1940   if (IS_PTR (type) && !force)
1941     return type;
1942
1943   etype = getSpec (type);
1944   ptype = newLink ();
1945
1946   ptype->next = type;
1947   /* if the output class is generic */
1948   if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
1949     DCL_PTR_CONST (ptype) = port->mem.code_ro;
1950
1951   /* if the variable was declared a constant */
1952   /* then the pointer points to a constant */
1953   if (IS_CONSTANT (etype))
1954     DCL_PTR_CONST (ptype) = 1;
1955
1956   /* the variable was volatile then pointer to volatile */
1957   if (IS_VOLATILE (etype))
1958     DCL_PTR_VOLATILE (ptype) = 1;
1959   return ptype;
1960 }
1961
1962 /*-----------------------------------------------------------------*/
1963 /* geniCodeArray2Ptr - array to pointer                            */
1964 /*-----------------------------------------------------------------*/
1965 operand *
1966 geniCodeArray2Ptr (operand * op)
1967 {
1968   sym_link *optype = operandType (op);
1969   sym_link *opetype = getSpec (optype);
1970
1971   /* set the pointer depending on the storage class */
1972   if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
1973     DCL_PTR_CONST (optype) = port->mem.code_ro;
1974
1975
1976   /* if the variable was declared a constant */
1977   /* then the pointer points to a constant */
1978   if (IS_CONSTANT (opetype))
1979     DCL_PTR_CONST (optype) = 1;
1980
1981   /* the variable was volatile then pointer to volatile */
1982   if (IS_VOLATILE (opetype))
1983     DCL_PTR_VOLATILE (optype) = 1;
1984   op->isaddr = 0;
1985   return op;
1986 }
1987
1988
1989 /*-----------------------------------------------------------------*/
1990 /* geniCodeArray - array access                                    */
1991 /*-----------------------------------------------------------------*/
1992 operand *
1993 geniCodeArray (operand * left, operand * right)
1994 {
1995   iCode *ic;
1996   sym_link *ltype = operandType (left);
1997
1998   if (IS_PTR (ltype))
1999     {
2000       if (IS_PTR (ltype->next) && left->isaddr)
2001         {
2002           left = geniCodeRValue (left, FALSE);
2003         }
2004       return geniCodeDerefPtr (geniCodeAdd (left, right));
2005     }
2006
2007   /* array access */
2008   right = geniCodeMultiply (right,
2009                             operandFromLit (getSize (ltype->next)), TRUE,FALSE);
2010
2011   /* we can check for limits here */
2012   if (isOperandLiteral (right) &&
2013       IS_ARRAY (ltype) &&
2014       DCL_ELEM (ltype) &&
2015       (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2016     {
2017       werror (E_ARRAY_BOUND);
2018       right = operandFromLit (0);
2019     }
2020
2021   ic = newiCode ('+', left, right);
2022
2023   IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2024                                       !IS_AGGREGATE (ltype->next) &&
2025                                       !IS_PTR (ltype->next))
2026                                      ? ltype : ltype->next), 0);
2027
2028   IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2029   ADDTOCHAIN (ic);
2030   return IC_RESULT (ic);
2031 }
2032
2033 /*-----------------------------------------------------------------*/
2034 /* geniCodeStruct - generates intermediate code for structres      */
2035 /*-----------------------------------------------------------------*/
2036 operand *
2037 geniCodeStruct (operand * left, operand * right, bool islval)
2038 {
2039   iCode *ic;
2040   sym_link *type = operandType (left);
2041   sym_link *etype = getSpec (type);
2042   sym_link *retype;
2043   symbol *element = getStructElement (SPEC_STRUCT (etype),
2044                                       right->operand.symOperand);
2045
2046   /* add the offset */
2047   ic = newiCode ('+', left, operandFromLit (element->offset));
2048
2049   IC_RESULT (ic) = newiTempOperand (element->type, 0);
2050
2051   /* preserve the storage & output class of the struct */
2052   /* as well as the volatile attribute */
2053   retype = getSpec (operandType (IC_RESULT (ic)));
2054   SPEC_SCLS (retype) = SPEC_SCLS (etype);
2055   SPEC_OCLS (retype) = SPEC_OCLS (etype);
2056   SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2057
2058   if (IS_PTR (element->type))
2059     setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2060
2061   IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2062
2063
2064   ADDTOCHAIN (ic);
2065   return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2066 }
2067
2068 /*-----------------------------------------------------------------*/
2069 /* geniCodePostInc - generate int code for Post increment          */
2070 /*-----------------------------------------------------------------*/
2071 operand *
2072 geniCodePostInc (operand * op)
2073 {
2074   iCode *ic;
2075   operand *rOp;
2076   sym_link *optype = operandType (op);
2077   operand *result;
2078   operand *rv = (IS_ITEMP (op) ?
2079                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2080                  op);
2081   sym_link *rvtype = operandType (rv);
2082   int size = 0;
2083
2084   /* if this is not an address we have trouble */
2085   if (!op->isaddr)
2086     {
2087       werror (E_LVALUE_REQUIRED, "++");
2088       return op;
2089     }
2090
2091   rOp = newiTempOperand (rvtype, 0);
2092   rOp->noSpilLoc = 1;
2093
2094   if (IS_ITEMP (rv))
2095     rv->noSpilLoc = 1;
2096
2097   geniCodeAssign (rOp, rv, 0);
2098
2099   size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2100   if (IS_FLOAT (rvtype))
2101     ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2102   else
2103     ic = newiCode ('+', rv, operandFromLit (size));
2104
2105   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2106   ADDTOCHAIN (ic);
2107
2108   geniCodeAssign (op, result, 0);
2109
2110   return rOp;
2111
2112 }
2113
2114 /*-----------------------------------------------------------------*/
2115 /* geniCodePreInc - generate code for preIncrement                 */
2116 /*-----------------------------------------------------------------*/
2117 operand *
2118 geniCodePreInc (operand * op)
2119 {
2120   iCode *ic;
2121   sym_link *optype = operandType (op);
2122   operand *rop = (IS_ITEMP (op) ?
2123                   geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2124                   op);
2125   sym_link *roptype = operandType (rop);
2126   operand *result;
2127   int size = 0;
2128
2129   if (!op->isaddr)
2130     {
2131       werror (E_LVALUE_REQUIRED, "++");
2132       return op;
2133     }
2134
2135
2136   size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2137   if (IS_FLOAT (roptype))
2138     ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2139   else
2140     ic = newiCode ('+', rop, operandFromLit (size));
2141   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2142   ADDTOCHAIN (ic);
2143
2144
2145   return geniCodeAssign (op, result, 0);
2146 }
2147
2148 /*-----------------------------------------------------------------*/
2149 /* geniCodePostDec - generates code for Post decrement             */
2150 /*-----------------------------------------------------------------*/
2151 operand *
2152 geniCodePostDec (operand * op)
2153 {
2154   iCode *ic;
2155   operand *rOp;
2156   sym_link *optype = operandType (op);
2157   operand *result;
2158   operand *rv = (IS_ITEMP (op) ?
2159                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2160                  op);
2161   sym_link *rvtype = operandType (rv);
2162   int size = 0;
2163
2164   /* if this is not an address we have trouble */
2165   if (!op->isaddr)
2166     {
2167       werror (E_LVALUE_REQUIRED, "++");
2168       return op;
2169     }
2170
2171   rOp = newiTempOperand (rvtype, 0);
2172   rOp->noSpilLoc = 1;
2173
2174   if (IS_ITEMP (rv))
2175     rv->noSpilLoc = 1;
2176
2177   geniCodeAssign (rOp, rv, 0);
2178
2179   size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2180   if (IS_FLOAT (rvtype))
2181     ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2182   else
2183     ic = newiCode ('-', rv, operandFromLit (size));
2184
2185   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2186   ADDTOCHAIN (ic);
2187
2188   geniCodeAssign (op, result, 0);
2189
2190   return rOp;
2191
2192 }
2193
2194 /*-----------------------------------------------------------------*/
2195 /* geniCodePreDec - generate code for pre  decrement               */
2196 /*-----------------------------------------------------------------*/
2197 operand *
2198 geniCodePreDec (operand * op)
2199 {
2200   iCode *ic;
2201   sym_link *optype = operandType (op);
2202   operand *rop = (IS_ITEMP (op) ?
2203                   geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2204                   op);
2205   sym_link *roptype = operandType (rop);
2206   operand *result;
2207   int size = 0;
2208
2209   if (!op->isaddr)
2210     {
2211       werror (E_LVALUE_REQUIRED, "++");
2212       return op;
2213     }
2214
2215
2216   size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2217   if (IS_FLOAT (roptype))
2218     ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2219   else
2220     ic = newiCode ('-', rop, operandFromLit (size));
2221   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2222   ADDTOCHAIN (ic);
2223
2224
2225   return geniCodeAssign (op, result, 0);
2226 }
2227
2228
2229 /*-----------------------------------------------------------------*/
2230 /* geniCodeBitwise - gen int code for bitWise  operators           */
2231 /*-----------------------------------------------------------------*/
2232 operand *
2233 geniCodeBitwise (operand * left, operand * right,
2234                  int oper, sym_link * resType)
2235 {
2236   iCode *ic;
2237
2238   left = geniCodeCast (resType, left, TRUE);
2239   right = geniCodeCast (resType, right, TRUE);
2240
2241   ic = newiCode (oper, left, right);
2242   IC_RESULT (ic) = newiTempOperand (resType, 0);
2243
2244   ADDTOCHAIN (ic);
2245   return IC_RESULT (ic);
2246 }
2247
2248 /*-----------------------------------------------------------------*/
2249 /* geniCodeAddressOf - gens icode for '&' address of operator      */
2250 /*-----------------------------------------------------------------*/
2251 operand *
2252 geniCodeAddressOf (operand * op)
2253 {
2254   iCode *ic;
2255   sym_link *p;
2256   sym_link *optype = operandType (op);
2257   sym_link *opetype = getSpec (optype);
2258
2259   /* lvalue check already done in decorateType */
2260   /* this must be a lvalue */
2261 /*     if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2262 /*  werror (E_LVALUE_REQUIRED,"&"); */
2263 /*  return op; */
2264 /*     } */
2265
2266   p = newLink ();
2267   p->class = DECLARATOR;
2268
2269   /* set the pointer depending on the storage class */
2270   if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2271     DCL_PTR_CONST (p) = port->mem.code_ro;
2272
2273   /* make sure we preserve the const & volatile */
2274   if (IS_CONSTANT (opetype))
2275     DCL_PTR_CONST (p) = 1;
2276
2277   if (IS_VOLATILE (opetype))
2278     DCL_PTR_VOLATILE (p) = 1;
2279
2280   p->next = copyLinkChain (optype);
2281
2282   /* if already a temp */
2283   if (IS_ITEMP (op))
2284     {
2285       setOperandType (op, p);
2286       op->isaddr = 0;
2287       return op;
2288     }
2289
2290   /* other wise make this of the type coming in */
2291   ic = newiCode (ADDRESS_OF, op, NULL);
2292   IC_RESULT (ic) = newiTempOperand (p, 1);
2293   IC_RESULT (ic)->isaddr = 0;
2294   ADDTOCHAIN (ic);
2295   return IC_RESULT (ic);
2296 }
2297 /*-----------------------------------------------------------------*/
2298 /* setOClass - sets the output class depending on the pointer type */
2299 /*-----------------------------------------------------------------*/
2300 void 
2301 setOClass (sym_link * ptr, sym_link * spec)
2302 {
2303   switch (DCL_TYPE (ptr))
2304     {
2305     case POINTER:
2306       SPEC_OCLS (spec) = data;
2307       break;
2308
2309     case GPOINTER:
2310       SPEC_OCLS (spec) = generic;
2311       break;
2312
2313     case FPOINTER:
2314       SPEC_OCLS (spec) = xdata;
2315       break;
2316
2317     case CPOINTER:
2318       SPEC_OCLS (spec) = code;
2319       break;
2320
2321     case IPOINTER:
2322       SPEC_OCLS (spec) = idata;
2323       break;
2324
2325     case PPOINTER:
2326       SPEC_OCLS (spec) = xstack;
2327       break;
2328
2329     case EEPPOINTER:
2330       SPEC_OCLS (spec) = eeprom;
2331       break;
2332
2333     default:
2334       break;
2335
2336     }
2337 }
2338
2339 /*-----------------------------------------------------------------*/
2340 /* geniCodeDerefPtr - dereference pointer with '*'                 */
2341 /*-----------------------------------------------------------------*/
2342 operand *
2343 geniCodeDerefPtr (operand * op)
2344 {
2345   sym_link *rtype, *retype;
2346   sym_link *optype = operandType (op);
2347
2348   /* if this is a pointer then generate the rvalue */
2349   if (IS_PTR (optype))
2350     {
2351       if (IS_TRUE_SYMOP (op))
2352         {
2353           op->isaddr = 1;
2354           op = geniCodeRValue (op, TRUE);
2355         }
2356       else
2357         op = geniCodeRValue (op, TRUE);
2358     }
2359
2360   /* now get rid of the pointer part */
2361   if (lvaluereq && IS_ITEMP (op))
2362     {
2363       retype = getSpec (rtype = copyLinkChain (optype));
2364     }
2365   else
2366     {
2367       retype = getSpec (rtype = copyLinkChain (optype->next));
2368     }
2369
2370   /* if this is a pointer then outputclass needs 2b updated */
2371   if (IS_PTR (optype))
2372     setOClass (optype, retype);
2373
2374   op->isGptr = IS_GENPTR (optype);
2375
2376   /* if the pointer was declared as a constant */
2377   /* then we cannot allow assignment to the derefed */
2378   if (IS_PTR_CONST (optype))
2379     SPEC_CONST (retype) = 1;
2380
2381   op->isaddr = (IS_PTR (rtype) ||
2382                 IS_STRUCT (rtype) ||
2383                 IS_INT (rtype) ||
2384                 IS_CHAR (rtype) ||
2385                 IS_FLOAT (rtype));
2386
2387   if (!lvaluereq)
2388     op = geniCodeRValue (op, TRUE);
2389
2390   setOperandType (op, rtype);
2391
2392   return op;
2393 }
2394
2395 /*-----------------------------------------------------------------*/
2396 /* geniCodeUnaryMinus - does a unary minus of the operand          */
2397 /*-----------------------------------------------------------------*/
2398 operand *
2399 geniCodeUnaryMinus (operand * op)
2400 {
2401   iCode *ic;
2402   sym_link *optype = operandType (op);
2403
2404   if (IS_LITERAL (optype))
2405     return operandFromLit (-floatFromVal (op->operand.valOperand));
2406
2407   ic = newiCode (UNARYMINUS, op, NULL);
2408   IC_RESULT (ic) = newiTempOperand (optype, 0);
2409   ADDTOCHAIN (ic);
2410   return IC_RESULT (ic);
2411 }
2412
2413 /*-----------------------------------------------------------------*/
2414 /* geniCodeLeftShift - gen i code for left shift                   */
2415 /*-----------------------------------------------------------------*/
2416 operand *
2417 geniCodeLeftShift (operand * left, operand * right)
2418 {
2419   iCode *ic;
2420
2421
2422   /* Note that we don't use the usual binary conversions for the
2423    * shift operations, in accordance with our ANSI friends.
2424    */
2425   if (options.ANSIint)
2426     {
2427       right = usualUnaryConversions (right);
2428       left = usualUnaryConversions (left);
2429     }
2430
2431   ic = newiCode (LEFT_OP, left, right);
2432   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2433   ADDTOCHAIN (ic);
2434   return IC_RESULT (ic);
2435 }
2436
2437 /*-----------------------------------------------------------------*/
2438 /* geniCodeRightShift - gen i code for right shift                 */
2439 /*-----------------------------------------------------------------*/
2440 operand *
2441 geniCodeRightShift (operand * left, operand * right)
2442 {
2443   iCode *ic;
2444
2445
2446   /* Note that we don't use the usual binary conversions for the
2447    * shift operations, in accordance with our ANSI friends.
2448    */
2449   if (options.ANSIint)
2450     {
2451       right = usualUnaryConversions (right);
2452       left = usualUnaryConversions (left);
2453     }
2454
2455   ic = newiCode (RIGHT_OP, left, right);
2456   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2457   ADDTOCHAIN (ic);
2458   return IC_RESULT (ic);
2459 }
2460
2461 #if defined(__BORLANDC__) || defined(_MSC_VER)
2462 #define LONG_LONG __int64
2463 #else
2464 #define LONG_LONG long long
2465 #endif
2466
2467 /*-----------------------------------------------------------------*/
2468 /* geniCodeLogic- logic code                                       */
2469 /*-----------------------------------------------------------------*/
2470 operand *
2471 geniCodeLogic (operand * left, operand * right, int op)
2472 {
2473   iCode *ic;
2474   sym_link *ctype;
2475   sym_link *rtype = operandType (right);
2476   sym_link *ltype = operandType (left);
2477
2478   /* left is integral type and right is literal then
2479      check if the literal value is within bounds */
2480   if (IS_INTEGRAL (ltype) && IS_LITERAL (rtype))
2481     {
2482       int nbits = bitsForType (ltype);
2483       long v = operandLitValue (right);
2484
2485       if (v > ((LONG_LONG) 1 << nbits) && v > 0)
2486         werror (W_CONST_RANGE, " compare operation ");
2487     }
2488
2489   ctype = usualBinaryConversions (&left, &right);
2490
2491   ic = newiCode (op, left, right);
2492   IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2493
2494   /* if comparing anything greater than one byte
2495      and not a '==' || '!=' || '&&' || '||' (these
2496      will be inlined */
2497   if (getSize (ctype) > 1 &&
2498       op != EQ_OP &&
2499       op != NE_OP &&
2500       op != AND_OP &&
2501       op != OR_OP)
2502     ic->supportRtn = 1;
2503
2504   ADDTOCHAIN (ic);
2505   return IC_RESULT (ic);
2506 }
2507
2508 /*-----------------------------------------------------------------*/
2509 /* geniCodeUnary - for a a generic unary operation                 */
2510 /*-----------------------------------------------------------------*/
2511 operand *
2512 geniCodeUnary (operand * op, int oper)
2513 {
2514   iCode *ic = newiCode (oper, op, NULL);
2515
2516   IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2517   ADDTOCHAIN (ic);
2518   return IC_RESULT (ic);
2519 }
2520
2521 /*-----------------------------------------------------------------*/
2522 /* geniCodeConditional - geniCode for '?' ':' operation            */
2523 /*-----------------------------------------------------------------*/
2524 operand *
2525 geniCodeConditional (ast * tree)
2526 {
2527   iCode *ic;
2528   symbol *falseLabel = newiTempLabel (NULL);
2529   symbol *exitLabel = newiTempLabel (NULL);
2530   operand *cond = ast2iCode (tree->left);
2531   operand *true, *false, *result;
2532
2533   ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2534                           NULL, falseLabel);
2535   ADDTOCHAIN (ic);
2536
2537   true = ast2iCode (tree->right->left);
2538
2539   /* move the value to a new Operand */
2540   result = newiTempOperand (operandType (true), 0);
2541   geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2542
2543   /* generate an unconditional goto */
2544   geniCodeGoto (exitLabel);
2545
2546   /* now for the right side */
2547   geniCodeLabel (falseLabel);
2548
2549   false = ast2iCode (tree->right->right);
2550   geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2551
2552   /* create the exit label */
2553   geniCodeLabel (exitLabel);
2554
2555   return result;
2556 }
2557
2558 /*-----------------------------------------------------------------*/
2559 /* geniCodeAssign - generate code for assignment                   */
2560 /*-----------------------------------------------------------------*/
2561 operand *
2562 geniCodeAssign (operand * left, operand * right, int nosupdate)
2563 {
2564   iCode *ic;
2565   sym_link *ltype = operandType (left);
2566   sym_link *rtype = operandType (right);
2567
2568   if (!left->isaddr && !IS_ITEMP (left))
2569     {
2570       werror (E_LVALUE_REQUIRED, "assignment");
2571       return left;
2572     }
2573
2574   /* left is integral type and right is literal then
2575      check if the literal value is within bounds */
2576   if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2577     {
2578       int nbits = bitsForType (ltype);
2579       long v = operandLitValue (right);
2580
2581       if (v > ((LONG_LONG) 1 << nbits) && v > 0)
2582         werror (W_CONST_RANGE, " = operation");
2583     }
2584
2585   /* if the left & right type don't exactly match */
2586   /* if pointer set then make sure the check is
2587      done with the type & not the pointer */
2588   /* then cast rights type to left */
2589
2590   /* first check the type for pointer assignement */
2591   if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2592       checkType (ltype, rtype) < 0)
2593     {
2594       if (checkType (ltype->next, rtype) < 0)
2595         right = geniCodeCast (ltype->next, right, TRUE);
2596     }
2597   else if (checkType (ltype, rtype) < 0)
2598     right = geniCodeCast (ltype, right, TRUE);
2599
2600   /* if left is a true symbol & ! volatile
2601      create an assignment to temporary for
2602      the right & then assign this temporary
2603      to the symbol this is SSA . isn't it simple
2604      and folks have published mountains of paper on it */
2605   if (IS_TRUE_SYMOP (left) &&
2606       !isOperandVolatile (left, FALSE) &&
2607       isOperandGlobal (left))
2608     {
2609       symbol *sym = NULL;
2610
2611       if (IS_TRUE_SYMOP (right))
2612         sym = OP_SYMBOL (right);
2613       ic = newiCode ('=', NULL, right);
2614       IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2615       SPIL_LOC (right) = sym;
2616       ADDTOCHAIN (ic);
2617     }
2618
2619   ic = newiCode ('=', NULL, right);
2620   IC_RESULT (ic) = left;
2621   ADDTOCHAIN (ic);
2622
2623   /* if left isgptr flag is set then support
2624      routine will be required */
2625   if (left->isGptr)
2626     ic->supportRtn = 1;
2627
2628   ic->nosupdate = nosupdate;
2629   return left;
2630 }
2631
2632 /*-----------------------------------------------------------------*/
2633 /* geniCodeSEParms - generate code for side effecting fcalls       */
2634 /*-----------------------------------------------------------------*/
2635 static void 
2636 geniCodeSEParms (ast * parms)
2637 {
2638   if (!parms)
2639     return;
2640
2641   if (parms->type == EX_OP && parms->opval.op == PARAM)
2642     {
2643       geniCodeSEParms (parms->left);
2644       geniCodeSEParms (parms->right);
2645       return;
2646     }
2647
2648   /* hack don't like this but too lazy to think of
2649      something better */
2650   if (IS_ADDRESS_OF_OP (parms))
2651     parms->left->lvalue = 1;
2652
2653   if (IS_CAST_OP (parms) &&
2654       IS_PTR (parms->ftype) &&
2655       IS_ADDRESS_OF_OP (parms->right))
2656     parms->right->left->lvalue = 1;
2657
2658   parms->opval.oprnd =
2659     geniCodeRValue (ast2iCode (parms), FALSE);
2660
2661   parms->type = EX_OPERAND;
2662 }
2663
2664 /*-----------------------------------------------------------------*/
2665 /* geniCodeParms - generates parameters                            */
2666 /*-----------------------------------------------------------------*/
2667 static void 
2668 geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func)
2669 {
2670   iCode *ic;
2671   operand *pval;
2672
2673   if (!parms)
2674     return;
2675
2676   /* if this is a param node then do the left & right */
2677   if (parms->type == EX_OP && parms->opval.op == PARAM)
2678     {
2679       geniCodeParms (parms->left, stack, fetype, func);
2680       geniCodeParms (parms->right, stack, fetype, func);
2681       return;
2682     }
2683
2684   /* get the parameter value */
2685   if (parms->type == EX_OPERAND)
2686     pval = parms->opval.oprnd;
2687   else
2688     {
2689       /* maybe this else should go away ?? */
2690       /* hack don't like this but too lazy to think of
2691          something better */
2692       if (IS_ADDRESS_OF_OP (parms))
2693         parms->left->lvalue = 1;
2694
2695       if (IS_CAST_OP (parms) &&
2696           IS_PTR (parms->ftype) &&
2697           IS_ADDRESS_OF_OP (parms->right))
2698         parms->right->left->lvalue = 1;
2699
2700       pval = geniCodeRValue (ast2iCode (parms), FALSE);
2701     }
2702
2703   /* if register parm then make it a send */
2704   if (((parms->argSym && IS_REGPARM (parms->argSym->etype)) ||
2705        IS_REGPARM (parms->etype)) && !func->hasVargs)
2706     {
2707       ic = newiCode (SEND, pval, NULL);
2708       ADDTOCHAIN (ic);
2709     }
2710   else
2711     {
2712       /* now decide whether to push or assign */
2713       if (!(options.stackAuto || IS_RENT (fetype)))
2714         {
2715
2716           /* assign */
2717           operand *top = operandFromSymbol (parms->argSym);
2718           geniCodeAssign (top, pval, 1);
2719         }
2720       else
2721         {
2722           sym_link *p = operandType (pval);
2723           /* push */
2724           ic = newiCode (IPUSH, pval, NULL);
2725           ic->parmPush = 1;
2726           /* update the stack adjustment */
2727           *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2728           ADDTOCHAIN (ic);
2729         }
2730     }
2731
2732 }
2733
2734 /*-----------------------------------------------------------------*/
2735 /* geniCodeCall - generates temp code for calling                  */
2736 /*-----------------------------------------------------------------*/
2737 operand *
2738 geniCodeCall (operand * left, ast * parms)
2739 {
2740   iCode *ic;
2741   operand *result;
2742   sym_link *type, *etype;
2743   int stack = 0;
2744
2745   /* take care of parameters with side-effecting
2746      function calls in them, this is required to take care
2747      of overlaying function parameters */
2748   geniCodeSEParms (parms);
2749
2750   /* first the parameters */
2751   geniCodeParms (parms, &stack, getSpec (operandType (left)), OP_SYMBOL (left));
2752
2753   /* now call : if symbol then pcall */
2754   if (IS_OP_POINTER (left))
2755     ic = newiCode (PCALL, left, NULL);
2756   else
2757     ic = newiCode (CALL, left, NULL);
2758
2759   IC_ARGS (ic) = left->operand.symOperand->args;
2760   type = copyLinkChain (operandType (left)->next);
2761   etype = getSpec (type);
2762   SPEC_EXTR (etype) = 0;
2763   IC_RESULT (ic) = result = newiTempOperand (type, 1);
2764
2765   ADDTOCHAIN (ic);
2766
2767   /* stack adjustment after call */
2768   ic->parmBytes = stack;
2769
2770   return result;
2771 }
2772
2773 /*-----------------------------------------------------------------*/
2774 /* geniCodeReceive - generate intermediate code for "receive"      */
2775 /*-----------------------------------------------------------------*/
2776 static void 
2777 geniCodeReceive (value * args)
2778 {
2779   /* for all arguments that are passed in registers */
2780   while (args)
2781     {
2782
2783       if (IS_REGPARM (args->etype))
2784         {
2785           operand *opr = operandFromValue (args);
2786           operand *opl;
2787           symbol *sym = OP_SYMBOL (opr);
2788           iCode *ic;
2789
2790           /* we will use it after all optimizations
2791              and before liveRange calculation */
2792           if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2793             {
2794
2795               if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2796                   options.stackAuto == 0 &&
2797                   !IS_DS390_PORT)
2798                 {
2799                 }
2800               else
2801                 {
2802                   opl = newiTempOperand (args->type, 0);
2803                   sym->reqv = opl;
2804                   sym->reqv->key = sym->key;
2805                   OP_SYMBOL (sym->reqv)->key = sym->key;
2806                   OP_SYMBOL (sym->reqv)->isreqv = 1;
2807                   OP_SYMBOL (sym->reqv)->islocal = 0;
2808                   SPIL_LOC (sym->reqv) = sym;
2809                 }
2810             }
2811
2812           ic = newiCode (RECEIVE, NULL, NULL);
2813           currFunc->recvSize = getSize (sym->etype);
2814           IC_RESULT (ic) = opr;
2815           ADDTOCHAIN (ic);
2816         }
2817
2818       args = args->next;
2819     }
2820 }
2821
2822 /*-----------------------------------------------------------------*/
2823 /* geniCodeFunctionBody - create the function body                 */
2824 /*-----------------------------------------------------------------*/
2825 void 
2826 geniCodeFunctionBody (ast * tree)
2827 {
2828   iCode *ic;
2829   operand *func;
2830   sym_link *fetype;
2831   int savelineno;
2832
2833   /* reset the auto generation */
2834   /* numbers */
2835   iTempNum = 0;
2836   iTempLblNum = 0;
2837   operandKey = 0;
2838   iCodeKey = 0;
2839   func = ast2iCode (tree->left);
2840   fetype = getSpec (operandType (func));
2841
2842   savelineno = lineno;
2843   lineno = OP_SYMBOL (func)->lineDef;
2844   /* create an entry label */
2845   geniCodeLabel (entryLabel);
2846   lineno = savelineno;
2847
2848   /* create a proc icode */
2849   ic = newiCode (FUNCTION, func, NULL);
2850   /* if the function has parmas   then */
2851   /* save the parameters information    */
2852   ic->argLabel.args = tree->values.args;
2853   ic->lineno = OP_SYMBOL (func)->lineDef;
2854
2855   ADDTOCHAIN (ic);
2856
2857   /* for all parameters that are passed
2858      on registers add a "receive" */
2859   geniCodeReceive (tree->values.args);
2860
2861   /* generate code for the body */
2862   ast2iCode (tree->right);
2863
2864   /* create a label for return */
2865   geniCodeLabel (returnLabel);
2866
2867   /* now generate the end proc */
2868   ic = newiCode (ENDFUNCTION, func, NULL);
2869   ADDTOCHAIN (ic);
2870   return;
2871 }
2872
2873 /*-----------------------------------------------------------------*/
2874 /* geniCodeReturn - gen icode for 'return' statement               */
2875 /*-----------------------------------------------------------------*/
2876 void 
2877 geniCodeReturn (operand * op)
2878 {
2879   iCode *ic;
2880
2881   /* if the operand is present force an rvalue */
2882   if (op)
2883     op = geniCodeRValue (op, FALSE);
2884
2885   ic = newiCode (RETURN, op, NULL);
2886   ADDTOCHAIN (ic);
2887 }
2888
2889 /*-----------------------------------------------------------------*/
2890 /* geniCodeIfx - generates code for extended if statement          */
2891 /*-----------------------------------------------------------------*/
2892 void 
2893 geniCodeIfx (ast * tree)
2894 {
2895   iCode *ic;
2896   operand *condition = ast2iCode (tree->left);
2897   sym_link *cetype;
2898
2899   /* if condition is null then exit */
2900   if (!condition)
2901     goto exit;
2902   else
2903     condition = geniCodeRValue (condition, FALSE);
2904
2905   cetype = getSpec (operandType (condition));
2906   /* if the condition is a literal */
2907   if (IS_LITERAL (cetype))
2908     {
2909       if (floatFromVal (condition->operand.valOperand))
2910         {
2911           if (tree->trueLabel)
2912             geniCodeGoto (tree->trueLabel);
2913           else
2914             assert (1);
2915         }
2916       else
2917         {
2918           if (tree->falseLabel)
2919             geniCodeGoto (tree->falseLabel);
2920           else
2921             assert (1);
2922         }
2923       goto exit;
2924     }
2925
2926   if (tree->trueLabel)
2927     {
2928       ic = newiCodeCondition (condition,
2929                               tree->trueLabel,
2930                               NULL);
2931       ADDTOCHAIN (ic);
2932
2933       if (tree->falseLabel)
2934         geniCodeGoto (tree->falseLabel);
2935     }
2936   else
2937     {
2938       ic = newiCodeCondition (condition,
2939                               NULL,
2940                               tree->falseLabel);
2941       ADDTOCHAIN (ic);
2942     }
2943
2944 exit:
2945   ast2iCode (tree->right);
2946 }
2947
2948 /*-----------------------------------------------------------------*/
2949 /* geniCodeJumpTable - tries to create a jump table for switch     */
2950 /*-----------------------------------------------------------------*/
2951 int 
2952 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
2953 {
2954   int min = 0, max = 0, t, cnt = 0;
2955   value *vch;
2956   iCode *ic;
2957   operand *boundary;
2958   symbol *falseLabel;
2959   set *labels = NULL;
2960
2961   if (!tree || !caseVals)
2962     return 0;
2963
2964   /* the criteria for creating a jump table is */
2965   /* all integer numbers between the maximum & minimum must */
2966   /* be present , the maximum value should not exceed 255 */
2967   min = max = (int) floatFromVal (vch = caseVals);
2968   sprintf (buffer, "_case_%d_%d",
2969            tree->values.switchVals.swNum,
2970            min);
2971   addSet (&labels, newiTempLabel (buffer));
2972
2973   /* if there is only one case value then no need */
2974   if (!(vch = vch->next))
2975     return 0;
2976
2977   while (vch)
2978     {
2979       if (((t = (int) floatFromVal (vch)) - max) != 1)
2980         return 0;
2981       sprintf (buffer, "_case_%d_%d",
2982                tree->values.switchVals.swNum,
2983                t);
2984       addSet (&labels, newiTempLabel (buffer));
2985       max = t;
2986       cnt++;
2987       vch = vch->next;
2988     }
2989
2990   /* if the number of case statements <= 2 then */
2991   /* it is not economical to create the jump table */
2992   /* since two compares are needed for boundary conditions */
2993   if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
2994     return 0;
2995
2996   if (tree->values.switchVals.swDefault)
2997     sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
2998   else
2999     sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3000
3001   falseLabel = newiTempLabel (buffer);
3002
3003   /* so we can create a jumptable */
3004   /* first we rule out the boundary conditions */
3005   /* if only optimization says so */
3006   if (!optimize.noJTabBoundary)
3007     {
3008       sym_link *cetype = getSpec (operandType (cond));
3009       /* no need to check the lower bound if
3010          the condition is unsigned & minimum value is zero */
3011       if (!(min == 0 && SPEC_USIGN (cetype)))
3012         {
3013           boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3014           ic = newiCodeCondition (boundary, falseLabel, NULL);
3015           ADDTOCHAIN (ic);
3016         }
3017
3018       /* now for upper bounds */
3019       boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3020       ic = newiCodeCondition (boundary, falseLabel, NULL);
3021       ADDTOCHAIN (ic);
3022     }
3023
3024   /* if the min is not zero then we no make it zero */
3025   if (min)
3026     {
3027       cond = geniCodeSubtract (cond, operandFromLit (min));
3028       setOperandType (cond, UCHARTYPE);
3029     }
3030
3031   /* now create the jumptable */
3032   ic = newiCode (JUMPTABLE, NULL, NULL);
3033   IC_JTCOND (ic) = cond;
3034   IC_JTLABELS (ic) = labels;
3035   ADDTOCHAIN (ic);
3036   return 1;
3037 }
3038
3039 /*-----------------------------------------------------------------*/
3040 /* geniCodeSwitch - changes a switch to a if statement             */
3041 /*-----------------------------------------------------------------*/
3042 void 
3043 geniCodeSwitch (ast * tree)
3044 {
3045   iCode *ic;
3046   operand *cond = geniCodeRValue (ast2iCode (tree->left), FALSE);
3047   value *caseVals = tree->values.switchVals.swVals;
3048   symbol *trueLabel, *falseLabel;
3049
3050   /* if we can make this a jump table */
3051   if (geniCodeJumpTable (cond, caseVals, tree))
3052     goto jumpTable;             /* no need for the comparison */
3053
3054   /* for the cases defined do */
3055   while (caseVals)
3056     {
3057
3058       operand *compare = geniCodeLogic (cond,
3059                                         operandFromValue (caseVals),
3060                                         EQ_OP);
3061
3062       sprintf (buffer, "_case_%d_%d",
3063                tree->values.switchVals.swNum,
3064                (int) floatFromVal (caseVals));
3065       trueLabel = newiTempLabel (buffer);
3066
3067       ic = newiCodeCondition (compare, trueLabel, NULL);
3068       ADDTOCHAIN (ic);
3069       caseVals = caseVals->next;
3070     }
3071
3072
3073
3074   /* if default is present then goto break else break */
3075   if (tree->values.switchVals.swDefault)
3076     sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3077   else
3078     sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3079
3080   falseLabel = newiTempLabel (buffer);
3081   geniCodeGoto (falseLabel);
3082
3083 jumpTable:
3084   ast2iCode (tree->right);
3085 }
3086
3087 /*-----------------------------------------------------------------*/
3088 /* geniCodeInline - intermediate code for inline assembler         */
3089 /*-----------------------------------------------------------------*/
3090 static void 
3091 geniCodeInline (ast * tree)
3092 {
3093   iCode *ic;
3094
3095   ic = newiCode (INLINEASM, NULL, NULL);
3096   IC_INLINE (ic) = tree->values.inlineasm;
3097   ADDTOCHAIN (ic);
3098 }
3099
3100 /*-----------------------------------------------------------------*/
3101 /* ast2iCode - creates an icodeList from an ast                    */
3102 /*-----------------------------------------------------------------*/
3103 operand *
3104 ast2iCode (ast * tree)
3105 {
3106   operand *left = NULL;
3107   operand *right = NULL;
3108
3109   if (!tree)
3110     return NULL;
3111
3112   /* set the global variables for filename & line number */
3113   if (tree->filename)
3114     filename = tree->filename;
3115   if (tree->lineno)
3116     lineno = tree->lineno;
3117   if (tree->block)
3118     block = tree->block;
3119   if (tree->level)
3120     scopeLevel = tree->level;
3121
3122   if (tree->type == EX_VALUE)
3123     return operandFromValue (tree->opval.val);
3124
3125   if (tree->type == EX_LINK)
3126     return operandFromLink (tree->opval.lnk);
3127
3128   /* if we find a nullop */
3129   if (tree->type == EX_OP &&
3130       (tree->opval.op == NULLOP ||
3131        tree->opval.op == BLOCK))
3132     {
3133       ast2iCode (tree->left);
3134       ast2iCode (tree->right);
3135       return NULL;
3136     }
3137
3138   /* special cases for not evaluating */
3139   if (tree->opval.op != ':' &&
3140       tree->opval.op != '?' &&
3141       tree->opval.op != CALL &&
3142       tree->opval.op != IFX &&
3143       tree->opval.op != LABEL &&
3144       tree->opval.op != GOTO &&
3145       tree->opval.op != SWITCH &&
3146       tree->opval.op != FUNCTION &&
3147       tree->opval.op != INLINEASM)
3148     {
3149
3150       if (IS_ASSIGN_OP (tree->opval.op) ||
3151           IS_DEREF_OP (tree) ||
3152           (tree->opval.op == '&' && !tree->right) ||
3153           tree->opval.op == PTR_OP)
3154         {
3155           lvaluereq++;
3156           if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3157               (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3158             {
3159               int olvr = lvaluereq;
3160               lvaluereq = 0;
3161               left = operandFromAst (tree->left);
3162               lvaluereq = olvr - 1;
3163             }
3164           else
3165             {
3166               left = operandFromAst (tree->left);
3167               lvaluereq--;
3168             }
3169           if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3170             left = geniCodeRValue (left, TRUE);
3171         }
3172       else
3173         {
3174           left = operandFromAst (tree->left);
3175         }
3176       if (tree->opval.op == INC_OP ||
3177           tree->opval.op == DEC_OP)
3178         {
3179           lvaluereq++;
3180           right = operandFromAst (tree->right);
3181           lvaluereq--;
3182         }
3183       else
3184         {
3185           right = operandFromAst (tree->right);
3186         }
3187     }
3188
3189   /* now depending on the type of operand */
3190   /* this will be a biggy                 */
3191   switch (tree->opval.op)
3192     {
3193
3194     case '[':                   /* array operation */
3195       {
3196         sym_link *ltype = operandType (left);
3197         left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3198         right = geniCodeRValue (right, TRUE);
3199       }
3200
3201       return geniCodeArray (left, right);
3202
3203     case '.':                   /* structure dereference */
3204       if (IS_PTR (operandType (left)))
3205         left = geniCodeRValue (left, TRUE);
3206       else
3207         left = geniCodeRValue (left, FALSE);
3208
3209       return geniCodeStruct (left, right, tree->lvalue);
3210
3211     case PTR_OP:                /* structure pointer dereference */
3212       {
3213         sym_link *pType;
3214         pType = operandType (left);
3215         left = geniCodeRValue (left, TRUE);
3216
3217         setOClass (pType, getSpec (operandType (left)));
3218       }
3219
3220       return geniCodeStruct (left, right, tree->lvalue);
3221
3222     case INC_OP:                /* increment operator */
3223       if (left)
3224         return geniCodePostInc (left);
3225       else
3226         return geniCodePreInc (right);
3227
3228     case DEC_OP:                /* decrement operator */
3229       if (left)
3230         return geniCodePostDec (left);
3231       else
3232         return geniCodePreDec (right);
3233
3234     case '&':                   /* bitwise and or address of operator */
3235       if (right)
3236         {                       /* this is a bitwise operator   */
3237           left = geniCodeRValue (left, FALSE);
3238           right = geniCodeRValue (right, FALSE);
3239           return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3240         }
3241       else
3242         return geniCodeAddressOf (left);
3243
3244     case '|':                   /* bitwise or & xor */
3245     case '^':
3246       return geniCodeBitwise (geniCodeRValue (left, FALSE),
3247                               geniCodeRValue (right, FALSE),
3248                               tree->opval.op,
3249                               tree->ftype);
3250
3251     case '/':
3252       return geniCodeDivision (geniCodeRValue (left, FALSE),
3253                                geniCodeRValue (right, FALSE));
3254
3255     case '%':
3256       return geniCodeModulus (geniCodeRValue (left, FALSE),
3257                               geniCodeRValue (right, FALSE));
3258     case '*':
3259       if (right)
3260         return geniCodeMultiply (geniCodeRValue (left, FALSE),
3261                                  geniCodeRValue (right, FALSE), FALSE,IS_INT(tree->ftype));
3262       else
3263         return geniCodeDerefPtr (geniCodeRValue (left, FALSE));
3264
3265     case '-':
3266       if (right)
3267         return geniCodeSubtract (geniCodeRValue (left, FALSE),
3268                                  geniCodeRValue (right, FALSE));
3269       else
3270         return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3271
3272     case '+':
3273       if (right)
3274         return geniCodeAdd (geniCodeRValue (left, FALSE),
3275                             geniCodeRValue (right, FALSE));
3276       else
3277         return geniCodeRValue (left, FALSE);    /* unary '+' has no meaning */
3278
3279     case LEFT_OP:
3280       return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3281                                 geniCodeRValue (right, FALSE));
3282
3283     case RIGHT_OP:
3284       return geniCodeRightShift (geniCodeRValue (left, FALSE),
3285                                  geniCodeRValue (right, FALSE));
3286     case CAST:
3287       return geniCodeCast (operandType (left),
3288                            geniCodeRValue (right, FALSE), FALSE);
3289
3290     case '~':
3291     case '!':
3292     case RRC:
3293     case RLC:
3294       return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3295
3296     case GETHBIT:
3297       {
3298         operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3299         setOperandType (op, UCHARTYPE);
3300         return op;
3301       }
3302     case '>':
3303     case '<':
3304     case LE_OP:
3305     case GE_OP:
3306     case EQ_OP:
3307     case NE_OP:
3308     case AND_OP:
3309     case OR_OP:
3310       return geniCodeLogic (geniCodeRValue (left, FALSE),
3311                             geniCodeRValue (right, FALSE),
3312                             tree->opval.op);
3313     case '?':
3314       return geniCodeConditional (tree);
3315
3316     case SIZEOF:
3317       return operandFromLit (getSize (tree->right->ftype));
3318
3319     case '=':
3320       {
3321         sym_link *rtype = operandType (right);
3322         sym_link *ltype = operandType (left);
3323         if (IS_PTR (rtype) && IS_ITEMP (right)
3324             && right->isaddr && checkType (rtype->next, ltype) == 1)
3325           right = geniCodeRValue (right, TRUE);
3326         else
3327           right = geniCodeRValue (right, FALSE);
3328
3329         geniCodeAssign (left, right, 0);
3330         return right;
3331       }
3332     case MUL_ASSIGN:
3333       return
3334         geniCodeAssign (left,
3335                 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3336                                                   FALSE),
3337                                   geniCodeRValue (right, FALSE), FALSE,FALSE), 0);
3338
3339     case DIV_ASSIGN:
3340       return
3341         geniCodeAssign (left,
3342                 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3343                                                   FALSE),
3344                                   geniCodeRValue (right, FALSE)), 0);
3345     case MOD_ASSIGN:
3346       return
3347         geniCodeAssign (left,
3348                  geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3349                                                   FALSE),
3350                                   geniCodeRValue (right, FALSE)), 0);
3351     case ADD_ASSIGN:
3352       {
3353         sym_link *rtype = operandType (right);
3354         sym_link *ltype = operandType (left);
3355         if (IS_PTR (rtype) && IS_ITEMP (right)
3356             && right->isaddr && checkType (rtype->next, ltype) == 1)
3357           right = geniCodeRValue (right, TRUE);
3358         else
3359           right = geniCodeRValue (right, FALSE);
3360
3361
3362         return geniCodeAssign (left,
3363                      geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3364                                                   FALSE),
3365                                   right), 0);
3366       }
3367     case SUB_ASSIGN:
3368       {
3369         sym_link *rtype = operandType (right);
3370         sym_link *ltype = operandType (left);
3371         if (IS_PTR (rtype) && IS_ITEMP (right)
3372             && right->isaddr && checkType (rtype->next, ltype) == 1)
3373           {
3374             right = geniCodeRValue (right, TRUE);
3375           }
3376         else
3377           {
3378             right = geniCodeRValue (right, FALSE);
3379           }
3380         return
3381           geniCodeAssign (left,
3382                 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3383                                                   FALSE),
3384                                   right), 0);
3385       }
3386     case LEFT_ASSIGN:
3387       return
3388         geniCodeAssign (left,
3389                 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3390                                                    ,FALSE),
3391                                    geniCodeRValue (right, FALSE)), 0);
3392     case RIGHT_ASSIGN:
3393       return
3394         geniCodeAssign (left,
3395                geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3396                                                    ,FALSE),
3397                                    geniCodeRValue (right, FALSE)), 0);
3398     case AND_ASSIGN:
3399       return
3400         geniCodeAssign (left,
3401                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3402                                                   FALSE),
3403                                   geniCodeRValue (right, FALSE),
3404                                   BITWISEAND,
3405                                   operandType (left)), 0);
3406     case XOR_ASSIGN:
3407       return
3408         geniCodeAssign (left,
3409                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3410                                                   FALSE),
3411                                   geniCodeRValue (right, FALSE),
3412                                   '^',
3413                                   operandType (left)), 0);
3414     case OR_ASSIGN:
3415       return
3416         geniCodeAssign (left,
3417                   geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3418                                                    ,FALSE),
3419                                    geniCodeRValue (right, FALSE),
3420                                    '|',
3421                                    operandType (left)), 0);
3422     case ',':
3423       return geniCodeRValue (right, FALSE);
3424
3425     case CALL:
3426       return geniCodeCall (ast2iCode (tree->left),
3427                            tree->right);
3428     case LABEL:
3429       geniCodeLabel (ast2iCode (tree->left)->operand.symOperand);
3430       return ast2iCode (tree->right);
3431
3432     case GOTO:
3433       geniCodeGoto (ast2iCode (tree->left)->operand.symOperand);
3434       return ast2iCode (tree->right);
3435
3436     case FUNCTION:
3437       geniCodeFunctionBody (tree);
3438       return NULL;
3439
3440     case RETURN:
3441       geniCodeReturn (right);
3442       return NULL;
3443
3444     case IFX:
3445       geniCodeIfx (tree);
3446       return NULL;
3447
3448     case SWITCH:
3449       geniCodeSwitch (tree);
3450       return NULL;
3451
3452     case INLINEASM:
3453       geniCodeInline (tree);
3454       return NULL;
3455     }
3456
3457   return NULL;
3458 }
3459
3460 /*-----------------------------------------------------------------*/
3461 /* reverseICChain - gets from the list and creates a linkedlist    */
3462 /*-----------------------------------------------------------------*/
3463 iCode *
3464 reverseiCChain ()
3465 {
3466   iCode *loop = NULL;
3467   iCode *prev = NULL;
3468
3469   while ((loop = getSet (&iCodeChain)))
3470     {
3471       loop->next = prev;
3472       if (prev)
3473         prev->prev = loop;
3474       prev = loop;
3475     }
3476
3477   return prev;
3478 }
3479
3480
3481 /*-----------------------------------------------------------------*/
3482 /* iCodeFromAst - given an ast will convert it to iCode            */
3483 /*-----------------------------------------------------------------*/
3484 iCode *
3485 iCodeFromAst (ast * tree)
3486 {
3487   returnLabel = newiTempLabel ("_return");
3488   entryLabel = newiTempLabel ("_entry");
3489   ast2iCode (tree);
3490   return reverseiCChain ();
3491 }