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