__rlrr array lacking extern
[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 (E_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       int nbits = bitsForType (ltype);
2502       long v = (long) operandLitValue (right);
2503
2504       if (v >= ((LONG_LONG) 1 << nbits) && v > 0)
2505         werror (W_CONST_RANGE, " = operation");
2506     }
2507
2508   /* if the left & right type don't exactly match */
2509   /* if pointer set then make sure the check is
2510      done with the type & not the pointer */
2511   /* then cast rights type to left */
2512
2513   /* first check the type for pointer assignement */
2514   if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2515       compareType (ltype, rtype) < 0)
2516     {
2517       if (compareType (ltype->next, rtype) < 0)
2518         right = geniCodeCast (ltype->next, right, TRUE);
2519     }
2520   else if (compareType (ltype, rtype) < 0)
2521     right = geniCodeCast (ltype, right, TRUE);
2522
2523   /* if left is a true symbol & ! volatile
2524      create an assignment to temporary for
2525      the right & then assign this temporary
2526      to the symbol this is SSA . isn't it simple
2527      and folks have published mountains of paper on it */
2528   if (IS_TRUE_SYMOP (left) &&
2529       !isOperandVolatile (left, FALSE) &&
2530       isOperandGlobal (left))
2531     {
2532       symbol *sym = NULL;
2533
2534       if (IS_TRUE_SYMOP (right))
2535         sym = OP_SYMBOL (right);
2536       ic = newiCode ('=', NULL, right);
2537       IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2538       SPIL_LOC (right) = sym;
2539       ADDTOCHAIN (ic);
2540     }
2541
2542   ic = newiCode ('=', NULL, right);
2543   IC_RESULT (ic) = left;
2544   ADDTOCHAIN (ic);
2545
2546   /* if left isgptr flag is set then support
2547      routine will be required */
2548   if (left->isGptr)
2549     ic->supportRtn = 1;
2550
2551   ic->nosupdate = nosupdate;
2552   return left;
2553 }
2554
2555 /*-----------------------------------------------------------------*/
2556 /* geniCodeSEParms - generate code for side effecting fcalls       */
2557 /*-----------------------------------------------------------------*/
2558 static void 
2559 geniCodeSEParms (ast * parms,int lvl)
2560 {
2561   if (!parms)
2562     return;
2563
2564   if (parms->type == EX_OP && parms->opval.op == PARAM)
2565     {
2566       geniCodeSEParms (parms->left,lvl);
2567       geniCodeSEParms (parms->right,lvl);
2568       return;
2569     }
2570
2571   /* hack don't like this but too lazy to think of
2572      something better */
2573   if (IS_ADDRESS_OF_OP (parms))
2574     parms->left->lvalue = 1;
2575
2576   if (IS_CAST_OP (parms) &&
2577       IS_PTR (parms->ftype) &&
2578       IS_ADDRESS_OF_OP (parms->right))
2579     parms->right->left->lvalue = 1;
2580
2581   parms->opval.oprnd =
2582     geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2583
2584   parms->type = EX_OPERAND;
2585 }
2586
2587 /*-----------------------------------------------------------------*/
2588 /* geniCodeParms - generates parameters                            */
2589 /*-----------------------------------------------------------------*/
2590 static void 
2591 geniCodeParms (ast * parms, int *stack, sym_link * fetype, symbol * func,int lvl)
2592 {
2593   iCode *ic;
2594   operand *pval;
2595
2596   if (!parms)
2597     return;
2598
2599   /* if this is a param node then do the left & right */
2600   if (parms->type == EX_OP && parms->opval.op == PARAM)
2601     {
2602       geniCodeParms (parms->left, stack, fetype, func,lvl);
2603       geniCodeParms (parms->right, stack, fetype, func,lvl);
2604       return;
2605     }
2606
2607   /* get the parameter value */
2608   if (parms->type == EX_OPERAND)
2609     pval = parms->opval.oprnd;
2610   else
2611     {
2612       /* maybe this else should go away ?? */
2613       /* hack don't like this but too lazy to think of
2614          something better */
2615       if (IS_ADDRESS_OF_OP (parms))
2616         parms->left->lvalue = 1;
2617
2618       if (IS_CAST_OP (parms) &&
2619           IS_PTR (parms->ftype) &&
2620           IS_ADDRESS_OF_OP (parms->right))
2621         parms->right->left->lvalue = 1;
2622
2623       pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2624     }
2625
2626   /* if register parm then make it a send */
2627   if (((parms->argSym && IS_REGPARM (parms->argSym->etype)) ||
2628        IS_REGPARM (parms->etype)) && !func->hasVargs)
2629     {
2630       ic = newiCode (SEND, pval, NULL);
2631       ADDTOCHAIN (ic);
2632     }
2633   else
2634     {
2635       /* now decide whether to push or assign */
2636       if (!(options.stackAuto || IS_RENT (fetype)))
2637         {
2638
2639           /* assign */
2640           operand *top = operandFromSymbol (parms->argSym);
2641           geniCodeAssign (top, pval, 1);
2642         }
2643       else
2644         {
2645           sym_link *p = operandType (pval);
2646           /* push */
2647           ic = newiCode (IPUSH, pval, NULL);
2648           ic->parmPush = 1;
2649           /* update the stack adjustment */
2650           *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2651           ADDTOCHAIN (ic);
2652         }
2653     }
2654
2655 }
2656
2657 /*-----------------------------------------------------------------*/
2658 /* geniCodeCall - generates temp code for calling                  */
2659 /*-----------------------------------------------------------------*/
2660 operand *
2661 geniCodeCall (operand * left, ast * parms,int lvl)
2662 {
2663   iCode *ic;
2664   operand *result;
2665   sym_link *type, *etype;
2666   int stack = 0;
2667
2668   if (!IS_FUNC(OP_SYMBOL(left)->type) && 
2669       !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2670     werror (E_FUNCTION_EXPECTED);
2671     return NULL;
2672   }
2673
2674   /* take care of parameters with side-effecting
2675      function calls in them, this is required to take care
2676      of overlaying function parameters */
2677   geniCodeSEParms (parms,lvl);
2678
2679   /* first the parameters */
2680   geniCodeParms (parms, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2681
2682   /* now call : if symbol then pcall */
2683   if (IS_OP_POINTER (left) || IS_ITEMP(left))
2684     ic = newiCode (PCALL, left, NULL);
2685   else
2686     ic = newiCode (CALL, left, NULL);
2687
2688   IC_ARGS (ic) = left->operand.symOperand->args;
2689   type = copyLinkChain (operandType (left)->next);
2690   etype = getSpec (type);
2691   SPEC_EXTR (etype) = 0;
2692   IC_RESULT (ic) = result = newiTempOperand (type, 1);
2693
2694   ADDTOCHAIN (ic);
2695
2696   /* stack adjustment after call */
2697   ic->parmBytes = stack;
2698
2699   return result;
2700 }
2701
2702 /*-----------------------------------------------------------------*/
2703 /* geniCodeReceive - generate intermediate code for "receive"      */
2704 /*-----------------------------------------------------------------*/
2705 static void 
2706 geniCodeReceive (value * args)
2707 {
2708   /* for all arguments that are passed in registers */
2709   while (args)
2710     {
2711
2712       if (IS_REGPARM (args->etype))
2713         {
2714           operand *opr = operandFromValue (args);
2715           operand *opl;
2716           symbol *sym = OP_SYMBOL (opr);
2717           iCode *ic;
2718
2719           /* we will use it after all optimizations
2720              and before liveRange calculation */
2721           if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2722             {
2723
2724               if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2725                   options.stackAuto == 0 &&
2726                   /* !TARGET_IS_DS390) */
2727                   (!(options.model == MODEL_FLAT24)) )
2728                 {
2729                 }
2730               else
2731                 {
2732                   opl = newiTempOperand (args->type, 0);
2733                   sym->reqv = opl;
2734                   sym->reqv->key = sym->key;
2735                   OP_SYMBOL (sym->reqv)->key = sym->key;
2736                   OP_SYMBOL (sym->reqv)->isreqv = 1;
2737                   OP_SYMBOL (sym->reqv)->islocal = 0;
2738                   SPIL_LOC (sym->reqv) = sym;
2739                 }
2740             }
2741
2742           ic = newiCode (RECEIVE, NULL, NULL);
2743           currFunc->recvSize = getSize (sym->etype);
2744           IC_RESULT (ic) = opr;
2745           ADDTOCHAIN (ic);
2746         }
2747
2748       args = args->next;
2749     }
2750 }
2751
2752 /*-----------------------------------------------------------------*/
2753 /* geniCodeFunctionBody - create the function body                 */
2754 /*-----------------------------------------------------------------*/
2755 void 
2756 geniCodeFunctionBody (ast * tree,int lvl)
2757 {
2758   iCode *ic;
2759   operand *func;
2760   sym_link *fetype;
2761   int savelineno;
2762
2763   /* reset the auto generation */
2764   /* numbers */
2765   iTempNum = 0;
2766   iTempLblNum = 0;
2767   operandKey = 0;
2768   iCodeKey = 0;
2769   func = ast2iCode (tree->left,lvl+1);
2770   fetype = getSpec (operandType (func));
2771
2772   savelineno = lineno;
2773   lineno = OP_SYMBOL (func)->lineDef;
2774   /* create an entry label */
2775   geniCodeLabel (entryLabel);
2776   lineno = savelineno;
2777
2778   /* create a proc icode */
2779   ic = newiCode (FUNCTION, func, NULL);
2780   /* if the function has parmas   then */
2781   /* save the parameters information    */
2782   ic->argLabel.args = tree->values.args;
2783   ic->lineno = OP_SYMBOL (func)->lineDef;
2784
2785   ADDTOCHAIN (ic);
2786
2787   /* for all parameters that are passed
2788      on registers add a "receive" */
2789   geniCodeReceive (tree->values.args);
2790
2791   /* generate code for the body */
2792   ast2iCode (tree->right,lvl+1);
2793
2794   /* create a label for return */
2795   geniCodeLabel (returnLabel);
2796
2797   /* now generate the end proc */
2798   ic = newiCode (ENDFUNCTION, func, NULL);
2799   ADDTOCHAIN (ic);
2800   return;
2801 }
2802
2803 /*-----------------------------------------------------------------*/
2804 /* geniCodeReturn - gen icode for 'return' statement               */
2805 /*-----------------------------------------------------------------*/
2806 void 
2807 geniCodeReturn (operand * op)
2808 {
2809   iCode *ic;
2810
2811   /* if the operand is present force an rvalue */
2812   if (op)
2813     op = geniCodeRValue (op, FALSE);
2814
2815   ic = newiCode (RETURN, op, NULL);
2816   ADDTOCHAIN (ic);
2817 }
2818
2819 /*-----------------------------------------------------------------*/
2820 /* geniCodeIfx - generates code for extended if statement          */
2821 /*-----------------------------------------------------------------*/
2822 void 
2823 geniCodeIfx (ast * tree,int lvl)
2824 {
2825   iCode *ic;
2826   operand *condition = ast2iCode (tree->left,lvl+1);
2827   sym_link *cetype;
2828
2829   /* if condition is null then exit */
2830   if (!condition)
2831     goto exit;
2832   else
2833     condition = geniCodeRValue (condition, FALSE);
2834
2835   cetype = getSpec (operandType (condition));
2836   /* if the condition is a literal */
2837   if (IS_LITERAL (cetype))
2838     {
2839       if (floatFromVal (condition->operand.valOperand))
2840         {
2841           if (tree->trueLabel)
2842             geniCodeGoto (tree->trueLabel);
2843           else
2844             assert (1);
2845         }
2846       else
2847         {
2848           if (tree->falseLabel)
2849             geniCodeGoto (tree->falseLabel);
2850           else
2851             assert (1);
2852         }
2853       goto exit;
2854     }
2855
2856   if (tree->trueLabel)
2857     {
2858       ic = newiCodeCondition (condition,
2859                               tree->trueLabel,
2860                               NULL);
2861       ADDTOCHAIN (ic);
2862
2863       if (tree->falseLabel)
2864         geniCodeGoto (tree->falseLabel);
2865     }
2866   else
2867     {
2868       ic = newiCodeCondition (condition,
2869                               NULL,
2870                               tree->falseLabel);
2871       ADDTOCHAIN (ic);
2872     }
2873
2874 exit:
2875   ast2iCode (tree->right,lvl+1);
2876 }
2877
2878 /*-----------------------------------------------------------------*/
2879 /* geniCodeJumpTable - tries to create a jump table for switch     */
2880 /*-----------------------------------------------------------------*/
2881 int 
2882 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
2883 {
2884   int min = 0, max = 0, t, cnt = 0;
2885   value *vch;
2886   iCode *ic;
2887   operand *boundary;
2888   symbol *falseLabel;
2889   set *labels = NULL;
2890
2891   if (!tree || !caseVals)
2892     return 0;
2893
2894   /* the criteria for creating a jump table is */
2895   /* all integer numbers between the maximum & minimum must */
2896   /* be present , the maximum value should not exceed 255 */
2897   min = max = (int) floatFromVal (vch = caseVals);
2898   sprintf (buffer, "_case_%d_%d",
2899            tree->values.switchVals.swNum,
2900            min);
2901   addSet (&labels, newiTempLabel (buffer));
2902
2903   /* if there is only one case value then no need */
2904   if (!(vch = vch->next))
2905     return 0;
2906
2907   while (vch)
2908     {
2909       if (((t = (int) floatFromVal (vch)) - max) != 1)
2910         return 0;
2911       sprintf (buffer, "_case_%d_%d",
2912                tree->values.switchVals.swNum,
2913                t);
2914       addSet (&labels, newiTempLabel (buffer));
2915       max = t;
2916       cnt++;
2917       vch = vch->next;
2918     }
2919
2920   /* if the number of case statements <= 2 then */
2921   /* it is not economical to create the jump table */
2922   /* since two compares are needed for boundary conditions */
2923   if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
2924     return 0;
2925
2926   if (tree->values.switchVals.swDefault)
2927     sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
2928   else
2929     sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
2930
2931   falseLabel = newiTempLabel (buffer);
2932
2933   /* so we can create a jumptable */
2934   /* first we rule out the boundary conditions */
2935   /* if only optimization says so */
2936   if (!optimize.noJTabBoundary)
2937     {
2938       sym_link *cetype = getSpec (operandType (cond));
2939       /* no need to check the lower bound if
2940          the condition is unsigned & minimum value is zero */
2941       if (!(min == 0 && SPEC_USIGN (cetype)))
2942         {
2943           boundary = geniCodeLogic (cond, operandFromLit (min), '<');
2944           ic = newiCodeCondition (boundary, falseLabel, NULL);
2945           ADDTOCHAIN (ic);
2946         }
2947
2948       /* now for upper bounds */
2949       boundary = geniCodeLogic (cond, operandFromLit (max), '>');
2950       ic = newiCodeCondition (boundary, falseLabel, NULL);
2951       ADDTOCHAIN (ic);
2952     }
2953
2954   /* if the min is not zero then we no make it zero */
2955   if (min)
2956     {
2957       cond = geniCodeSubtract (cond, operandFromLit (min));
2958       setOperandType (cond, UCHARTYPE);
2959     }
2960
2961   /* now create the jumptable */
2962   ic = newiCode (JUMPTABLE, NULL, NULL);
2963   IC_JTCOND (ic) = cond;
2964   IC_JTLABELS (ic) = labels;
2965   ADDTOCHAIN (ic);
2966   return 1;
2967 }
2968
2969 /*-----------------------------------------------------------------*/
2970 /* geniCodeSwitch - changes a switch to a if statement             */
2971 /*-----------------------------------------------------------------*/
2972 void 
2973 geniCodeSwitch (ast * tree,int lvl)
2974 {
2975   iCode *ic;
2976   operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
2977   value *caseVals = tree->values.switchVals.swVals;
2978   symbol *trueLabel, *falseLabel;
2979
2980   /* if we can make this a jump table */
2981   if (geniCodeJumpTable (cond, caseVals, tree))
2982     goto jumpTable;             /* no need for the comparison */
2983
2984   /* for the cases defined do */
2985   while (caseVals)
2986     {
2987
2988       operand *compare = geniCodeLogic (cond,
2989                                         operandFromValue (caseVals),
2990                                         EQ_OP);
2991
2992       sprintf (buffer, "_case_%d_%d",
2993                tree->values.switchVals.swNum,
2994                (int) floatFromVal (caseVals));
2995       trueLabel = newiTempLabel (buffer);
2996
2997       ic = newiCodeCondition (compare, trueLabel, NULL);
2998       ADDTOCHAIN (ic);
2999       caseVals = caseVals->next;
3000     }
3001
3002
3003
3004   /* if default is present then goto break else break */
3005   if (tree->values.switchVals.swDefault)
3006     sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
3007   else
3008     sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
3009
3010   falseLabel = newiTempLabel (buffer);
3011   geniCodeGoto (falseLabel);
3012
3013 jumpTable:
3014   ast2iCode (tree->right,lvl+1);
3015 }
3016
3017 /*-----------------------------------------------------------------*/
3018 /* geniCodeInline - intermediate code for inline assembler         */
3019 /*-----------------------------------------------------------------*/
3020 static void 
3021 geniCodeInline (ast * tree)
3022 {
3023   iCode *ic;
3024
3025   ic = newiCode (INLINEASM, NULL, NULL);
3026   IC_INLINE (ic) = tree->values.inlineasm;
3027   ADDTOCHAIN (ic);
3028 }
3029
3030 /*-----------------------------------------------------------------*/
3031 /* geniCodeArrayInit - intermediate code for array initializer     */
3032 /*-----------------------------------------------------------------*/
3033 static void 
3034 geniCodeArrayInit (ast * tree, operand *array)
3035 {
3036   iCode *ic;
3037
3038   if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3039     ic = newiCode (ARRAYINIT, array, NULL);
3040     IC_ARRAYILIST (ic) = tree->values.constlist;
3041   } else {
3042     operand *left=newOperand(), *right=newOperand();
3043     left->type=right->type=SYMBOL;
3044     OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3045     OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3046     ic = newiCode (ARRAYINIT, left, right);
3047   }
3048   ADDTOCHAIN (ic);
3049 }
3050
3051 /*-----------------------------------------------------------------*/
3052 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some      */
3053 /* particular case. Ie : assigning or dereferencing array or ptr   */
3054 /*-----------------------------------------------------------------*/
3055 set * lvaluereqSet = NULL;
3056 typedef struct lvalItem
3057   {
3058     int req;
3059     int lvl;
3060   }
3061 lvalItem;
3062
3063 /*-----------------------------------------------------------------*/
3064 /* addLvaluereq - add a flag for lvalreq for current ast level     */
3065 /*-----------------------------------------------------------------*/
3066 void addLvaluereq(int lvl)
3067 {
3068   lvalItem * lpItem = (lvalItem *)Safe_calloc (1, sizeof (lvalItem));
3069   lpItem->req=1;
3070   lpItem->lvl=lvl;
3071   addSetHead(&lvaluereqSet,lpItem);
3072
3073 }
3074 /*-----------------------------------------------------------------*/
3075 /* delLvaluereq - del a flag for lvalreq for current ast level     */
3076 /*-----------------------------------------------------------------*/
3077 void delLvaluereq()
3078 {
3079   lvalItem * lpItem;
3080   lpItem = getSet(&lvaluereqSet);
3081   if(lpItem) free(lpItem);
3082 }
3083 /*-----------------------------------------------------------------*/
3084 /* clearLvaluereq - clear lvalreq flag                             */
3085 /*-----------------------------------------------------------------*/
3086 void clearLvaluereq()
3087 {
3088   lvalItem * lpItem;
3089   lpItem = peekSet(lvaluereqSet);
3090   if(lpItem) lpItem->req = 0;
3091 }
3092 /*-----------------------------------------------------------------*/
3093 /* getLvaluereq - get the last lvalreq level                       */
3094 /*-----------------------------------------------------------------*/
3095 int getLvaluereqLvl()
3096 {
3097   lvalItem * lpItem;
3098   lpItem = peekSet(lvaluereqSet);
3099   if(lpItem) return lpItem->lvl;
3100   return 0;
3101 }
3102 /*-----------------------------------------------------------------*/
3103 /* isLvaluereq - is lvalreq valid for this level ?                 */
3104 /*-----------------------------------------------------------------*/
3105 int isLvaluereq(int lvl)
3106 {
3107   lvalItem * lpItem;
3108   lpItem = peekSet(lvaluereqSet);
3109   if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3110   return 0;
3111 }
3112
3113 /*-----------------------------------------------------------------*/
3114 /* ast2iCode - creates an icodeList from an ast                    */
3115 /*-----------------------------------------------------------------*/
3116 operand *
3117 ast2iCode (ast * tree,int lvl)
3118 {
3119   operand *left = NULL;
3120   operand *right = NULL;
3121   if (!tree)
3122     return NULL;
3123   /* set the global variables for filename & line number */
3124   if (tree->filename)
3125     filename = tree->filename;
3126   if (tree->lineno)
3127     lineno = tree->lineno;
3128   if (tree->block)
3129     block = tree->block;
3130   if (tree->level)
3131     scopeLevel = tree->level;
3132
3133   if (tree->type == EX_VALUE)
3134     return operandFromValue (tree->opval.val);
3135
3136   if (tree->type == EX_LINK)
3137     return operandFromLink (tree->opval.lnk);
3138
3139   /* if we find a nullop */
3140   if (tree->type == EX_OP &&
3141      (tree->opval.op == NULLOP ||
3142      tree->opval.op == BLOCK))
3143     {
3144       ast2iCode (tree->left,lvl+1);
3145       ast2iCode (tree->right,lvl+1);
3146       return NULL;
3147     }
3148
3149   /* special cases for not evaluating */
3150   if (tree->opval.op != ':' &&
3151       tree->opval.op != '?' &&
3152       tree->opval.op != CALL &&
3153       tree->opval.op != IFX &&
3154       tree->opval.op != LABEL &&
3155       tree->opval.op != GOTO &&
3156       tree->opval.op != SWITCH &&
3157       tree->opval.op != FUNCTION &&
3158       tree->opval.op != INLINEASM)
3159     {
3160
3161         if (IS_ASSIGN_OP (tree->opval.op) ||
3162            IS_DEREF_OP (tree) ||
3163            (tree->opval.op == '&' && !tree->right) ||
3164            tree->opval.op == PTR_OP)
3165           {
3166             addLvaluereq(lvl);
3167             if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3168                (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3169               clearLvaluereq();
3170
3171             left = operandFromAst (tree->left,lvl);
3172             delLvaluereq();
3173             if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3174               left = geniCodeRValue (left, TRUE);
3175           }
3176         else
3177           {
3178             left = operandFromAst (tree->left,lvl);
3179           }
3180         if (tree->opval.op == INC_OP ||
3181             tree->opval.op == DEC_OP)
3182           {
3183             addLvaluereq(lvl);
3184             right = operandFromAst (tree->right,lvl);
3185             delLvaluereq();
3186           }
3187         else
3188           {
3189             right = operandFromAst (tree->right,lvl);
3190           }
3191       }
3192
3193   /* now depending on the type of operand */
3194   /* this will be a biggy                 */
3195   switch (tree->opval.op)
3196     {
3197
3198     case '[':                   /* array operation */
3199       {
3200         sym_link *ltype = operandType (left);
3201         left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3202         right = geniCodeRValue (right, TRUE);
3203       }
3204
3205       return geniCodeArray (left, right,lvl);
3206
3207     case '.':                   /* structure dereference */
3208       if (IS_PTR (operandType (left)))
3209         left = geniCodeRValue (left, TRUE);
3210       else
3211         left = geniCodeRValue (left, FALSE);
3212
3213       return geniCodeStruct (left, right, tree->lvalue);
3214
3215     case PTR_OP:                /* structure pointer dereference */
3216       {
3217         sym_link *pType;
3218         pType = operandType (left);
3219         left = geniCodeRValue (left, TRUE);
3220
3221         setOClass (pType, getSpec (operandType (left)));
3222       }
3223
3224       return geniCodeStruct (left, right, tree->lvalue);
3225
3226     case INC_OP:                /* increment operator */
3227       if (left)
3228         return geniCodePostInc (left);
3229       else
3230         return geniCodePreInc (right);
3231
3232     case DEC_OP:                /* decrement operator */
3233       if (left)
3234         return geniCodePostDec (left);
3235       else
3236         return geniCodePreDec (right);
3237
3238     case '&':                   /* bitwise and or address of operator */
3239       if (right)
3240         {                       /* this is a bitwise operator   */
3241           left = geniCodeRValue (left, FALSE);
3242           right = geniCodeRValue (right, FALSE);
3243           return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3244         }
3245       else
3246         return geniCodeAddressOf (left);
3247
3248     case '|':                   /* bitwise or & xor */
3249     case '^':
3250       return geniCodeBitwise (geniCodeRValue (left, FALSE),
3251                               geniCodeRValue (right, FALSE),
3252                               tree->opval.op,
3253                               tree->ftype);
3254
3255     case '/':
3256       return geniCodeDivision (geniCodeRValue (left, FALSE),
3257                                geniCodeRValue (right, FALSE));
3258
3259     case '%':
3260       return geniCodeModulus (geniCodeRValue (left, FALSE),
3261                               geniCodeRValue (right, FALSE));
3262     case '*':
3263       if (right)
3264         return geniCodeMultiply (geniCodeRValue (left, FALSE),
3265                                  geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3266       else
3267         return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3268
3269     case '-':
3270       if (right)
3271         return geniCodeSubtract (geniCodeRValue (left, FALSE),
3272                                  geniCodeRValue (right, FALSE));
3273       else
3274         return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3275
3276     case '+':
3277       if (right)
3278         return geniCodeAdd (geniCodeRValue (left, FALSE),
3279                             geniCodeRValue (right, FALSE),lvl);
3280       else
3281         return geniCodeRValue (left, FALSE);    /* unary '+' has no meaning */
3282
3283     case LEFT_OP:
3284       return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3285                                 geniCodeRValue (right, FALSE));
3286
3287     case RIGHT_OP:
3288       return geniCodeRightShift (geniCodeRValue (left, FALSE),
3289                                  geniCodeRValue (right, FALSE));
3290     case CAST:
3291       return geniCodeCast (operandType (left),
3292                            geniCodeRValue (right, FALSE), FALSE);
3293
3294     case '~':
3295     case '!':
3296     case RRC:
3297     case RLC:
3298       return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3299
3300     case GETHBIT:
3301       {
3302         operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3303         setOperandType (op, UCHARTYPE);
3304         return op;
3305       }
3306     case '>':
3307     case '<':
3308     case LE_OP:
3309     case GE_OP:
3310     case EQ_OP:
3311     case NE_OP:
3312     case AND_OP:
3313     case OR_OP:
3314       return geniCodeLogic (geniCodeRValue (left, FALSE),
3315                             geniCodeRValue (right, FALSE),
3316                             tree->opval.op);
3317     case '?':
3318       return geniCodeConditional (tree,lvl);
3319
3320     case SIZEOF:
3321       return operandFromLit (getSize (tree->right->ftype));
3322
3323     case '=':
3324       {
3325         sym_link *rtype = operandType (right);
3326         sym_link *ltype = operandType (left);
3327         if (IS_PTR (rtype) && IS_ITEMP (right)
3328             && right->isaddr && compareType (rtype->next, ltype) == 1)
3329           right = geniCodeRValue (right, TRUE);
3330         else
3331           right = geniCodeRValue (right, FALSE);
3332
3333         geniCodeAssign (left, right, 0);
3334         return right;
3335       }
3336     case MUL_ASSIGN:
3337       return
3338         geniCodeAssign (left,
3339                 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3340                                                   FALSE),
3341                                   geniCodeRValue (right, FALSE),FALSE), 0);
3342
3343     case DIV_ASSIGN:
3344       return
3345         geniCodeAssign (left,
3346                 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3347                                                   FALSE),
3348                                   geniCodeRValue (right, FALSE)), 0);
3349     case MOD_ASSIGN:
3350       return
3351         geniCodeAssign (left,
3352                  geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3353                                                   FALSE),
3354                                   geniCodeRValue (right, FALSE)), 0);
3355     case ADD_ASSIGN:
3356       {
3357         sym_link *rtype = operandType (right);
3358         sym_link *ltype = operandType (left);
3359         if (IS_PTR (rtype) && IS_ITEMP (right)
3360             && right->isaddr && compareType (rtype->next, ltype) == 1)
3361           right = geniCodeRValue (right, TRUE);
3362         else
3363           right = geniCodeRValue (right, FALSE);
3364
3365
3366         return geniCodeAssign (left,
3367                      geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3368                                                   FALSE),
3369                                   right,lvl), 0);
3370       }
3371     case SUB_ASSIGN:
3372       {
3373         sym_link *rtype = operandType (right);
3374         sym_link *ltype = operandType (left);
3375         if (IS_PTR (rtype) && IS_ITEMP (right)
3376             && right->isaddr && compareType (rtype->next, ltype) == 1)
3377           {
3378             right = geniCodeRValue (right, TRUE);
3379           }
3380         else
3381           {
3382             right = geniCodeRValue (right, FALSE);
3383           }
3384         return
3385           geniCodeAssign (left,
3386                 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3387                                                   FALSE),
3388                                   right), 0);
3389       }
3390     case LEFT_ASSIGN:
3391       return
3392         geniCodeAssign (left,
3393                 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3394                                                    ,FALSE),
3395                                    geniCodeRValue (right, FALSE)), 0);
3396     case RIGHT_ASSIGN:
3397       return
3398         geniCodeAssign (left,
3399                geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3400                                                    ,FALSE),
3401                                    geniCodeRValue (right, FALSE)), 0);
3402     case AND_ASSIGN:
3403       return
3404         geniCodeAssign (left,
3405                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3406                                                   FALSE),
3407                                   geniCodeRValue (right, FALSE),
3408                                   BITWISEAND,
3409                                   operandType (left)), 0);
3410     case XOR_ASSIGN:
3411       return
3412         geniCodeAssign (left,
3413                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3414                                                   FALSE),
3415                                   geniCodeRValue (right, FALSE),
3416                                   '^',
3417                                   operandType (left)), 0);
3418     case OR_ASSIGN:
3419       return
3420         geniCodeAssign (left,
3421                   geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3422                                                    ,FALSE),
3423                                    geniCodeRValue (right, FALSE),
3424                                    '|',
3425                                    operandType (left)), 0);
3426     case ',':
3427       return geniCodeRValue (right, FALSE);
3428
3429     case CALL:
3430       return geniCodeCall (ast2iCode (tree->left,lvl+1),
3431                            tree->right,lvl);
3432     case LABEL:
3433       geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3434       return ast2iCode (tree->right,lvl+1);
3435
3436     case GOTO:
3437       geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3438       return ast2iCode (tree->right,lvl+1);
3439
3440     case FUNCTION:
3441       geniCodeFunctionBody (tree,lvl);
3442       return NULL;
3443
3444     case RETURN:
3445       geniCodeReturn (right);
3446       return NULL;
3447
3448     case IFX:
3449       geniCodeIfx (tree,lvl);
3450       return NULL;
3451
3452     case SWITCH:
3453       geniCodeSwitch (tree,lvl);
3454       return NULL;
3455
3456     case INLINEASM:
3457       geniCodeInline (tree);
3458       return NULL;
3459         
3460     case ARRAYINIT:
3461         geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3462         return NULL;
3463     }
3464
3465   return NULL;
3466 }
3467
3468 /*-----------------------------------------------------------------*/
3469 /* reverseICChain - gets from the list and creates a linkedlist    */
3470 /*-----------------------------------------------------------------*/
3471 iCode *
3472 reverseiCChain ()
3473 {
3474   iCode *loop = NULL;
3475   iCode *prev = NULL;
3476
3477   while ((loop = getSet (&iCodeChain)))
3478     {
3479       loop->next = prev;
3480       if (prev)
3481         prev->prev = loop;
3482       prev = loop;
3483     }
3484
3485   return prev;
3486 }
3487
3488
3489 /*-----------------------------------------------------------------*/
3490 /* iCodeFromAst - given an ast will convert it to iCode            */
3491 /*-----------------------------------------------------------------*/
3492 iCode *
3493 iCodeFromAst (ast * tree)
3494 {
3495   returnLabel = newiTempLabel ("_return");
3496   entryLabel = newiTempLabel ("_entry");
3497   ast2iCode (tree,0);
3498   return reverseiCChain ();
3499 }