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