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