undid the hackup of const and volatile, the problem is much bigger
[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 a pointer then generate the rvalue */
2535   if (IS_PTR (optype))
2536     {
2537       if (IS_TRUE_SYMOP (op))
2538         {
2539           op->isaddr = 1;
2540           op = geniCodeRValue (op, TRUE);
2541         }
2542       else
2543         op = geniCodeRValue (op, TRUE);
2544     }
2545
2546   /* now get rid of the pointer part */
2547   if (isLvaluereq(lvl) && IS_ITEMP (op))
2548     {
2549       retype = getSpec (rtype = copyLinkChain (optype));
2550     }
2551   else
2552     {
2553       retype = getSpec (rtype = copyLinkChain (optype->next));
2554     }
2555
2556   /* if this is a pointer then outputclass needs 2b updated */
2557   if (IS_PTR (optype))
2558     setOClass (optype, retype);
2559
2560   op->isGptr = IS_GENPTR (optype);
2561
2562 #ifdef JWK
2563   /* if the pointer was declared as a constant */
2564   /* then we cannot allow assignment to the derefed */
2565   if (IS_PTR_CONST (optype))
2566     SPEC_CONST (retype) = 1;
2567 #endif
2568
2569   op->isaddr = (IS_PTR (rtype) ||
2570                 IS_STRUCT (rtype) ||
2571                 IS_INT (rtype) ||
2572                 IS_CHAR (rtype) ||
2573                 IS_FLOAT (rtype));
2574
2575   if (!isLvaluereq(lvl))
2576     op = geniCodeRValue (op, TRUE);
2577
2578   setOperandType (op, rtype);
2579
2580   return op;
2581 }
2582
2583 /*-----------------------------------------------------------------*/
2584 /* geniCodeUnaryMinus - does a unary minus of the operand          */
2585 /*-----------------------------------------------------------------*/
2586 operand *
2587 geniCodeUnaryMinus (operand * op)
2588 {
2589   iCode *ic;
2590   sym_link *optype = operandType (op);
2591
2592   if (IS_LITERAL (optype))
2593     return operandFromLit (-floatFromVal (op->operand.valOperand));
2594
2595   ic = newiCode (UNARYMINUS, op, NULL);
2596   IC_RESULT (ic) = newiTempOperand (optype, 0);
2597   ADDTOCHAIN (ic);
2598   return IC_RESULT (ic);
2599 }
2600
2601 /*-----------------------------------------------------------------*/
2602 /* geniCodeLeftShift - gen i code for left shift                   */
2603 /*-----------------------------------------------------------------*/
2604 operand *
2605 geniCodeLeftShift (operand * left, operand * right)
2606 {
2607   iCode *ic;
2608
2609   ic = newiCode (LEFT_OP, left, right);
2610   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2611   ADDTOCHAIN (ic);
2612   return IC_RESULT (ic);
2613 }
2614
2615 /*-----------------------------------------------------------------*/
2616 /* geniCodeRightShift - gen i code for right shift                 */
2617 /*-----------------------------------------------------------------*/
2618 operand *
2619 geniCodeRightShift (operand * left, operand * right)
2620 {
2621   iCode *ic;
2622
2623   ic = newiCode (RIGHT_OP, left, right);
2624   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2625   ADDTOCHAIN (ic);
2626   return IC_RESULT (ic);
2627 }
2628
2629 /*-----------------------------------------------------------------*/
2630 /* geniCodeLogic- logic code                                       */
2631 /*-----------------------------------------------------------------*/
2632 operand *
2633 geniCodeLogic (operand * left, operand * right, int op)
2634 {
2635   iCode *ic;
2636   sym_link *ctype;
2637   sym_link *rtype = operandType (right);
2638   sym_link *ltype = operandType (left);
2639
2640   /* left is integral type and right is literal then
2641      check if the literal value is within bounds */
2642   if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2643     {
2644       checkConstantRange(ltype, 
2645                          OP_VALUE(right), "compare operation", 1);
2646     }
2647
2648   ctype = usualBinaryConversions (&left, &right);
2649
2650   ic = newiCode (op, left, right);
2651   IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2652
2653   /* if comparing float
2654      and not a '==' || '!=' || '&&' || '||' (these
2655      will be inlined */
2656   if (IS_FLOAT(ctype) &&
2657       op != EQ_OP &&
2658       op != NE_OP &&
2659       op != AND_OP &&
2660       op != OR_OP)
2661     ic->supportRtn = 1;
2662
2663   ADDTOCHAIN (ic);
2664   return IC_RESULT (ic);
2665 }
2666
2667 /*-----------------------------------------------------------------*/
2668 /* geniCodeUnary - for a a generic unary operation                 */
2669 /*-----------------------------------------------------------------*/
2670 operand *
2671 geniCodeUnary (operand * op, int oper)
2672 {
2673   iCode *ic = newiCode (oper, op, NULL);
2674
2675   IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2676   ADDTOCHAIN (ic);
2677   return IC_RESULT (ic);
2678 }
2679
2680 /*-----------------------------------------------------------------*/
2681 /* geniCodeConditional - geniCode for '?' ':' operation            */
2682 /*-----------------------------------------------------------------*/
2683 operand *
2684 geniCodeConditional (ast * tree,int lvl)
2685 {
2686   iCode *ic;
2687   symbol *falseLabel = newiTempLabel (NULL);
2688   symbol *exitLabel = newiTempLabel (NULL);
2689   operand *cond = ast2iCode (tree->left,lvl+1);
2690   operand *true, *false, *result;
2691
2692   ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2693                           NULL, falseLabel);
2694   ADDTOCHAIN (ic);
2695
2696   true = ast2iCode (tree->right->left,lvl+1);
2697
2698   /* move the value to a new Operand */
2699   result = newiTempOperand (tree->right->ftype, 0);
2700   geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2701
2702   /* generate an unconditional goto */
2703   geniCodeGoto (exitLabel);
2704
2705   /* now for the right side */
2706   geniCodeLabel (falseLabel);
2707
2708   false = ast2iCode (tree->right->right,lvl+1);
2709   geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2710
2711   /* create the exit label */
2712   geniCodeLabel (exitLabel);
2713
2714   return result;
2715 }
2716
2717 /*-----------------------------------------------------------------*/
2718 /* geniCodeAssign - generate code for assignment                   */
2719 /*-----------------------------------------------------------------*/
2720 operand *
2721 geniCodeAssign (operand * left, operand * right, int nosupdate)
2722 {
2723   iCode *ic;
2724   sym_link *ltype = operandType (left);
2725   sym_link *rtype = operandType (right);
2726
2727   if (!left->isaddr && !IS_ITEMP (left))
2728     {
2729       werror (E_LVALUE_REQUIRED, "assignment");
2730       return left;
2731     }
2732
2733   /* left is integral type and right is literal then
2734      check if the literal value is within bounds */
2735   if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2736     {
2737       checkConstantRange(ltype, 
2738                          OP_VALUE(right), "= operation", 0);
2739     }
2740
2741   /* if the left & right type don't exactly match */
2742   /* if pointer set then make sure the check is
2743      done with the type & not the pointer */
2744   /* then cast rights type to left */
2745
2746   /* first check the type for pointer assignement */
2747   if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2748       compareType (ltype, rtype) <= 0)
2749     {
2750       if (compareType (ltype->next, rtype) < 0)
2751         right = geniCodeCast (ltype->next, right, TRUE);
2752     }
2753   else if (compareType (ltype, rtype) < 0)
2754     right = geniCodeCast (ltype, right, TRUE);
2755
2756   /* if left is a true symbol & ! volatile
2757      create an assignment to temporary for
2758      the right & then assign this temporary
2759      to the symbol this is SSA . isn't it simple
2760      and folks have published mountains of paper on it */
2761   if (IS_TRUE_SYMOP (left) &&
2762       !isOperandVolatile (left, FALSE) &&
2763       isOperandGlobal (left))
2764     {
2765       symbol *sym = NULL;
2766
2767       if (IS_TRUE_SYMOP (right))
2768         sym = OP_SYMBOL (right);
2769       ic = newiCode ('=', NULL, right);
2770       IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2771       SPIL_LOC (right) = sym;
2772       ADDTOCHAIN (ic);
2773     }
2774
2775   ic = newiCode ('=', NULL, right);
2776   IC_RESULT (ic) = left;
2777   ADDTOCHAIN (ic);
2778
2779   /* if left isgptr flag is set then support
2780      routine will be required */
2781   if (left->isGptr)
2782     ic->supportRtn = 1;
2783
2784   ic->nosupdate = nosupdate;
2785   return left;
2786 }
2787
2788 /*-----------------------------------------------------------------*/
2789 /* geniCodeSEParms - generate code for side effecting fcalls       */
2790 /*-----------------------------------------------------------------*/
2791 static void 
2792 geniCodeSEParms (ast * parms,int lvl)
2793 {
2794   if (!parms)
2795     return;
2796
2797   if (parms->type == EX_OP && parms->opval.op == PARAM)
2798     {
2799       geniCodeSEParms (parms->left,lvl);
2800       geniCodeSEParms (parms->right,lvl);
2801       return;
2802     }
2803
2804   /* hack don't like this but too lazy to think of
2805      something better */
2806   if (IS_ADDRESS_OF_OP (parms))
2807     parms->left->lvalue = 1;
2808
2809   if (IS_CAST_OP (parms) &&
2810       IS_PTR (parms->ftype) &&
2811       IS_ADDRESS_OF_OP (parms->right))
2812     parms->right->left->lvalue = 1;
2813
2814   parms->opval.oprnd = 
2815     geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2816                 
2817   parms->type = EX_OPERAND;
2818   AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
2819                 SPEC_ARGREG(parms->ftype);
2820 }
2821
2822 /*-----------------------------------------------------------------*/
2823 /* geniCodeParms - generates parameters                            */
2824 /*-----------------------------------------------------------------*/
2825 value *
2826 geniCodeParms (ast * parms, value *argVals, int *stack, 
2827                sym_link * fetype, symbol * func,int lvl)
2828 {
2829   iCode *ic;
2830   operand *pval;
2831
2832   if (!parms)
2833     return argVals;
2834
2835   if (argVals==NULL) {
2836     // first argument
2837     argVals=FUNC_ARGS(func->type);
2838   }
2839
2840   /* if this is a param node then do the left & right */
2841   if (parms->type == EX_OP && parms->opval.op == PARAM)
2842     {
2843       argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
2844       argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
2845       return argVals;
2846     }
2847
2848   /* get the parameter value */
2849   if (parms->type == EX_OPERAND)
2850     pval = parms->opval.oprnd;
2851   else
2852     {
2853       /* maybe this else should go away ?? */
2854       /* hack don't like this but too lazy to think of
2855          something better */
2856       if (IS_ADDRESS_OF_OP (parms))
2857         parms->left->lvalue = 1;
2858
2859       if (IS_CAST_OP (parms) &&
2860           IS_PTR (parms->ftype) &&
2861           IS_ADDRESS_OF_OP (parms->right))
2862         parms->right->left->lvalue = 1;
2863
2864       pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2865     }
2866
2867   /* if register parm then make it a send */
2868   if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
2869       IFFUNC_ISBUILTIN(func->type))
2870     {
2871       ic = newiCode (SEND, pval, NULL);
2872       ic->argreg = SPEC_ARGREG(parms->etype);
2873       ic->builtinSEND = FUNC_ISBUILTIN(func->type);
2874       ADDTOCHAIN (ic);
2875     }
2876   else
2877     {
2878       /* now decide whether to push or assign */
2879       if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
2880         {
2881
2882           /* assign */
2883           operand *top = operandFromSymbol (argVals->sym);
2884           /* clear useDef and other bitVectors */
2885           OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
2886           geniCodeAssign (top, pval, 1);
2887         }
2888       else
2889         {
2890           sym_link *p = operandType (pval);
2891           /* push */
2892           ic = newiCode (IPUSH, pval, NULL);
2893           ic->parmPush = 1;
2894           /* update the stack adjustment */
2895           *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2896           ADDTOCHAIN (ic);
2897         }
2898     }
2899
2900   argVals=argVals->next;
2901   return argVals;
2902 }
2903
2904 /*-----------------------------------------------------------------*/
2905 /* geniCodeCall - generates temp code for calling                  */
2906 /*-----------------------------------------------------------------*/
2907 operand *
2908 geniCodeCall (operand * left, ast * parms,int lvl)
2909 {
2910   iCode *ic;
2911   operand *result;
2912   sym_link *type, *etype;
2913   int stack = 0;
2914
2915   if (!IS_FUNC(OP_SYMBOL(left)->type) && 
2916       !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2917     werror (E_FUNCTION_EXPECTED);
2918     return NULL;
2919   }
2920
2921   /* take care of parameters with side-effecting
2922      function calls in them, this is required to take care
2923      of overlaying function parameters */
2924   geniCodeSEParms (parms,lvl);
2925
2926   /* first the parameters */
2927   geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2928
2929   /* now call : if symbol then pcall */
2930   if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
2931     ic = newiCode (PCALL, left, NULL);
2932   } else {
2933     ic = newiCode (CALL, left, NULL);
2934   }
2935
2936   type = copyLinkChain (operandType (left)->next);
2937   etype = getSpec (type);
2938   SPEC_EXTR (etype) = 0;
2939   IC_RESULT (ic) = result = newiTempOperand (type, 1);
2940
2941   ADDTOCHAIN (ic);
2942
2943   /* stack adjustment after call */
2944   ic->parmBytes = stack;
2945
2946   return result;
2947 }
2948
2949 /*-----------------------------------------------------------------*/
2950 /* geniCodeReceive - generate intermediate code for "receive"      */
2951 /*-----------------------------------------------------------------*/
2952 static void 
2953 geniCodeReceive (value * args)
2954 {
2955   /* for all arguments that are passed in registers */
2956   while (args)
2957     {
2958       int first = 1;
2959       if (IS_REGPARM (args->etype))
2960         {
2961           operand *opr = operandFromValue (args);
2962           operand *opl;
2963           symbol *sym = OP_SYMBOL (opr);
2964           iCode *ic;
2965
2966           /* we will use it after all optimizations
2967              and before liveRange calculation */
2968           if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2969             {
2970
2971               if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2972                   options.stackAuto == 0 &&
2973                   (!(options.model == MODEL_FLAT24)) )
2974                 {
2975                 }
2976               else
2977                 {
2978                   opl = newiTempOperand (args->type, 0);
2979                   sym->reqv = opl;
2980                   sym->reqv->key = sym->key;
2981                   OP_SYMBOL (sym->reqv)->key = sym->key;
2982                   OP_SYMBOL (sym->reqv)->isreqv = 1;
2983                   OP_SYMBOL (sym->reqv)->islocal = 0;
2984                   SPIL_LOC (sym->reqv) = sym;
2985                 }
2986             }
2987
2988           ic = newiCode (RECEIVE, NULL, NULL);    
2989           ic->argreg = SPEC_ARGREG(args->etype);
2990           if (first) {
2991               currFunc->recvSize = getSize (sym->type);
2992               first = 0;
2993           }
2994           IC_RESULT (ic) = opr;
2995           ADDTOCHAIN (ic);
2996         }
2997
2998       args = args->next;
2999     }
3000 }
3001
3002 /*-----------------------------------------------------------------*/
3003 /* geniCodeFunctionBody - create the function body                 */
3004 /*-----------------------------------------------------------------*/
3005 void 
3006 geniCodeFunctionBody (ast * tree,int lvl)
3007 {
3008   iCode *ic;
3009   operand *func;
3010   sym_link *fetype;
3011   int savelineno;
3012
3013   /* reset the auto generation */
3014   /* numbers */
3015   iTempNum = 0;
3016   iTempLblNum = 0;
3017   operandKey = 0;
3018   iCodeKey = 0;
3019   func = ast2iCode (tree->left,lvl+1);
3020   fetype = getSpec (operandType (func));
3021
3022   savelineno = lineno;
3023   lineno = OP_SYMBOL (func)->lineDef;
3024   /* create an entry label */
3025   geniCodeLabel (entryLabel);
3026   lineno = savelineno;
3027
3028   /* create a proc icode */
3029   ic = newiCode (FUNCTION, func, NULL);
3030   lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3031
3032   ADDTOCHAIN (ic);
3033
3034   /* for all parameters that are passed
3035      on registers add a "receive" */
3036   geniCodeReceive (tree->values.args);
3037
3038   /* generate code for the body */
3039   ast2iCode (tree->right,lvl+1);
3040
3041   /* create a label for return */
3042   geniCodeLabel (returnLabel);
3043
3044   /* now generate the end proc */
3045   ic = newiCode (ENDFUNCTION, func, NULL);
3046   ADDTOCHAIN (ic);
3047   return;
3048 }
3049
3050 /*-----------------------------------------------------------------*/
3051 /* geniCodeReturn - gen icode for 'return' statement               */
3052 /*-----------------------------------------------------------------*/
3053 void 
3054 geniCodeReturn (operand * op)
3055 {
3056   iCode *ic;
3057
3058   /* if the operand is present force an rvalue */
3059   if (op)
3060     op = geniCodeRValue (op, FALSE);
3061
3062   ic = newiCode (RETURN, op, NULL);
3063   ADDTOCHAIN (ic);
3064 }
3065
3066 /*-----------------------------------------------------------------*/
3067 /* geniCodeIfx - generates code for extended if statement          */
3068 /*-----------------------------------------------------------------*/
3069 void 
3070 geniCodeIfx (ast * tree,int lvl)
3071 {
3072   iCode *ic;
3073   operand *condition = ast2iCode (tree->left,lvl+1);
3074   sym_link *cetype;
3075
3076   /* if condition is null then exit */
3077   if (!condition)
3078     goto exit;
3079   else
3080     condition = geniCodeRValue (condition, FALSE);
3081
3082   cetype = getSpec (operandType (condition));
3083   /* if the condition is a literal */
3084   if (IS_LITERAL (cetype))
3085     {
3086       if (floatFromVal (condition->operand.valOperand))
3087         {
3088           if (tree->trueLabel)
3089             geniCodeGoto (tree->trueLabel);
3090           else
3091             assert (0);
3092         }
3093       else
3094         {
3095           if (tree->falseLabel)
3096             geniCodeGoto (tree->falseLabel);
3097           else
3098             assert (0);
3099         }
3100       goto exit;
3101     }
3102
3103   if (tree->trueLabel)
3104     {
3105       ic = newiCodeCondition (condition,
3106                               tree->trueLabel,
3107                               NULL);
3108       ADDTOCHAIN (ic);
3109
3110       if (tree->falseLabel)
3111         geniCodeGoto (tree->falseLabel);
3112     }
3113   else
3114     {
3115       ic = newiCodeCondition (condition,
3116                               NULL,
3117                               tree->falseLabel);
3118       ADDTOCHAIN (ic);
3119     }
3120
3121 exit:
3122   ast2iCode (tree->right,lvl+1);
3123 }
3124
3125 /*-----------------------------------------------------------------*/
3126 /* geniCodeJumpTable - tries to create a jump table for switch     */
3127 /*-----------------------------------------------------------------*/
3128 int 
3129 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3130 {
3131   int min = 0, max = 0, t, cnt = 0;
3132   value *vch;
3133   iCode *ic;
3134   operand *boundary;
3135   symbol *falseLabel;
3136   set *labels = NULL;
3137
3138   if (!tree || !caseVals)
3139     return 0;
3140
3141   /* the criteria for creating a jump table is */
3142   /* all integer numbers between the maximum & minimum must */
3143   /* be present , the maximum value should not exceed 255 */
3144   min = max = (int) floatFromVal (vch = caseVals);
3145   SNPRINTF (buffer, sizeof(buffer), 
3146             "_case_%d_%d",
3147            tree->values.switchVals.swNum,
3148            min);
3149   addSet (&labels, newiTempLabel (buffer));
3150
3151   /* if there is only one case value then no need */
3152   if (!(vch = vch->next))
3153     return 0;
3154
3155   while (vch)
3156     {
3157       if (((t = (int) floatFromVal (vch)) - max) != 1)
3158         return 0;
3159       SNPRINTF (buffer, sizeof(buffer), 
3160                 "_case_%d_%d",
3161                tree->values.switchVals.swNum,
3162                t);
3163       addSet (&labels, newiTempLabel (buffer));
3164       max = t;
3165       cnt++;
3166       vch = vch->next;
3167     }
3168
3169   /* if the number of case statements <= 2 then */
3170   /* it is not economical to create the jump table */
3171   /* since two compares are needed for boundary conditions */
3172   if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3173     return 0;
3174
3175   if (tree->values.switchVals.swDefault)
3176     {
3177         SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3178     }
3179   else
3180     {
3181         SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3182     }
3183     
3184
3185   falseLabel = newiTempLabel (buffer);
3186
3187   /* so we can create a jumptable */
3188   /* first we rule out the boundary conditions */
3189   /* if only optimization says so */
3190   if (!optimize.noJTabBoundary)
3191     {
3192       sym_link *cetype = getSpec (operandType (cond));
3193       /* no need to check the lower bound if
3194          the condition is unsigned & minimum value is zero */
3195       if (!(min == 0 && SPEC_USIGN (cetype)))
3196         {
3197           boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3198           ic = newiCodeCondition (boundary, falseLabel, NULL);
3199           ADDTOCHAIN (ic);
3200         }
3201
3202       /* now for upper bounds */
3203       boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3204       ic = newiCodeCondition (boundary, falseLabel, NULL);
3205       ADDTOCHAIN (ic);
3206     }
3207
3208   /* if the min is not zero then we no make it zero */
3209   if (min)
3210     {
3211       cond = geniCodeSubtract (cond, operandFromLit (min));
3212       setOperandType (cond, UCHARTYPE);
3213     }
3214
3215   /* now create the jumptable */
3216   ic = newiCode (JUMPTABLE, NULL, NULL);
3217   IC_JTCOND (ic) = cond;
3218   IC_JTLABELS (ic) = labels;
3219   ADDTOCHAIN (ic);
3220   return 1;
3221 }
3222
3223 /*-----------------------------------------------------------------*/
3224 /* geniCodeSwitch - changes a switch to a if statement             */
3225 /*-----------------------------------------------------------------*/
3226 void 
3227 geniCodeSwitch (ast * tree,int lvl)
3228 {
3229   iCode *ic;
3230   operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3231   value *caseVals = tree->values.switchVals.swVals;
3232   symbol *trueLabel, *falseLabel;
3233
3234   /* if we can make this a jump table */
3235   if (geniCodeJumpTable (cond, caseVals, tree))
3236     goto jumpTable;             /* no need for the comparison */
3237
3238   /* for the cases defined do */
3239   while (caseVals)
3240     {
3241
3242       operand *compare = geniCodeLogic (cond,
3243                                         operandFromValue (caseVals),
3244                                         EQ_OP);
3245
3246       SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3247                tree->values.switchVals.swNum,
3248                (int) floatFromVal (caseVals));
3249       trueLabel = newiTempLabel (buffer);
3250
3251       ic = newiCodeCondition (compare, trueLabel, NULL);
3252       ADDTOCHAIN (ic);
3253       caseVals = caseVals->next;
3254     }
3255
3256
3257
3258   /* if default is present then goto break else break */
3259   if (tree->values.switchVals.swDefault)
3260     {
3261         SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3262     }
3263   else
3264     {
3265         SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3266     }
3267
3268   falseLabel = newiTempLabel (buffer);
3269   geniCodeGoto (falseLabel);
3270
3271 jumpTable:
3272   ast2iCode (tree->right,lvl+1);
3273 }
3274
3275 /*-----------------------------------------------------------------*/
3276 /* geniCodeInline - intermediate code for inline assembler         */
3277 /*-----------------------------------------------------------------*/
3278 static void 
3279 geniCodeInline (ast * tree)
3280 {
3281   iCode *ic;
3282
3283   ic = newiCode (INLINEASM, NULL, NULL);
3284   IC_INLINE (ic) = tree->values.inlineasm;
3285   ADDTOCHAIN (ic);
3286 }
3287
3288 /*-----------------------------------------------------------------*/
3289 /* geniCodeArrayInit - intermediate code for array initializer     */
3290 /*-----------------------------------------------------------------*/
3291 static void 
3292 geniCodeArrayInit (ast * tree, operand *array)
3293 {
3294   iCode *ic;
3295
3296   if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3297     ic = newiCode (ARRAYINIT, array, NULL);
3298     IC_ARRAYILIST (ic) = tree->values.constlist;
3299   } else {
3300     operand *left=newOperand(), *right=newOperand();
3301     left->type=right->type=SYMBOL;
3302     OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3303     OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3304     ic = newiCode (ARRAYINIT, left, right);
3305   }
3306   ADDTOCHAIN (ic);
3307 }
3308
3309 /*-----------------------------------------------------------------*/
3310 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some      */
3311 /* particular case. Ie : assigning or dereferencing array or ptr   */
3312 /*-----------------------------------------------------------------*/
3313 set * lvaluereqSet = NULL;
3314 typedef struct lvalItem
3315   {
3316     int req;
3317     int lvl;
3318   }
3319 lvalItem;
3320
3321 /*-----------------------------------------------------------------*/
3322 /* addLvaluereq - add a flag for lvalreq for current ast level     */
3323 /*-----------------------------------------------------------------*/
3324 void addLvaluereq(int lvl)
3325 {
3326   lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3327   lpItem->req=1;
3328   lpItem->lvl=lvl;
3329   addSetHead(&lvaluereqSet,lpItem);
3330
3331 }
3332 /*-----------------------------------------------------------------*/
3333 /* delLvaluereq - del a flag for lvalreq for current ast level     */
3334 /*-----------------------------------------------------------------*/
3335 void delLvaluereq()
3336 {
3337   lvalItem * lpItem;
3338   lpItem = getSet(&lvaluereqSet);
3339   if(lpItem) Safe_free(lpItem);
3340 }
3341 /*-----------------------------------------------------------------*/
3342 /* clearLvaluereq - clear lvalreq flag                             */
3343 /*-----------------------------------------------------------------*/
3344 void clearLvaluereq()
3345 {
3346   lvalItem * lpItem;
3347   lpItem = peekSet(lvaluereqSet);
3348   if(lpItem) lpItem->req = 0;
3349 }
3350 /*-----------------------------------------------------------------*/
3351 /* getLvaluereq - get the last lvalreq level                       */
3352 /*-----------------------------------------------------------------*/
3353 int getLvaluereqLvl()
3354 {
3355   lvalItem * lpItem;
3356   lpItem = peekSet(lvaluereqSet);
3357   if(lpItem) return lpItem->lvl;
3358   return 0;
3359 }
3360 /*-----------------------------------------------------------------*/
3361 /* isLvaluereq - is lvalreq valid for this level ?                 */
3362 /*-----------------------------------------------------------------*/
3363 int isLvaluereq(int lvl)
3364 {
3365   lvalItem * lpItem;
3366   lpItem = peekSet(lvaluereqSet);
3367   if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3368   return 0;
3369 }
3370
3371 /*-----------------------------------------------------------------*/
3372 /* ast2iCode - creates an icodeList from an ast                    */
3373 /*-----------------------------------------------------------------*/
3374 operand *
3375 ast2iCode (ast * tree,int lvl)
3376 {
3377   operand *left = NULL;
3378   operand *right = NULL;
3379   if (!tree)
3380     return NULL;
3381
3382   /* set the global variables for filename & line number */
3383   if (tree->filename)
3384     filename = tree->filename;
3385   if (tree->lineno)
3386     lineno = tree->lineno;
3387   if (tree->block)
3388     block = tree->block;
3389   if (tree->level)
3390     scopeLevel = tree->level;
3391
3392   if (tree->type == EX_VALUE)
3393     return operandFromValue (tree->opval.val);
3394
3395   if (tree->type == EX_LINK)
3396     return operandFromLink (tree->opval.lnk);
3397
3398   /* if we find a nullop */
3399   if (tree->type == EX_OP &&
3400      (tree->opval.op == NULLOP ||
3401      tree->opval.op == BLOCK))
3402     {
3403       ast2iCode (tree->left,lvl+1);
3404       ast2iCode (tree->right,lvl+1);
3405       return NULL;
3406     }
3407
3408   /* special cases for not evaluating */
3409   if (tree->opval.op != ':' &&
3410       tree->opval.op != '?' &&
3411       tree->opval.op != CALL &&
3412       tree->opval.op != IFX &&
3413       tree->opval.op != LABEL &&
3414       tree->opval.op != GOTO &&
3415       tree->opval.op != SWITCH &&
3416       tree->opval.op != FUNCTION &&
3417       tree->opval.op != INLINEASM)
3418     {
3419
3420         if (IS_ASSIGN_OP (tree->opval.op) ||
3421            IS_DEREF_OP (tree) ||
3422            (tree->opval.op == '&' && !tree->right) ||
3423            tree->opval.op == PTR_OP)
3424           {
3425             addLvaluereq(lvl);
3426             if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3427                (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3428               clearLvaluereq();
3429
3430             left = operandFromAst (tree->left,lvl);
3431             delLvaluereq();
3432             if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3433               left = geniCodeRValue (left, TRUE);
3434           }
3435         else
3436           {
3437             left = operandFromAst (tree->left,lvl);
3438           }
3439         if (tree->opval.op == INC_OP ||
3440             tree->opval.op == DEC_OP)
3441           {
3442             addLvaluereq(lvl);
3443             right = operandFromAst (tree->right,lvl);
3444             delLvaluereq();
3445           }
3446         else
3447           {
3448             right = operandFromAst (tree->right,lvl);
3449           }
3450       }
3451
3452   /* now depending on the type of operand */
3453   /* this will be a biggy                 */
3454   switch (tree->opval.op)
3455     {
3456
3457     case '[':                   /* array operation */
3458       {
3459         //sym_link *ltype = operandType (left);
3460         //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3461         left = geniCodeRValue (left, FALSE);
3462         right = geniCodeRValue (right, TRUE);
3463       }
3464
3465       return geniCodeArray (left, right,lvl);
3466
3467     case '.':                   /* structure dereference */
3468       if (IS_PTR (operandType (left)))
3469         left = geniCodeRValue (left, TRUE);
3470       else
3471         left = geniCodeRValue (left, FALSE);
3472
3473       return geniCodeStruct (left, right, tree->lvalue);
3474
3475     case PTR_OP:                /* structure pointer dereference */
3476       {
3477         sym_link *pType;
3478         pType = operandType (left);
3479         left = geniCodeRValue (left, TRUE);
3480
3481         setOClass (pType, getSpec (operandType (left)));
3482       }
3483
3484       return geniCodeStruct (left, right, tree->lvalue);
3485
3486     case INC_OP:                /* increment operator */
3487       if (left)
3488         return geniCodePostInc (left);
3489       else
3490         return geniCodePreInc (right);
3491
3492     case DEC_OP:                /* decrement operator */
3493       if (left)
3494         return geniCodePostDec (left);
3495       else
3496         return geniCodePreDec (right);
3497
3498     case '&':                   /* bitwise and or address of operator */
3499       if (right)
3500         {                       /* this is a bitwise operator   */
3501           left = geniCodeRValue (left, FALSE);
3502           right = geniCodeRValue (right, FALSE);
3503           return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3504         }
3505       else
3506         return geniCodeAddressOf (left);
3507
3508     case '|':                   /* bitwise or & xor */
3509     case '^':
3510       return geniCodeBitwise (geniCodeRValue (left, FALSE),
3511                               geniCodeRValue (right, FALSE),
3512                               tree->opval.op,
3513                               tree->ftype);
3514
3515     case '/':
3516       return geniCodeDivision (geniCodeRValue (left, FALSE),
3517                                geniCodeRValue (right, FALSE));
3518
3519     case '%':
3520       return geniCodeModulus (geniCodeRValue (left, FALSE),
3521                               geniCodeRValue (right, FALSE));
3522     case '*':
3523       if (right)
3524         return geniCodeMultiply (geniCodeRValue (left, FALSE),
3525                                  geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3526       else
3527         return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3528
3529     case '-':
3530       if (right)
3531         return geniCodeSubtract (geniCodeRValue (left, FALSE),
3532                                  geniCodeRValue (right, FALSE));
3533       else
3534         return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3535
3536     case '+':
3537       if (right)
3538         return geniCodeAdd (geniCodeRValue (left, FALSE),
3539                             geniCodeRValue (right, FALSE),lvl);
3540       else
3541         return geniCodeRValue (left, FALSE);    /* unary '+' has no meaning */
3542
3543     case LEFT_OP:
3544       return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3545                                 geniCodeRValue (right, FALSE));
3546
3547     case RIGHT_OP:
3548       return geniCodeRightShift (geniCodeRValue (left, FALSE),
3549                                  geniCodeRValue (right, FALSE));
3550     case CAST:
3551       return geniCodeCast (operandType (left),
3552                            geniCodeRValue (right, FALSE), FALSE);
3553
3554     case '~':
3555     case '!':
3556     case RRC:
3557     case RLC:
3558       return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3559
3560     case GETHBIT:
3561       {
3562         operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3563         setOperandType (op, UCHARTYPE);
3564         return op;
3565       }
3566     case '>':
3567     case '<':
3568     case LE_OP:
3569     case GE_OP:
3570     case EQ_OP:
3571     case NE_OP:
3572     case AND_OP:
3573     case OR_OP:
3574       return geniCodeLogic (geniCodeRValue (left, FALSE),
3575                             geniCodeRValue (right, FALSE),
3576                             tree->opval.op);
3577     case '?':
3578       return geniCodeConditional (tree,lvl);
3579
3580     case SIZEOF:
3581       return operandFromLit (getSize (tree->right->ftype));
3582
3583     case '=':
3584       {
3585         sym_link *rtype = operandType (right);
3586         sym_link *ltype = operandType (left);
3587         if (IS_PTR (rtype) && IS_ITEMP (right)
3588             && right->isaddr && compareType (rtype->next, ltype) == 1)
3589           right = geniCodeRValue (right, TRUE);
3590         else
3591           right = geniCodeRValue (right, FALSE);
3592
3593         geniCodeAssign (left, right, 0);
3594         return right;
3595       }
3596     case MUL_ASSIGN:
3597       return
3598         geniCodeAssign (left,
3599                 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3600                                                   FALSE),
3601                                   geniCodeRValue (right, FALSE),FALSE), 0);
3602
3603     case DIV_ASSIGN:
3604       return
3605         geniCodeAssign (left,
3606                 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3607                                                   FALSE),
3608                                   geniCodeRValue (right, FALSE)), 0);
3609     case MOD_ASSIGN:
3610       return
3611         geniCodeAssign (left,
3612                  geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3613                                                   FALSE),
3614                                   geniCodeRValue (right, FALSE)), 0);
3615     case ADD_ASSIGN:
3616       {
3617         sym_link *rtype = operandType (right);
3618         sym_link *ltype = operandType (left);
3619         if (IS_PTR (rtype) && IS_ITEMP (right)
3620             && right->isaddr && compareType (rtype->next, ltype) == 1)
3621           right = geniCodeRValue (right, TRUE);
3622         else
3623           right = geniCodeRValue (right, FALSE);
3624
3625
3626         return geniCodeAssign (left,
3627                      geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3628                                                   FALSE),
3629                                   right,lvl), 0);
3630       }
3631     case SUB_ASSIGN:
3632       {
3633         sym_link *rtype = operandType (right);
3634         sym_link *ltype = operandType (left);
3635         if (IS_PTR (rtype) && IS_ITEMP (right)
3636             && right->isaddr && compareType (rtype->next, ltype) == 1)
3637           {
3638             right = geniCodeRValue (right, TRUE);
3639           }
3640         else
3641           {
3642             right = geniCodeRValue (right, FALSE);
3643           }
3644         return
3645           geniCodeAssign (left,
3646                 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3647                                                   FALSE),
3648                                   right), 0);
3649       }
3650     case LEFT_ASSIGN:
3651       return
3652         geniCodeAssign (left,
3653                 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3654                                                    ,FALSE),
3655                                    geniCodeRValue (right, FALSE)), 0);
3656     case RIGHT_ASSIGN:
3657       return
3658         geniCodeAssign (left,
3659                geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3660                                                    ,FALSE),
3661                                    geniCodeRValue (right, FALSE)), 0);
3662     case AND_ASSIGN:
3663       return
3664         geniCodeAssign (left,
3665                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3666                                                   FALSE),
3667                                   geniCodeRValue (right, FALSE),
3668                                   BITWISEAND,
3669                                   operandType (left)), 0);
3670     case XOR_ASSIGN:
3671       return
3672         geniCodeAssign (left,
3673                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3674                                                   FALSE),
3675                                   geniCodeRValue (right, FALSE),
3676                                   '^',
3677                                   operandType (left)), 0);
3678     case OR_ASSIGN:
3679       return
3680         geniCodeAssign (left,
3681                   geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3682                                                    ,FALSE),
3683                                    geniCodeRValue (right, FALSE),
3684                                    '|',
3685                                    operandType (left)), 0);
3686     case ',':
3687       return geniCodeRValue (right, FALSE);
3688
3689     case CALL:
3690       return geniCodeCall (ast2iCode (tree->left,lvl+1),
3691                            tree->right,lvl);
3692     case LABEL:
3693       geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3694       return ast2iCode (tree->right,lvl+1);
3695
3696     case GOTO:
3697       geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3698       return ast2iCode (tree->right,lvl+1);
3699
3700     case FUNCTION:
3701       geniCodeFunctionBody (tree,lvl);
3702       return NULL;
3703
3704     case RETURN:
3705       geniCodeReturn (right);
3706       return NULL;
3707
3708     case IFX:
3709       geniCodeIfx (tree,lvl);
3710       return NULL;
3711
3712     case SWITCH:
3713       geniCodeSwitch (tree,lvl);
3714       return NULL;
3715
3716     case INLINEASM:
3717       geniCodeInline (tree);
3718       return NULL;
3719         
3720     case ARRAYINIT:
3721         geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3722         return NULL;
3723     }
3724
3725   return NULL;
3726 }
3727
3728 /*-----------------------------------------------------------------*/
3729 /* reverseICChain - gets from the list and creates a linkedlist    */
3730 /*-----------------------------------------------------------------*/
3731 iCode *
3732 reverseiCChain ()
3733 {
3734   iCode *loop = NULL;
3735   iCode *prev = NULL;
3736
3737   while ((loop = getSet (&iCodeChain)))
3738     {
3739       loop->next = prev;
3740       if (prev)
3741         prev->prev = loop;
3742       prev = loop;
3743     }
3744
3745   return prev;
3746 }
3747
3748
3749 /*-----------------------------------------------------------------*/
3750 /* iCodeFromAst - given an ast will convert it to iCode            */
3751 /*-----------------------------------------------------------------*/
3752 iCode *
3753 iCodeFromAst (ast * tree)
3754 {
3755   returnLabel = newiTempLabel ("_return");
3756   entryLabel = newiTempLabel ("_entry");
3757   ast2iCode (tree,0);
3758   return reverseiCChain ();
3759 }
3760
3761 static const char *opTypeToStr(OPTYPE op)
3762 {
3763     switch(op)
3764     {
3765       case SYMBOL: return "symbol";
3766       case VALUE: return "value";
3767       case TYPE: return "type";
3768     }
3769     return "undefined type";    
3770 }
3771
3772
3773 operand *validateOpType(operand         *op, 
3774                         const char      *macro,
3775                         const char      *args,
3776                         OPTYPE          type,
3777                         const char      *file, 
3778                         unsigned        line)
3779 {    
3780     if (op && op->type == type)
3781     {
3782         return op;
3783     }
3784     fprintf(stderr, 
3785             "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
3786             " expected %s, got %s\n",
3787             macro, args, file, line, 
3788             opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
3789     exit(-1);
3790     return op; // never reached, makes compiler happy.
3791 }