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