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