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