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