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