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