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