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