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