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