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