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