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