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