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