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