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