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