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