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