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