Removed a warning
[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   if (IS_ITEMP (op) && !chkTemp)
843     return 0;
844
845   return IS_VOLATILE(operandType(op));
846 }
847
848 /*-----------------------------------------------------------------*/
849 /* isOperandLiteral - returns 1 if an operand contains a literal   */
850 /*-----------------------------------------------------------------*/
851 int 
852 isOperandLiteral (operand * op)
853 {
854   sym_link *opetype;
855
856   if (!op)
857     return 0;
858
859   opetype = getSpec (operandType (op));
860
861   if (IS_LITERAL (opetype))
862     return 1;
863
864   return 0;
865 }
866
867 /*-----------------------------------------------------------------*/
868 /* isOperandInFarSpace - will return true if operand is in farSpace */
869 /*-----------------------------------------------------------------*/
870 bool 
871 isOperandInFarSpace (operand * op)
872 {
873   sym_link *etype;
874
875   if (!op)
876     return FALSE;
877
878   if (!IS_SYMOP (op))
879     return FALSE;
880
881   if (!IS_TRUE_SYMOP (op))
882     {
883       if (SPIL_LOC (op))
884         etype = SPIL_LOC (op)->etype;
885       else
886         return FALSE;
887     }
888   else
889     {
890       etype = getSpec (operandType (op));
891     }
892   return (IN_FARSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
893 }
894
895 /*------------------------------------------------------------------*/
896 /* isOperandInDirSpace - will return true if operand is in dirSpace */
897 /*------------------------------------------------------------------*/
898 bool 
899 isOperandInDirSpace (operand * op)
900 {
901   sym_link *etype;
902
903   if (!op)
904     return FALSE;
905
906   if (!IS_SYMOP (op))
907     return FALSE;
908
909   if (!IS_TRUE_SYMOP (op))
910     {
911       if (SPIL_LOC (op))
912         etype = SPIL_LOC (op)->etype;
913       else
914         return FALSE;
915     }
916   else
917     {
918       etype = getSpec (operandType (op));
919     }
920   return (IN_DIRSPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
921 }
922
923 /*--------------------------------------------------------------------*/
924 /* isOperandInCodeSpace - will return true if operand is in codeSpace */
925 /*--------------------------------------------------------------------*/
926 bool 
927 isOperandInCodeSpace (operand * op)
928 {
929   sym_link *etype;
930
931   if (!op)
932     return FALSE;
933
934   if (!IS_SYMOP (op))
935     return FALSE;
936
937   etype = getSpec (operandType (op));
938
939   if (!IS_TRUE_SYMOP (op))
940     {
941       if (SPIL_LOC (op))
942         etype = SPIL_LOC (op)->etype;
943       else
944         return FALSE;
945     }
946   else
947     {
948       etype = getSpec (operandType (op));
949     }
950   return (IN_CODESPACE (SPEC_OCLS (etype)) ? TRUE : FALSE);
951 }
952
953 /*-----------------------------------------------------------------*/
954 /* isOperandOnStack - will return true if operand is on stack      */
955 /*-----------------------------------------------------------------*/
956 bool 
957 isOperandOnStack (operand * op)
958 {
959   sym_link *etype;
960
961   if (!op)
962     return FALSE;
963
964   if (!IS_SYMOP (op))
965     return FALSE;
966
967   etype = getSpec (operandType (op));
968   if (IN_STACK (etype) ||
969       OP_SYMBOL(op)->onStack ||
970       (SPIL_LOC(op) && SPIL_LOC(op)->onStack))
971     return TRUE;
972
973   return FALSE;
974 }
975
976 /*-----------------------------------------------------------------*/
977 /* operandLitValue - literal value of an operand                   */
978 /*-----------------------------------------------------------------*/
979 double 
980 operandLitValue (operand * op)
981 {
982   assert (isOperandLiteral (op));
983
984   return floatFromVal (op->operand.valOperand);
985 }
986
987 /*-----------------------------------------------------------------*/
988 /* getBuiltInParms - returns parameters to a builtin functions     */
989 /*-----------------------------------------------------------------*/
990 iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms)
991 {
992     sym_link *ftype;
993
994     *pcount = 0;
995     /* builtin functions uses only SEND for parameters */
996     while (ic->op != CALL) {
997         assert(ic->op == SEND && ic->builtinSEND);
998         ic->generated = 1;    /* mark the icode as generated */
999         parms[*pcount] = IC_LEFT(ic);
1000         ic = ic->next;
1001         (*pcount)++;
1002     }
1003     
1004     ic->generated = 1;
1005     /* make sure this is a builtin function call */
1006     assert(IS_SYMOP(IC_LEFT(ic)));
1007     ftype = operandType(IC_LEFT(ic));
1008     assert(IFFUNC_ISBUILTIN(ftype));
1009     return ic;
1010 }
1011
1012 /*-----------------------------------------------------------------*/
1013 /* operandOperation - perforoms operations on operands             */
1014 /*-----------------------------------------------------------------*/
1015 operand *
1016 operandOperation (operand * left, operand * right,
1017                   int op, sym_link * type)
1018 {
1019   sym_link *let , *ret=NULL;
1020   operand *retval = (operand *) 0;
1021   
1022   assert (isOperandLiteral (left));
1023   let = getSpec(operandType(left));
1024   if (right) {
1025     assert (isOperandLiteral (right));
1026     ret = getSpec(operandType(left));
1027   }
1028
1029   switch (op)
1030     {
1031     case '+':
1032       retval = operandFromValue (valCastLiteral (type,
1033                                                  operandLitValue (left) +
1034                                                  operandLitValue (right)));
1035       break;
1036     case '-':
1037       retval = operandFromValue (valCastLiteral (type,
1038                                                  operandLitValue (left) -
1039                                                  operandLitValue (right)));
1040       break;
1041     case '*':
1042       retval = operandFromValue (valCastLiteral (type,
1043                                                  operandLitValue (left) *
1044                                                  operandLitValue (right)));
1045       break;
1046     case '/':
1047       if ((unsigned long) operandLitValue (right) == 0)
1048         {
1049           werror (E_DIVIDE_BY_ZERO);
1050           retval = right;
1051
1052         }
1053       else
1054         retval = operandFromValue (valCastLiteral (type,
1055                                                    operandLitValue (left) /
1056                                                    operandLitValue (right)));
1057       break;
1058     case '%':
1059       if ((unsigned long) operandLitValue (right) == 0) {
1060           werror (E_DIVIDE_BY_ZERO);
1061           retval = right;
1062       }
1063       else 
1064         retval = operandFromLit ((SPEC_USIGN(let) ? 
1065                                   (unsigned long) operandLitValue (left) :
1066                                   (long) operandLitValue (left)) %
1067                                  (SPEC_USIGN(ret) ? 
1068                                   (unsigned long) operandLitValue (right) :
1069                                   (long) operandLitValue (right)));
1070
1071       break;
1072     case LEFT_OP:
1073       retval = operandFromLit ((SPEC_USIGN(let) ? 
1074                                   (unsigned long) operandLitValue (left) :
1075                                   (long) operandLitValue (left)) <<
1076                                  (SPEC_USIGN(ret) ? 
1077                                   (unsigned long) operandLitValue (right) :
1078                                   (long) operandLitValue (right)));
1079       break;
1080     case RIGHT_OP: {
1081       double lval = operandLitValue(left), rval = operandLitValue(right);
1082       double res=0;
1083       switch ((SPEC_USIGN(let) ? 2 : 0) + (SPEC_USIGN(ret) ? 1 : 0)) 
1084         {
1085         case 0: // left=unsigned right=unsigned
1086           res=(unsigned long)lval >> (unsigned long)rval;
1087           break;
1088         case 1: // left=unsigned right=signed
1089           res=(unsigned long)lval >> (signed long)rval;
1090           break;
1091         case 2: // left=signed right=unsigned
1092           res=(signed long)lval >> (unsigned long)rval;
1093           break;
1094         case 3: // left=signed right=signed
1095           res=(signed long)lval >> (signed long)rval;
1096           break;
1097         }
1098       retval = operandFromLit (res);
1099       break;
1100     }
1101     case EQ_OP:
1102       retval = operandFromLit (operandLitValue (left) ==
1103                                operandLitValue (right));
1104       break;
1105     case '<':
1106       retval = operandFromLit (operandLitValue (left) <
1107                                operandLitValue (right));
1108       break;
1109     case LE_OP:
1110       retval = operandFromLit (operandLitValue (left) <=
1111                                operandLitValue (right));
1112       break;
1113     case NE_OP:
1114       retval = operandFromLit (operandLitValue (left) !=
1115                                operandLitValue (right));
1116       break;
1117     case '>':
1118       retval = operandFromLit (operandLitValue (left) >
1119                                operandLitValue (right));
1120       break;
1121     case GE_OP:
1122       retval = operandFromLit (operandLitValue (left) >=
1123                                operandLitValue (right));
1124       break;
1125     case BITWISEAND:
1126       retval = operandFromLit ((long)operandLitValue(left) & 
1127                                (long)operandLitValue(right));
1128       break;
1129     case '|':
1130       retval = operandFromLit ((long)operandLitValue (left) |
1131                                (long)operandLitValue (right));
1132       break;
1133     case '^':
1134       retval = operandFromLit ((long)operandLitValue (left) ^
1135                                (long)operandLitValue (right));
1136       break;
1137     case AND_OP:
1138       retval = operandFromLit (operandLitValue (left) &&
1139                                operandLitValue (right));
1140       break;
1141     case OR_OP:
1142       retval = operandFromLit (operandLitValue (left) ||
1143                                operandLitValue (right));
1144       break;
1145     case RRC:
1146       {
1147         long i = (long) operandLitValue (left);
1148
1149         retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
1150                                  (i << 1));
1151       }
1152       break;
1153     case RLC:
1154       {
1155         long i = (long) operandLitValue (left);
1156
1157         retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
1158                                  (i >> 1));
1159       }
1160       break;
1161
1162     case UNARYMINUS:
1163       retval = operandFromLit (-1 * operandLitValue (left));
1164       break;
1165
1166     case '~':
1167       retval = operandFromLit (~((long) operandLitValue (left)));
1168       break;
1169
1170     case '!':
1171       retval = operandFromLit (!operandLitValue (left));
1172       break;
1173
1174     default:
1175       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1176               " operandOperation invalid operator ");
1177       assert (0);
1178     }
1179
1180   return retval;
1181 }
1182
1183
1184 /*-----------------------------------------------------------------*/
1185 /* isOperandEqual - compares two operand & return 1 if they r =    */
1186 /*-----------------------------------------------------------------*/
1187 int 
1188 isOperandEqual (operand * left, operand * right)
1189 {
1190   /* if the pointers are equal then they are equal */
1191   if (left == right)
1192     return 1;
1193
1194   /* if either of them null then false */
1195   if (!left || !right)
1196     return 0;
1197
1198   if (left->type != right->type)
1199     return 0;
1200
1201   if (IS_SYMOP (left) && IS_SYMOP (right))
1202     return left->key == right->key;
1203
1204   /* if types are the same */
1205   switch (left->type)
1206     {
1207     case SYMBOL:
1208       return isSymbolEqual (left->operand.symOperand,
1209                             right->operand.symOperand);
1210     case VALUE:
1211       return (floatFromVal (left->operand.valOperand) ==
1212               floatFromVal (right->operand.valOperand));
1213     case TYPE:
1214       if (compareType (left->operand.typeOperand,
1215                      right->operand.typeOperand) == 1)
1216         return 1;
1217     }
1218
1219   return 0;
1220 }
1221
1222 /*-------------------------------------------------------------------*/
1223 /* isiCodeEqual - compares two iCodes are equal, returns true if yes */
1224 /*-------------------------------------------------------------------*/
1225 int 
1226 isiCodeEqual (iCode * left, iCode * right)
1227 {
1228   /* if the same pointer */
1229   if (left == right)
1230     return 1;
1231
1232   /* if either of them null */
1233   if (!left || !right)
1234     return 0;
1235
1236   /* if operand are the same */
1237   if (left->op == right->op)
1238     {
1239
1240       /* compare all the elements depending on type */
1241       if (left->op != IFX)
1242         {
1243           if (!isOperandEqual (IC_LEFT (left), IC_LEFT (right)))
1244             return 0;
1245           if (!isOperandEqual (IC_RIGHT (left), IC_RIGHT (right)))
1246             return 0;
1247
1248         }
1249       else
1250         {
1251           if (!isOperandEqual (IC_COND (left), IC_COND (right)))
1252             return 0;
1253           if (!isSymbolEqual (IC_TRUE (left), IC_TRUE (right)))
1254             return 0;
1255           if (!isSymbolEqual (IC_FALSE (left), IC_FALSE (right)))
1256             return 0;
1257         }
1258       
1259       return 1;
1260     }
1261   return 0;
1262 }
1263
1264 /*-----------------------------------------------------------------*/
1265 /* newiTempFromOp - create a temp Operand with same attributes     */
1266 /*-----------------------------------------------------------------*/
1267 operand *
1268 newiTempFromOp (operand * op)
1269 {
1270   operand *nop;
1271
1272   if (!op)
1273     return NULL;
1274
1275   if (!IS_ITEMP (op))
1276     return op;
1277
1278   nop = newiTempOperand (operandType (op), TRUE);
1279   nop->isaddr = op->isaddr;
1280   nop->isvolatile = op->isvolatile;
1281   nop->isGlobal = op->isGlobal;
1282   nop->isLiteral = op->isLiteral;
1283   nop->usesDefs = op->usesDefs;
1284   nop->isParm = op->isParm;
1285   return nop;
1286 }
1287
1288 /*-----------------------------------------------------------------*/
1289 /* operand from operand - creates an operand holder for the type   */
1290 /*-----------------------------------------------------------------*/
1291 operand *
1292 operandFromOperand (operand * op)
1293 {
1294   operand *nop;
1295
1296   if (!op)
1297     return NULL;
1298   nop = newOperand ();
1299   nop->type = op->type;
1300   nop->isaddr = op->isaddr;
1301   nop->key = op->key;
1302   nop->isvolatile = op->isvolatile;
1303   nop->isGlobal = op->isGlobal;
1304   nop->isLiteral = op->isLiteral;
1305   nop->usesDefs = op->usesDefs;
1306   nop->isParm = op->isParm;
1307
1308   switch (nop->type)
1309     {
1310     case SYMBOL:
1311       nop->operand.symOperand = op->operand.symOperand;
1312       break;
1313     case VALUE:
1314       nop->operand.valOperand = op->operand.valOperand;
1315       break;
1316     case TYPE:
1317       nop->operand.typeOperand = op->operand.typeOperand;
1318       break;
1319     }
1320
1321   return nop;
1322 }
1323
1324 /*-----------------------------------------------------------------*/
1325 /* opFromOpWithDU - makes a copy of the operand and DU chains      */
1326 /*-----------------------------------------------------------------*/
1327 operand *
1328 opFromOpWithDU (operand * op, bitVect * defs, bitVect * uses)
1329 {
1330   operand *nop = operandFromOperand (op);
1331
1332   if (nop->type == SYMBOL)
1333     {
1334       OP_SYMBOL (nop)->defs = bitVectCopy (defs);
1335       OP_SYMBOL (nop)->uses = bitVectCopy (uses);
1336     }
1337
1338   return nop;
1339 }
1340
1341 /*-----------------------------------------------------------------*/
1342 /* operandFromSymbol - creates an operand from a symbol            */
1343 /*-----------------------------------------------------------------*/
1344 operand *
1345 operandFromSymbol (symbol * sym)
1346 {
1347   operand *op;
1348   iCode *ic;
1349   int ok = 1;
1350   /* if the symbol's type is a literal */
1351   /* then it is an enumerator type     */
1352   if (IS_LITERAL (sym->etype) && SPEC_ENUM (sym->etype))
1353     return operandFromValue (valFromType (sym->etype));
1354
1355   if (!sym->key)
1356     sym->key = ++operandKey;
1357
1358   /* if this an implicit variable, means struct/union */
1359   /* member so just return it                         */
1360   if (sym->implicit || IS_FUNC (sym->type))
1361     {
1362       op = newOperand ();
1363       op->type = SYMBOL;
1364       op->operand.symOperand = sym;
1365       op->key = sym->key;
1366       op->isvolatile = isOperandVolatile (op, TRUE);
1367       op->isGlobal = isOperandGlobal (op);
1368       return op;
1369     }
1370
1371   /* under the following conditions create a
1372      register equivalent for a local symbol */
1373   if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
1374       (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
1375       (!(options.model == MODEL_FLAT24)) ) &&
1376       options.stackAuto == 0)
1377     ok = 0;
1378
1379   if (!IS_AGGREGATE (sym->type) &&      /* not an aggregate */
1380       !IS_FUNC (sym->type) &&   /* not a function   */
1381       !sym->_isparm &&          /* not a parameter  */
1382       sym->level &&             /* is a local variable */
1383       !sym->addrtaken &&        /* whose address has not been taken */
1384       !sym->reqv &&             /* does not already have a reg equivalence */
1385       !IS_VOLATILE (sym->etype) &&      /* not declared as volatile */
1386       !IS_STATIC (sym->etype) &&        /* and not declared static  */
1387       !sym->islbl &&            /* not a label */
1388       ok &&                     /* farspace check */
1389       !IS_BITVAR (sym->etype)   /* not a bit variable */
1390     )
1391     {
1392
1393       /* we will use it after all optimizations
1394          and before liveRange calculation */
1395       sym->reqv = newiTempOperand (sym->type, 0);
1396       sym->reqv->key = sym->key;
1397       OP_SYMBOL (sym->reqv)->key = sym->key;
1398       OP_SYMBOL (sym->reqv)->isreqv = 1;
1399       OP_SYMBOL (sym->reqv)->islocal = 1;
1400       OP_SYMBOL (sym->reqv)->onStack = sym->onStack;
1401       SPIL_LOC (sym->reqv) = sym;
1402     }
1403
1404   if (!IS_AGGREGATE (sym->type))
1405     {
1406       op = newOperand ();
1407       op->type = SYMBOL;
1408       op->operand.symOperand = sym;
1409       op->isaddr = 1;
1410       op->key = sym->key;
1411       op->isvolatile = isOperandVolatile (op, TRUE);
1412       op->isGlobal = isOperandGlobal (op);
1413       op->isPtr = IS_PTR (operandType (op));
1414       op->isParm = sym->_isparm;
1415       return op;
1416     }
1417
1418   /* create :-                     */
1419   /*    itemp = &[_symbol]         */
1420
1421   ic = newiCode (ADDRESS_OF, newOperand (), NULL);
1422   IC_LEFT (ic)->type = SYMBOL;
1423   IC_LEFT (ic)->operand.symOperand = sym;
1424   IC_LEFT (ic)->key = sym->key;
1425   (IC_LEFT (ic))->isvolatile = isOperandVolatile (IC_LEFT (ic), TRUE);
1426   (IC_LEFT (ic))->isGlobal = isOperandGlobal (IC_LEFT (ic));
1427   IC_LEFT (ic)->isPtr = IS_PTR (operandType (IC_LEFT (ic)));
1428
1429   /* create result */
1430   IC_RESULT (ic) = newiTempOperand (sym->type, 0);
1431   if (IS_ARRAY (sym->type))
1432     {
1433       IC_RESULT (ic) = geniCodeArray2Ptr (IC_RESULT (ic));
1434       IC_RESULT (ic)->isaddr = 0;
1435     }
1436   else
1437     IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (sym->type));
1438
1439   ADDTOCHAIN (ic);
1440
1441   return IC_RESULT (ic);
1442 }
1443
1444 /*-----------------------------------------------------------------*/
1445 /* operandFromValue - creates an operand from value                */
1446 /*-----------------------------------------------------------------*/
1447 operand *
1448 operandFromValue (value * val)
1449 {
1450   operand *op;
1451
1452   /* if this is a symbol then do the symbol thing */
1453   if (val->sym)
1454     return operandFromSymbol (val->sym);
1455
1456   /* this is not a symbol */
1457   op = newOperand ();
1458   op->type = VALUE;
1459   op->operand.valOperand = val;
1460   op->isLiteral = isOperandLiteral (op);
1461   return op;
1462 }
1463
1464 /*-----------------------------------------------------------------*/
1465 /* operandFromLink - operand from typeChain                        */
1466 /*-----------------------------------------------------------------*/
1467 operand *
1468 operandFromLink (sym_link * type)
1469 {
1470   operand *op;
1471
1472   /* operand from sym_link */
1473   if (!type)
1474     return NULL;
1475
1476   op = newOperand ();
1477   op->type = TYPE;
1478   op->operand.typeOperand = copyLinkChain (type);
1479   return op;
1480 }
1481
1482 /*-----------------------------------------------------------------*/
1483 /* operandFromLit - makes an operand from a literal value          */
1484 /*-----------------------------------------------------------------*/
1485 operand *
1486 operandFromLit (double i)
1487 {
1488   return operandFromValue (valueFromLit (i));
1489 }
1490
1491 /*-----------------------------------------------------------------*/
1492 /* operandFromAst - creates an operand from an ast                 */
1493 /*-----------------------------------------------------------------*/
1494 operand *
1495 operandFromAst (ast * tree,int lvl)
1496 {
1497
1498   if (!tree)
1499     return NULL;
1500
1501   /* depending on type do */
1502   switch (tree->type)
1503     {
1504     case EX_OP:
1505       return ast2iCode (tree,lvl+1);
1506       break;
1507
1508     case EX_VALUE:
1509       return operandFromValue (tree->opval.val);
1510       break;
1511
1512     case EX_LINK:
1513       return operandFromLink (tree->opval.lnk);
1514     }
1515
1516   assert (0);
1517   /*  Just to keep the comiler happy */
1518   return (operand *) 0;
1519 }
1520
1521 /*-----------------------------------------------------------------*/
1522 /* setOperandType - sets the operand's type to the given type      */
1523 /*-----------------------------------------------------------------*/
1524 void 
1525 setOperandType (operand * op, sym_link * type)
1526 {
1527   /* depending on the type of operand */
1528   switch (op->type)
1529     {
1530
1531     case VALUE:
1532       op->operand.valOperand->etype =
1533         getSpec (op->operand.valOperand->type =
1534                  copyLinkChain (type));
1535       return;
1536
1537     case SYMBOL:
1538       if (op->operand.symOperand->isitmp)
1539         op->operand.symOperand->etype =
1540           getSpec (op->operand.symOperand->type =
1541                    copyLinkChain (type));
1542       else
1543         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1544                 "attempt to modify type of source");
1545       return;
1546
1547     case TYPE:
1548       op->operand.typeOperand = copyLinkChain (type);
1549       return;
1550     }
1551
1552 }
1553 /*-----------------------------------------------------------------*/
1554 /* Get size in byte of ptr need to access an array                 */
1555 /*-----------------------------------------------------------------*/
1556 int
1557 getArraySizePtr (operand * op)
1558 {
1559   sym_link *ltype = operandType(op);
1560
1561   if(IS_PTR(ltype))
1562     {
1563       int size = getSize(ltype);
1564       return(IS_GENPTR(ltype)?(size-1):size);
1565     }
1566
1567   if(IS_ARRAY(ltype))
1568     {
1569       sym_link *letype = getSpec(ltype);
1570       switch (PTR_TYPE (SPEC_OCLS (letype)))
1571         {
1572         case IPOINTER:
1573         case PPOINTER:
1574         case POINTER:
1575           return (PTRSIZE);
1576         case EEPPOINTER:
1577         case FPOINTER:
1578         case CPOINTER:
1579         case FUNCTION:
1580           return (FPTRSIZE);
1581         case GPOINTER:
1582           return (GPTRSIZE-1);
1583
1584         default:
1585           return (FPTRSIZE);
1586         }
1587     }
1588   return (FPTRSIZE);
1589 }
1590
1591 /*-----------------------------------------------------------------*/
1592 /* perform "usual unary conversions"                               */
1593 /*-----------------------------------------------------------------*/
1594 operand *
1595 usualUnaryConversions (operand * op)
1596 {
1597   if (IS_INTEGRAL (operandType (op)))
1598     {
1599       if (getSize (operandType (op)) < (unsigned int) INTSIZE)
1600         {
1601           /* Widen to int. */
1602           return geniCodeCast (INTTYPE, op, TRUE);
1603         }
1604     }
1605   return op;
1606 }
1607
1608 /*-----------------------------------------------------------------*/
1609 /* perform "usual binary conversions"                              */
1610 /*-----------------------------------------------------------------*/
1611 sym_link *
1612 usualBinaryConversions (operand ** op1, operand ** op2)
1613 {
1614   sym_link *ctype;
1615   sym_link *rtype = operandType (*op2);
1616   sym_link *ltype = operandType (*op1);
1617   
1618   ctype = computeType (ltype, rtype);
1619
1620   *op1 = geniCodeCast (ctype, *op1, TRUE);
1621   *op2 = geniCodeCast (ctype, *op2, TRUE);
1622   
1623   return ctype;
1624 }
1625
1626 /*-----------------------------------------------------------------*/
1627 /* geniCodeValueAtAddress - generate intermeditate code for value  */
1628 /*                          at address                             */
1629 /*-----------------------------------------------------------------*/
1630 operand *
1631 geniCodeRValue (operand * op, bool force)
1632 {
1633   iCode *ic;
1634   sym_link *type = operandType (op);
1635   sym_link *etype = getSpec (type);
1636
1637   /* if this is an array & already */
1638   /* an address then return this   */
1639   if (IS_AGGREGATE (type) ||
1640       (IS_PTR (type) && !force && !op->isaddr))
1641     return operandFromOperand (op);
1642
1643   /* if this is not an address then must be */
1644   /* rvalue already so return this one      */
1645   if (!op->isaddr)
1646     return op;
1647
1648   /* if this is not a temp symbol then */
1649   if (!IS_ITEMP (op) &&
1650       !force &&
1651       !IN_FARSPACE (SPEC_OCLS (etype)))
1652     {
1653       op = operandFromOperand (op);
1654       op->isaddr = 0;
1655       return op;
1656     }
1657
1658   if (IS_SPEC (type) &&
1659       IS_TRUE_SYMOP (op) &&
1660       (!IN_FARSPACE (SPEC_OCLS (etype)) ||
1661       (options.model == MODEL_FLAT24) ))
1662     {
1663       op = operandFromOperand (op);
1664       op->isaddr = 0;
1665       return op;
1666     }
1667
1668   ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
1669   if (IS_PTR (type) && op->isaddr && force)
1670     type = type->next;
1671
1672   type = copyLinkChain (type);
1673
1674   IC_RESULT (ic) = newiTempOperand (type, 1);
1675   IC_RESULT (ic)->isaddr = 0;
1676
1677 /*     ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1678
1679   ADDTOCHAIN (ic);
1680
1681   return IC_RESULT (ic);
1682 }
1683
1684 /*-----------------------------------------------------------------*/
1685 /* geniCodeCast - changes the value from one type to another       */
1686 /*-----------------------------------------------------------------*/
1687 operand *
1688 geniCodeCast (sym_link * type, operand * op, bool implicit)
1689 {
1690   iCode *ic;
1691   sym_link *optype;
1692   sym_link *opetype = getSpec (optype = operandType (op));
1693   sym_link *restype;
1694   int errors=0;
1695
1696   /* one of them has size zero then error */
1697   if (IS_VOID (optype))
1698     {
1699       werror (E_CAST_ZERO);
1700       return op;
1701     }
1702
1703   /* if the operand is already the desired type then do nothing */
1704   if (compareType (type, optype) == 1)
1705     return op;
1706
1707   /* if this is a literal then just change the type & return */
1708   if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
1709     return operandFromValue (valCastLiteral (type,
1710                                              operandLitValue (op)));
1711
1712   /* if casting to/from pointers, do some checking */
1713   if (IS_PTR(type)) { // to a pointer
1714     if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
1715       if (IS_INTEGRAL(optype)) { 
1716         // maybe this is NULL, than it's ok. 
1717         if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
1718           if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
1719             // no way to set the storage
1720             if (IS_LITERAL(optype)) {
1721               werror(E_LITERAL_GENERIC);
1722               errors++;
1723             } else {
1724               werror(E_NONPTR2_GENPTR);
1725               errors++;
1726             }
1727           } else if (implicit) {
1728             werror(W_INTEGRAL2PTR_NOCAST);
1729             errors++;
1730           }
1731         }
1732       } else { 
1733         // shouldn't do that with float, array or structure unless to void
1734         if (!IS_VOID(getSpec(type)) && 
1735             !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1736           werror(E_INCOMPAT_TYPES);
1737           errors++;
1738         }
1739       }
1740     } else { // from a pointer to a pointer
1741       if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
1742         // if not a pointer to a function
1743         if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
1744           if (implicit) { // if not to generic, they have to match 
1745             if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
1746               werror(E_INCOMPAT_PTYPES);
1747               errors++;
1748             }
1749           }
1750         }
1751       }
1752     }
1753   } else { // to a non pointer
1754     if (IS_PTR(optype)) { // from a pointer
1755       if (implicit) { // sneaky
1756         if (IS_INTEGRAL(type)) {
1757           werror(W_PTR2INTEGRAL_NOCAST);
1758           errors++;
1759         } else { // shouldn't do that with float, array or structure
1760           werror(E_INCOMPAT_TYPES);
1761           errors++;
1762         }
1763       }
1764     }
1765   }
1766   if (errors) {
1767     printFromToType (optype, type);
1768   }
1769
1770   /* if they are the same size create an assignment */
1771   if (getSize (type) == getSize (optype) &&
1772       !IS_BITFIELD (type) &&
1773       !IS_FLOAT (type) &&
1774       !IS_FLOAT (optype) &&
1775       ((IS_SPEC (type) && IS_SPEC (optype)) ||
1776        (!IS_SPEC (type) && !IS_SPEC (optype))))
1777     {
1778
1779       ic = newiCode ('=', NULL, op);
1780       IC_RESULT (ic) = newiTempOperand (type, 0);
1781       SPIL_LOC (IC_RESULT (ic)) =
1782         (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
1783       IC_RESULT (ic)->isaddr = 0;
1784     }
1785   else
1786     {
1787       ic = newiCode (CAST, operandFromLink (type),
1788                      geniCodeRValue (op, FALSE));
1789
1790       IC_RESULT (ic) = newiTempOperand (type, 0);
1791     }
1792
1793   /* preserve the storage class & output class */
1794   /* of the original variable                  */
1795   restype = getSpec (operandType (IC_RESULT (ic)));
1796   if (!IS_LITERAL(opetype))
1797       SPEC_SCLS (restype) = SPEC_SCLS (opetype);
1798   SPEC_OCLS (restype) = SPEC_OCLS (opetype);
1799
1800   ADDTOCHAIN (ic);
1801   return IC_RESULT (ic);
1802 }
1803
1804 /*-----------------------------------------------------------------*/
1805 /* geniCodeLabel - will create a Label                             */
1806 /*-----------------------------------------------------------------*/
1807 void 
1808 geniCodeLabel (symbol * label)
1809 {
1810   iCode *ic;
1811
1812   ic = newiCodeLabelGoto (LABEL, label);
1813   ADDTOCHAIN (ic);
1814 }
1815
1816 /*-----------------------------------------------------------------*/
1817 /* geniCodeGoto  - will create a Goto                              */
1818 /*-----------------------------------------------------------------*/
1819 void 
1820 geniCodeGoto (symbol * label)
1821 {
1822   iCode *ic;
1823
1824   ic = newiCodeLabelGoto (GOTO, label);
1825   ADDTOCHAIN (ic);
1826 }
1827
1828 /*-----------------------------------------------------------------*/
1829 /* geniCodeMultiply - gen intermediate code for multiplication     */
1830 /*-----------------------------------------------------------------*/
1831 operand *
1832 geniCodeMultiply (operand * left, operand * right,int resultIsInt)
1833 {
1834   iCode *ic;
1835   int p2 = 0;
1836   sym_link *resType;
1837   LRTYPE;
1838
1839   /* if they are both literal then we know the result */
1840   if (IS_LITERAL (letype) && IS_LITERAL (retype))
1841     return operandFromValue (valMult (left->operand.valOperand,
1842                                       right->operand.valOperand));
1843
1844   if (IS_LITERAL(retype)) {
1845     p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
1846   }
1847
1848   resType = usualBinaryConversions (&left, &right);
1849 #if 1
1850   rtype = operandType (right);
1851   retype = getSpec (rtype);
1852   ltype = operandType (left);
1853   letype = getSpec (ltype);
1854 #endif
1855   if (resultIsInt)
1856     {
1857       SPEC_NOUN(getSpec(resType))=V_INT;
1858     }
1859
1860   /* if the right is a literal & power of 2 */
1861   /* then make it a left shift              */
1862   /* code generated for 1 byte * 1 byte literal = 2 bytes result is more 
1863      efficient in most cases than 2 bytes result = 2 bytes << literal 
1864      if port has 1 byte muldiv */
1865   if (p2 && !IS_FLOAT (letype) &&
1866       !((resultIsInt) && (getSize (resType) != getSize (ltype)) && 
1867         (port->support.muldiv == 1)))
1868     {
1869       if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
1870         {
1871           /* LEFT_OP need same size for left and result, */
1872           left = geniCodeCast (resType, left, TRUE);
1873           ltype = operandType (left);
1874         }
1875       ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
1876     }
1877   else
1878     {
1879       ic = newiCode ('*', left, right);         /* normal multiplication */
1880       /* if the size left or right > 1 then support routine */
1881       if (getSize (ltype) > 1 || getSize (rtype) > 1)
1882         ic->supportRtn = 1;
1883
1884     }
1885   IC_RESULT (ic) = newiTempOperand (resType, 1);
1886
1887   ADDTOCHAIN (ic);
1888   return IC_RESULT (ic);
1889 }
1890
1891 /*-----------------------------------------------------------------*/
1892 /* geniCodeDivision - gen intermediate code for division           */
1893 /*-----------------------------------------------------------------*/
1894 operand *
1895 geniCodeDivision (operand * left, operand * right)
1896 {
1897   iCode *ic;
1898   int p2 = 0;
1899   sym_link *resType;
1900   sym_link *rtype = operandType (right);
1901   sym_link *retype = getSpec (rtype);
1902   sym_link *ltype = operandType (left);
1903   sym_link *letype = getSpec (ltype);
1904
1905   resType = usualBinaryConversions (&left, &right);
1906
1907   /* if the right is a literal & power of 2 
1908      and left is unsigned then make it a    
1909      right shift */
1910   if (IS_LITERAL (retype) &&
1911       !IS_FLOAT (letype) &&
1912       SPEC_USIGN(letype) &&
1913       (p2 = powof2 ((unsigned long)
1914                     floatFromVal (right->operand.valOperand)))) {
1915     ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
1916   }
1917   else
1918     {
1919       ic = newiCode ('/', left, right);         /* normal division */
1920       /* if the size left or right > 1 then support routine */
1921       if (getSize (ltype) > 1 || getSize (rtype) > 1)
1922         ic->supportRtn = 1;
1923     }
1924   IC_RESULT (ic) = newiTempOperand (resType, 0);
1925
1926   ADDTOCHAIN (ic);
1927   return IC_RESULT (ic);
1928 }
1929 /*-----------------------------------------------------------------*/
1930 /* geniCodeModulus  - gen intermediate code for modulus            */
1931 /*-----------------------------------------------------------------*/
1932 operand *
1933 geniCodeModulus (operand * left, operand * right)
1934 {
1935   iCode *ic;
1936   sym_link *resType;
1937   LRTYPE;
1938
1939   /* if they are both literal then we know the result */
1940   if (IS_LITERAL (letype) && IS_LITERAL (retype))
1941     return operandFromValue (valMod (left->operand.valOperand,
1942                                      right->operand.valOperand));
1943
1944   resType = usualBinaryConversions (&left, &right);
1945
1946   /* now they are the same size */
1947   ic = newiCode ('%', left, right);
1948
1949   /* if the size left or right > 1 then support routine */
1950   if (getSize (ltype) > 1 || getSize (rtype) > 1)
1951     ic->supportRtn = 1;
1952   IC_RESULT (ic) = newiTempOperand (resType, 0);
1953
1954   ADDTOCHAIN (ic);
1955   return IC_RESULT (ic);
1956 }
1957
1958 /*-----------------------------------------------------------------*/
1959 /* geniCodePtrPtrSubtract - subtracts pointer from pointer         */
1960 /*-----------------------------------------------------------------*/
1961 operand *
1962 geniCodePtrPtrSubtract (operand * left, operand * right)
1963 {
1964   iCode *ic;
1965   operand *result;
1966   LRTYPE;
1967
1968   /* if they are both literals then */
1969   if (IS_LITERAL (letype) && IS_LITERAL (retype))
1970     {
1971       result = operandFromValue (valMinus (left->operand.valOperand,
1972                                            right->operand.valOperand));
1973       goto subtractExit;
1974     }
1975
1976   ic = newiCode ('-', left, right);
1977
1978   IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
1979   ADDTOCHAIN (ic);
1980
1981 subtractExit:
1982   if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
1983     return result;
1984   }
1985
1986   // should we really do this? is this ANSI?
1987   return geniCodeDivision (result,
1988                            operandFromLit (getSize (ltype->next)));
1989 }
1990
1991 /*-----------------------------------------------------------------*/
1992 /* geniCodeSubtract - generates code for subtraction               */
1993 /*-----------------------------------------------------------------*/
1994 operand *
1995 geniCodeSubtract (operand * left, operand * right)
1996 {
1997   iCode *ic;
1998   int isarray = 0;
1999   sym_link *resType;
2000   LRTYPE;
2001
2002   /* if they both pointers then */
2003   if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
2004       (IS_PTR (rtype) || IS_ARRAY (rtype)))
2005     return geniCodePtrPtrSubtract (left, right);
2006
2007   /* if they are both literal then we know the result */
2008   if (IS_LITERAL (letype) && IS_LITERAL (retype)
2009       && left->isLiteral && right->isLiteral)
2010     return operandFromValue (valMinus (left->operand.valOperand,
2011                                        right->operand.valOperand));
2012
2013   /* if left is an array or pointer */
2014   if (IS_PTR (ltype) || IS_ARRAY (ltype))
2015     {
2016       isarray = left->isaddr;
2017       right = geniCodeMultiply (right,
2018                                 operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2019       resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
2020     }
2021   else
2022     {                           /* make them the same size */
2023       resType = usualBinaryConversions (&left, &right);
2024     }
2025
2026   ic = newiCode ('-', left, right);
2027
2028   IC_RESULT (ic) = newiTempOperand (resType, 1);
2029   IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2030
2031   /* if left or right is a float */
2032   if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2033     ic->supportRtn = 1;
2034
2035   ADDTOCHAIN (ic);
2036   return IC_RESULT (ic);
2037 }
2038
2039 /*-----------------------------------------------------------------*/
2040 /* geniCodeAdd - generates iCode for addition                      */
2041 /*-----------------------------------------------------------------*/
2042 operand *
2043 geniCodeAdd (operand * left, operand * right, int lvl)
2044 {
2045   iCode *ic;
2046   sym_link *resType;
2047   operand *size;
2048   int isarray = 0;
2049   LRTYPE;
2050
2051 #if 0
2052   /* if left is an array then array access */
2053   if (IS_ARRAY (ltype))
2054     return geniCodeArray (left, right,lvl);
2055 #endif
2056
2057   /* if the right side is LITERAL zero */
2058   /* return the left side              */
2059   if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
2060     return left;
2061
2062   /* if left is literal zero return right */
2063   if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
2064     return right;
2065
2066   /* if left is a pointer then size */
2067   if (IS_PTR (ltype) || IS_ARRAY(ltype))
2068     {
2069       isarray = left->isaddr;
2070       // there is no need to multiply with 1
2071       if (getSize(ltype->next)!=1) {
2072         size  = operandFromLit (getSize (ltype->next));
2073         right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
2074       }
2075       resType = copyLinkChain (ltype);
2076     }
2077   else
2078     { // make them the same size
2079       resType = usualBinaryConversions (&left, &right);
2080     }
2081
2082   /* if they are both literals then we know */
2083   if (IS_LITERAL (letype) && IS_LITERAL (retype)
2084       && left->isLiteral && right->isLiteral)
2085     return operandFromValue (valPlus (valFromType (letype),
2086                                       valFromType (retype)));
2087
2088   ic = newiCode ('+', left, right);
2089
2090   IC_RESULT (ic) = newiTempOperand (resType, 1);
2091   IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
2092
2093   /* if left or right is a float then support
2094      routine */
2095   if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
2096     ic->supportRtn = 1;
2097
2098   ADDTOCHAIN (ic);
2099
2100   return IC_RESULT (ic);
2101
2102 }
2103
2104 /*-----------------------------------------------------------------*/
2105 /* aggrToPtr - changes an aggregate to pointer to an aggregate     */
2106 /*-----------------------------------------------------------------*/
2107 sym_link *
2108 aggrToPtr (sym_link * type, bool force)
2109 {
2110   sym_link *etype;
2111   sym_link *ptype;
2112
2113
2114   if (IS_PTR (type) && !force)
2115     return type;
2116
2117   etype = getSpec (type);
2118   ptype = newLink (DECLARATOR);
2119
2120   ptype->next = type;
2121
2122 #ifdef JWK
2123   /* if the output class is code */
2124   if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
2125     DCL_PTR_CONST (ptype) = port->mem.code_ro;
2126
2127   /* if the variable was declared a constant */
2128   /* then the pointer points to a constant */
2129   if (IS_CONSTANT (etype))
2130     DCL_PTR_CONST (ptype) = 1;
2131
2132   /* the variable was volatile then pointer to volatile */
2133   if (IS_VOLATILE (etype))
2134     DCL_PTR_VOLATILE (ptype) = 1;
2135 #else
2136   DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype));
2137 #endif
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 #ifdef JWK
2152   /* set the pointer depending on the storage class */
2153   if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2154     DCL_PTR_CONST (optype) = port->mem.code_ro;
2155
2156   /* if the variable was declared a constant */
2157   /* then the pointer points to a constant */
2158   if (IS_CONSTANT (opetype))
2159     DCL_PTR_CONST (optype) = 1;
2160
2161   /* the variable was volatile then pointer to volatile */
2162   if (IS_VOLATILE (opetype))
2163     DCL_PTR_VOLATILE (optype) = 1;
2164 #else
2165   DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype));
2166 #endif
2167
2168   op->isaddr = 0;
2169   return op;
2170 }
2171
2172
2173 /*-----------------------------------------------------------------*/
2174 /* geniCodeArray - array access                                    */
2175 /*-----------------------------------------------------------------*/
2176 operand *
2177 geniCodeArray (operand * left, operand * right,int lvl)
2178 {
2179   iCode *ic;
2180   sym_link *ltype = operandType (left);
2181
2182   if (IS_PTR (ltype))
2183     {
2184       if (IS_PTR (ltype->next) && left->isaddr)
2185         {
2186           left = geniCodeRValue (left, FALSE);
2187         }
2188       return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
2189     }
2190
2191   right = geniCodeMultiply (right,
2192                             operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
2193
2194   /* we can check for limits here */
2195   if (isOperandLiteral (right) &&
2196       IS_ARRAY (ltype) &&
2197       DCL_ELEM (ltype) &&
2198       (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
2199     {
2200       werror (E_ARRAY_BOUND);
2201       right = operandFromLit (0);
2202     }
2203
2204   ic = newiCode ('+', left, right);
2205
2206   IC_RESULT (ic) = newiTempOperand (((IS_PTR (ltype) &&
2207                                       !IS_AGGREGATE (ltype->next) &&
2208                                       !IS_PTR (ltype->next))
2209                                      ? ltype : ltype->next), 0);
2210
2211   IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
2212   ADDTOCHAIN (ic);
2213   return IC_RESULT (ic);
2214 }
2215
2216 /*-----------------------------------------------------------------*/
2217 /* geniCodeStruct - generates intermediate code for structres      */
2218 /*-----------------------------------------------------------------*/
2219 operand *
2220 geniCodeStruct (operand * left, operand * right, bool islval)
2221 {
2222   iCode *ic;
2223   sym_link *type = operandType (left);
2224   sym_link *etype = getSpec (type);
2225   sym_link *retype;
2226   symbol *element = getStructElement (SPEC_STRUCT (etype),
2227                                       right->operand.symOperand);
2228
2229   wassert(IS_SYMOP(right));
2230     
2231   /* add the offset */
2232   ic = newiCode ('+', left, operandFromLit (element->offset));
2233
2234   IC_RESULT (ic) = newiTempOperand (element->type, 0);
2235
2236   /* preserve the storage & output class of the struct */
2237   /* as well as the volatile attribute */
2238   retype = getSpec (operandType (IC_RESULT (ic)));
2239   SPEC_SCLS (retype) = SPEC_SCLS (etype);
2240   SPEC_OCLS (retype) = SPEC_OCLS (etype);
2241   SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
2242
2243   if (IS_PTR (element->type))
2244     setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
2245
2246   IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (element->type));
2247
2248
2249   ADDTOCHAIN (ic);
2250   return (islval ? IC_RESULT (ic) : geniCodeRValue (IC_RESULT (ic), TRUE));
2251 }
2252
2253 /*-----------------------------------------------------------------*/
2254 /* geniCodePostInc - generate int code for Post increment          */
2255 /*-----------------------------------------------------------------*/
2256 operand *
2257 geniCodePostInc (operand * op)
2258 {
2259   iCode *ic;
2260   operand *rOp;
2261   sym_link *optype = operandType (op);
2262   operand *result;
2263   operand *rv = (IS_ITEMP (op) ?
2264                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2265                  op);
2266   sym_link *rvtype = operandType (rv);
2267   int size = 0;
2268
2269   /* if this is not an address we have trouble */
2270   if (!op->isaddr)
2271     {
2272       werror (E_LVALUE_REQUIRED, "++");
2273       return op;
2274     }
2275
2276   rOp = newiTempOperand (rvtype, 0);
2277   OP_SYMBOL(rOp)->noSpilLoc = 1;
2278
2279   if (IS_ITEMP (rv))
2280     OP_SYMBOL(rv)->noSpilLoc = 1;
2281
2282   geniCodeAssign (rOp, rv, 0);
2283
2284   size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2285   if (IS_FLOAT (rvtype))
2286     ic = newiCode ('+', rv, operandFromValue (constFloatVal ("1.0")));
2287   else
2288     ic = newiCode ('+', rv, operandFromLit (size));
2289
2290   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2291   ADDTOCHAIN (ic);
2292
2293   geniCodeAssign (op, result, 0);
2294
2295   return rOp;
2296
2297 }
2298
2299 /*-----------------------------------------------------------------*/
2300 /* geniCodePreInc - generate code for preIncrement                 */
2301 /*-----------------------------------------------------------------*/
2302 operand *
2303 geniCodePreInc (operand * op)
2304 {
2305   iCode *ic;
2306   sym_link *optype = operandType (op);
2307   operand *rop = (IS_ITEMP (op) ?
2308                   geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2309                   op);
2310   sym_link *roptype = operandType (rop);
2311   operand *result;
2312   int size = 0;
2313
2314   if (!op->isaddr)
2315     {
2316       werror (E_LVALUE_REQUIRED, "++");
2317       return op;
2318     }
2319
2320
2321   size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2322   if (IS_FLOAT (roptype))
2323     ic = newiCode ('+', rop, operandFromValue (constFloatVal ("1.0")));
2324   else
2325     ic = newiCode ('+', rop, operandFromLit (size));
2326   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2327   ADDTOCHAIN (ic);
2328
2329
2330   return geniCodeAssign (op, result, 0);
2331 }
2332
2333 /*-----------------------------------------------------------------*/
2334 /* geniCodePostDec - generates code for Post decrement             */
2335 /*-----------------------------------------------------------------*/
2336 operand *
2337 geniCodePostDec (operand * op)
2338 {
2339   iCode *ic;
2340   operand *rOp;
2341   sym_link *optype = operandType (op);
2342   operand *result;
2343   operand *rv = (IS_ITEMP (op) ?
2344                  geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2345                  op);
2346   sym_link *rvtype = operandType (rv);
2347   int size = 0;
2348
2349   /* if this is not an address we have trouble */
2350   if (!op->isaddr)
2351     {
2352       werror (E_LVALUE_REQUIRED, "--");
2353       return op;
2354     }
2355
2356   rOp = newiTempOperand (rvtype, 0);
2357   OP_SYMBOL(rOp)->noSpilLoc = 1;
2358
2359   if (IS_ITEMP (rv))
2360     OP_SYMBOL(rv)->noSpilLoc = 1;
2361
2362   geniCodeAssign (rOp, rv, 0);
2363
2364   size = (IS_PTR (rvtype) ? getSize (rvtype->next) : 1);
2365   if (IS_FLOAT (rvtype))
2366     ic = newiCode ('-', rv, operandFromValue (constFloatVal ("1.0")));
2367   else
2368     ic = newiCode ('-', rv, operandFromLit (size));
2369
2370   IC_RESULT (ic) = result = newiTempOperand (rvtype, 0);
2371   ADDTOCHAIN (ic);
2372
2373   geniCodeAssign (op, result, 0);
2374
2375   return rOp;
2376
2377 }
2378
2379 /*-----------------------------------------------------------------*/
2380 /* geniCodePreDec - generate code for pre  decrement               */
2381 /*-----------------------------------------------------------------*/
2382 operand *
2383 geniCodePreDec (operand * op)
2384 {
2385   iCode *ic;
2386   sym_link *optype = operandType (op);
2387   operand *rop = (IS_ITEMP (op) ?
2388                   geniCodeRValue (op, (IS_PTR (optype) ? TRUE : FALSE)) :
2389                   op);
2390   sym_link *roptype = operandType (rop);
2391   operand *result;
2392   int size = 0;
2393
2394   if (!op->isaddr)
2395     {
2396       werror (E_LVALUE_REQUIRED, "--");
2397       return op;
2398     }
2399
2400
2401   size = (IS_PTR (roptype) ? getSize (roptype->next) : 1);
2402   if (IS_FLOAT (roptype))
2403     ic = newiCode ('-', rop, operandFromValue (constFloatVal ("1.0")));
2404   else
2405     ic = newiCode ('-', rop, operandFromLit (size));
2406   IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
2407   ADDTOCHAIN (ic);
2408
2409
2410   return geniCodeAssign (op, result, 0);
2411 }
2412
2413
2414 /*-----------------------------------------------------------------*/
2415 /* geniCodeBitwise - gen int code for bitWise  operators           */
2416 /*-----------------------------------------------------------------*/
2417 operand *
2418 geniCodeBitwise (operand * left, operand * right,
2419                  int oper, sym_link * resType)
2420 {
2421   iCode *ic;
2422
2423   left = geniCodeCast (resType, left, TRUE);
2424   right = geniCodeCast (resType, right, TRUE);
2425
2426   ic = newiCode (oper, left, right);
2427   IC_RESULT (ic) = newiTempOperand (resType, 0);
2428
2429   ADDTOCHAIN (ic);
2430   return IC_RESULT (ic);
2431 }
2432
2433 /*-----------------------------------------------------------------*/
2434 /* geniCodeAddressOf - gens icode for '&' address of operator      */
2435 /*-----------------------------------------------------------------*/
2436 operand *
2437 geniCodeAddressOf (operand * op)
2438 {
2439   iCode *ic;
2440   sym_link *p;
2441   sym_link *optype = operandType (op);
2442   sym_link *opetype = getSpec (optype);
2443
2444   /* lvalue check already done in decorateType */
2445   /* this must be a lvalue */
2446 /*     if (!op->isaddr && !IS_AGGREGATE(optype)) { */
2447 /*  werror (E_LVALUE_REQUIRED,"&"); */
2448 /*  return op; */
2449 /*     } */
2450
2451   p = newLink (DECLARATOR);
2452
2453 #ifdef JWK
2454   /* set the pointer depending on the storage class */
2455   if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
2456     DCL_PTR_CONST (p) = port->mem.code_ro;
2457
2458   /* make sure we preserve the const & volatile */
2459   if (IS_CONSTANT (opetype))
2460     DCL_PTR_CONST (p) = 1;
2461
2462   if (IS_VOLATILE (opetype))
2463     DCL_PTR_VOLATILE (p) = 1;
2464 #else
2465   DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
2466 #endif
2467
2468
2469   p->next = copyLinkChain (optype);
2470
2471   /* if already a temp */
2472   if (IS_ITEMP (op))
2473     {
2474       setOperandType (op, p);
2475       op->isaddr = 0;
2476       return op;
2477     }
2478
2479   /* other wise make this of the type coming in */
2480   ic = newiCode (ADDRESS_OF, op, NULL);
2481   IC_RESULT (ic) = newiTempOperand (p, 1);
2482   IC_RESULT (ic)->isaddr = 0;
2483   ADDTOCHAIN (ic);
2484   return IC_RESULT (ic);
2485 }
2486 /*-----------------------------------------------------------------*/
2487 /* setOClass - sets the output class depending on the pointer type */
2488 /*-----------------------------------------------------------------*/
2489 void 
2490 setOClass (sym_link * ptr, sym_link * spec)
2491 {
2492   switch (DCL_TYPE (ptr))
2493     {
2494     case POINTER:
2495       SPEC_OCLS (spec) = data;
2496       break;
2497
2498     case GPOINTER:
2499       SPEC_OCLS (spec) = generic;
2500       break;
2501
2502     case FPOINTER:
2503       SPEC_OCLS (spec) = xdata;
2504       break;
2505
2506     case CPOINTER:
2507       SPEC_OCLS (spec) = code;
2508       break;
2509
2510     case IPOINTER:
2511       SPEC_OCLS (spec) = idata;
2512       break;
2513
2514     case PPOINTER:
2515       SPEC_OCLS (spec) = xstack;
2516       break;
2517
2518     case EEPPOINTER:
2519       SPEC_OCLS (spec) = eeprom;
2520       break;
2521
2522     default:
2523       break;
2524
2525     }
2526 }
2527
2528 /*-----------------------------------------------------------------*/
2529 /* geniCodeDerefPtr - dereference pointer with '*'                 */
2530 /*-----------------------------------------------------------------*/
2531 operand *
2532 geniCodeDerefPtr (operand * op,int lvl)
2533 {
2534   sym_link *rtype, *retype;
2535   sym_link *optype = operandType (op);
2536
2537   /* if this is a pointer then generate the rvalue */
2538   if (IS_PTR (optype))
2539     {
2540       if (IS_TRUE_SYMOP (op))
2541         {
2542           op->isaddr = 1;
2543           op = geniCodeRValue (op, TRUE);
2544         }
2545       else
2546         op = geniCodeRValue (op, TRUE);
2547     }
2548
2549   /* now get rid of the pointer part */
2550   if (isLvaluereq(lvl) && IS_ITEMP (op))
2551     {
2552       retype = getSpec (rtype = copyLinkChain (optype));
2553     }
2554   else
2555     {
2556       retype = getSpec (rtype = copyLinkChain (optype->next));
2557     }
2558
2559   /* if this is a pointer then outputclass needs 2b updated */
2560   if (IS_PTR (optype))
2561     setOClass (optype, retype);
2562
2563   op->isGptr = IS_GENPTR (optype);
2564
2565   /* if the pointer was declared as a constant */
2566   /* then we cannot allow assignment to the derefed */
2567   if (IS_PTR_CONST (optype))
2568     SPEC_CONST (retype) = 1;
2569
2570   op->isaddr = (IS_PTR (rtype) ||
2571                 IS_STRUCT (rtype) ||
2572                 IS_INT (rtype) ||
2573                 IS_CHAR (rtype) ||
2574                 IS_FLOAT (rtype));
2575
2576   if (!isLvaluereq(lvl))
2577     op = geniCodeRValue (op, TRUE);
2578
2579   setOperandType (op, rtype);
2580
2581   return op;
2582 }
2583
2584 /*-----------------------------------------------------------------*/
2585 /* geniCodeUnaryMinus - does a unary minus of the operand          */
2586 /*-----------------------------------------------------------------*/
2587 operand *
2588 geniCodeUnaryMinus (operand * op)
2589 {
2590   iCode *ic;
2591   sym_link *optype = operandType (op);
2592
2593   if (IS_LITERAL (optype))
2594     return operandFromLit (-floatFromVal (op->operand.valOperand));
2595
2596   ic = newiCode (UNARYMINUS, op, NULL);
2597   IC_RESULT (ic) = newiTempOperand (optype, 0);
2598   ADDTOCHAIN (ic);
2599   return IC_RESULT (ic);
2600 }
2601
2602 /*-----------------------------------------------------------------*/
2603 /* geniCodeLeftShift - gen i code for left shift                   */
2604 /*-----------------------------------------------------------------*/
2605 operand *
2606 geniCodeLeftShift (operand * left, operand * right)
2607 {
2608   iCode *ic;
2609
2610   ic = newiCode (LEFT_OP, left, right);
2611   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2612   ADDTOCHAIN (ic);
2613   return IC_RESULT (ic);
2614 }
2615
2616 /*-----------------------------------------------------------------*/
2617 /* geniCodeRightShift - gen i code for right shift                 */
2618 /*-----------------------------------------------------------------*/
2619 operand *
2620 geniCodeRightShift (operand * left, operand * right)
2621 {
2622   iCode *ic;
2623
2624   ic = newiCode (RIGHT_OP, left, right);
2625   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
2626   ADDTOCHAIN (ic);
2627   return IC_RESULT (ic);
2628 }
2629
2630 /*-----------------------------------------------------------------*/
2631 /* geniCodeLogic- logic code                                       */
2632 /*-----------------------------------------------------------------*/
2633 operand *
2634 geniCodeLogic (operand * left, operand * right, int op)
2635 {
2636   iCode *ic;
2637   sym_link *ctype;
2638   sym_link *rtype = operandType (right);
2639   sym_link *ltype = operandType (left);
2640
2641   /* left is integral type and right is literal then
2642      check if the literal value is within bounds */
2643   if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
2644     {
2645       checkConstantRange(ltype, 
2646                          OP_VALUE(right), "compare operation", 1);
2647     }
2648
2649   ctype = usualBinaryConversions (&left, &right);
2650
2651   ic = newiCode (op, left, right);
2652   IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
2653
2654   /* if comparing float
2655      and not a '==' || '!=' || '&&' || '||' (these
2656      will be inlined */
2657   if (IS_FLOAT(ctype) &&
2658       op != EQ_OP &&
2659       op != NE_OP &&
2660       op != AND_OP &&
2661       op != OR_OP)
2662     ic->supportRtn = 1;
2663
2664   ADDTOCHAIN (ic);
2665   return IC_RESULT (ic);
2666 }
2667
2668 /*-----------------------------------------------------------------*/
2669 /* geniCodeUnary - for a a generic unary operation                 */
2670 /*-----------------------------------------------------------------*/
2671 operand *
2672 geniCodeUnary (operand * op, int oper)
2673 {
2674   iCode *ic = newiCode (oper, op, NULL);
2675
2676   IC_RESULT (ic) = newiTempOperand (operandType (op), 0);
2677   ADDTOCHAIN (ic);
2678   return IC_RESULT (ic);
2679 }
2680
2681 /*-----------------------------------------------------------------*/
2682 /* geniCodeConditional - geniCode for '?' ':' operation            */
2683 /*-----------------------------------------------------------------*/
2684 operand *
2685 geniCodeConditional (ast * tree,int lvl)
2686 {
2687   iCode *ic;
2688   symbol *falseLabel = newiTempLabel (NULL);
2689   symbol *exitLabel = newiTempLabel (NULL);
2690   operand *cond = ast2iCode (tree->left,lvl+1);
2691   operand *true, *false, *result;
2692
2693   ic = newiCodeCondition (geniCodeRValue (cond, FALSE),
2694                           NULL, falseLabel);
2695   ADDTOCHAIN (ic);
2696
2697   true = ast2iCode (tree->right->left,lvl+1);
2698
2699   /* move the value to a new Operand */
2700   result = newiTempOperand (tree->right->ftype, 0);
2701   geniCodeAssign (result, geniCodeRValue (true, FALSE), 0);
2702
2703   /* generate an unconditional goto */
2704   geniCodeGoto (exitLabel);
2705
2706   /* now for the right side */
2707   geniCodeLabel (falseLabel);
2708
2709   false = ast2iCode (tree->right->right,lvl+1);
2710   geniCodeAssign (result, geniCodeRValue (false, FALSE), 0);
2711
2712   /* create the exit label */
2713   geniCodeLabel (exitLabel);
2714
2715   return result;
2716 }
2717
2718 /*-----------------------------------------------------------------*/
2719 /* geniCodeAssign - generate code for assignment                   */
2720 /*-----------------------------------------------------------------*/
2721 operand *
2722 geniCodeAssign (operand * left, operand * right, int nosupdate)
2723 {
2724   iCode *ic;
2725   sym_link *ltype = operandType (left);
2726   sym_link *rtype = operandType (right);
2727
2728   if (!left->isaddr && !IS_ITEMP (left))
2729     {
2730       werror (E_LVALUE_REQUIRED, "assignment");
2731       return left;
2732     }
2733
2734   /* left is integral type and right is literal then
2735      check if the literal value is within bounds */
2736   if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
2737     {
2738       checkConstantRange(ltype, 
2739                          OP_VALUE(right), "= operation", 0);
2740     }
2741
2742   /* if the left & right type don't exactly match */
2743   /* if pointer set then make sure the check is
2744      done with the type & not the pointer */
2745   /* then cast rights type to left */
2746
2747   /* first check the type for pointer assignement */
2748   if (left->isaddr && IS_PTR (ltype) && IS_ITEMP (left) &&
2749       compareType (ltype, rtype) <= 0)
2750     {
2751       if (compareType (ltype->next, rtype) < 0)
2752         right = geniCodeCast (ltype->next, right, TRUE);
2753     }
2754   else if (compareType (ltype, rtype) < 0)
2755     right = geniCodeCast (ltype, right, TRUE);
2756
2757   /* if left is a true symbol & ! volatile
2758      create an assignment to temporary for
2759      the right & then assign this temporary
2760      to the symbol this is SSA . isn't it simple
2761      and folks have published mountains of paper on it */
2762   if (IS_TRUE_SYMOP (left) &&
2763       !isOperandVolatile (left, FALSE) &&
2764       isOperandGlobal (left))
2765     {
2766       symbol *sym = NULL;
2767
2768       if (IS_TRUE_SYMOP (right))
2769         sym = OP_SYMBOL (right);
2770       ic = newiCode ('=', NULL, right);
2771       IC_RESULT (ic) = right = newiTempOperand (ltype, 0);
2772       SPIL_LOC (right) = sym;
2773       ADDTOCHAIN (ic);
2774     }
2775
2776   ic = newiCode ('=', NULL, right);
2777   IC_RESULT (ic) = left;
2778   ADDTOCHAIN (ic);
2779
2780   /* if left isgptr flag is set then support
2781      routine will be required */
2782   if (left->isGptr)
2783     ic->supportRtn = 1;
2784
2785   ic->nosupdate = nosupdate;
2786   return left;
2787 }
2788
2789 /*-----------------------------------------------------------------*/
2790 /* geniCodeSEParms - generate code for side effecting fcalls       */
2791 /*-----------------------------------------------------------------*/
2792 static void 
2793 geniCodeSEParms (ast * parms,int lvl)
2794 {
2795   if (!parms)
2796     return;
2797
2798   if (parms->type == EX_OP && parms->opval.op == PARAM)
2799     {
2800       geniCodeSEParms (parms->left,lvl);
2801       geniCodeSEParms (parms->right,lvl);
2802       return;
2803     }
2804
2805   /* hack don't like this but too lazy to think of
2806      something better */
2807   if (IS_ADDRESS_OF_OP (parms))
2808     parms->left->lvalue = 1;
2809
2810   if (IS_CAST_OP (parms) &&
2811       IS_PTR (parms->ftype) &&
2812       IS_ADDRESS_OF_OP (parms->right))
2813     parms->right->left->lvalue = 1;
2814
2815   parms->opval.oprnd = 
2816     geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2817                 
2818   parms->type = EX_OPERAND;
2819   AST_ARGREG(parms) = parms->etype ? SPEC_ARGREG(parms->etype) :
2820                 SPEC_ARGREG(parms->ftype);
2821 }
2822
2823 /*-----------------------------------------------------------------*/
2824 /* geniCodeParms - generates parameters                            */
2825 /*-----------------------------------------------------------------*/
2826 value *
2827 geniCodeParms (ast * parms, value *argVals, int *stack, 
2828                sym_link * fetype, symbol * func,int lvl)
2829 {
2830   iCode *ic;
2831   operand *pval;
2832
2833   if (!parms)
2834     return argVals;
2835
2836   if (argVals==NULL) {
2837     // first argument
2838     argVals=FUNC_ARGS(func->type);
2839   }
2840
2841   /* if this is a param node then do the left & right */
2842   if (parms->type == EX_OP && parms->opval.op == PARAM)
2843     {
2844       argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
2845       argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
2846       return argVals;
2847     }
2848
2849   /* get the parameter value */
2850   if (parms->type == EX_OPERAND)
2851     pval = parms->opval.oprnd;
2852   else
2853     {
2854       /* maybe this else should go away ?? */
2855       /* hack don't like this but too lazy to think of
2856          something better */
2857       if (IS_ADDRESS_OF_OP (parms))
2858         parms->left->lvalue = 1;
2859
2860       if (IS_CAST_OP (parms) &&
2861           IS_PTR (parms->ftype) &&
2862           IS_ADDRESS_OF_OP (parms->right))
2863         parms->right->left->lvalue = 1;
2864
2865       pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
2866     }
2867
2868   /* if register parm then make it a send */
2869   if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
2870       IFFUNC_ISBUILTIN(func->type))
2871     {
2872       ic = newiCode (SEND, pval, NULL);
2873       ic->argreg = SPEC_ARGREG(parms->etype);
2874       ic->builtinSEND = FUNC_ISBUILTIN(func->type);
2875       ADDTOCHAIN (ic);
2876     }
2877   else
2878     {
2879       /* now decide whether to push or assign */
2880       if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
2881         {
2882
2883           /* assign */
2884           operand *top = operandFromSymbol (argVals->sym);
2885           /* clear useDef and other bitVectors */
2886           OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
2887           geniCodeAssign (top, pval, 1);
2888         }
2889       else
2890         {
2891           sym_link *p = operandType (pval);
2892           /* push */
2893           ic = newiCode (IPUSH, pval, NULL);
2894           ic->parmPush = 1;
2895           /* update the stack adjustment */
2896           *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
2897           ADDTOCHAIN (ic);
2898         }
2899     }
2900
2901   argVals=argVals->next;
2902   return argVals;
2903 }
2904
2905 /*-----------------------------------------------------------------*/
2906 /* geniCodeCall - generates temp code for calling                  */
2907 /*-----------------------------------------------------------------*/
2908 operand *
2909 geniCodeCall (operand * left, ast * parms,int lvl)
2910 {
2911   iCode *ic;
2912   operand *result;
2913   sym_link *type, *etype;
2914   int stack = 0;
2915
2916   if (!IS_FUNC(OP_SYMBOL(left)->type) && 
2917       !IS_CODEPTR(OP_SYMBOL(left)->type)) {
2918     werror (E_FUNCTION_EXPECTED);
2919     return NULL;
2920   }
2921
2922   /* take care of parameters with side-effecting
2923      function calls in them, this is required to take care
2924      of overlaying function parameters */
2925   geniCodeSEParms (parms,lvl);
2926
2927   /* first the parameters */
2928   geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
2929
2930   /* now call : if symbol then pcall */
2931   if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
2932     ic = newiCode (PCALL, left, NULL);
2933   } else {
2934     ic = newiCode (CALL, left, NULL);
2935   }
2936
2937   type = copyLinkChain (operandType (left)->next);
2938   etype = getSpec (type);
2939   SPEC_EXTR (etype) = 0;
2940   IC_RESULT (ic) = result = newiTempOperand (type, 1);
2941
2942   ADDTOCHAIN (ic);
2943
2944   /* stack adjustment after call */
2945   ic->parmBytes = stack;
2946
2947   return result;
2948 }
2949
2950 /*-----------------------------------------------------------------*/
2951 /* geniCodeReceive - generate intermediate code for "receive"      */
2952 /*-----------------------------------------------------------------*/
2953 static void 
2954 geniCodeReceive (value * args)
2955 {
2956   /* for all arguments that are passed in registers */
2957   while (args)
2958     {
2959       int first = 1;
2960       if (IS_REGPARM (args->etype))
2961         {
2962           operand *opr = operandFromValue (args);
2963           operand *opl;
2964           symbol *sym = OP_SYMBOL (opr);
2965           iCode *ic;
2966
2967           /* we will use it after all optimizations
2968              and before liveRange calculation */
2969           if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
2970             {
2971
2972               if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
2973                   options.stackAuto == 0 &&
2974                   (!(options.model == MODEL_FLAT24)) )
2975                 {
2976                 }
2977               else
2978                 {
2979                   opl = newiTempOperand (args->type, 0);
2980                   sym->reqv = opl;
2981                   sym->reqv->key = sym->key;
2982                   OP_SYMBOL (sym->reqv)->key = sym->key;
2983                   OP_SYMBOL (sym->reqv)->isreqv = 1;
2984                   OP_SYMBOL (sym->reqv)->islocal = 0;
2985                   SPIL_LOC (sym->reqv) = sym;
2986                 }
2987             }
2988
2989           ic = newiCode (RECEIVE, NULL, NULL);    
2990           ic->argreg = SPEC_ARGREG(args->etype);
2991           if (first) {
2992               currFunc->recvSize = getSize (sym->type);
2993               first = 0;
2994           }
2995           IC_RESULT (ic) = opr;
2996           ADDTOCHAIN (ic);
2997         }
2998
2999       args = args->next;
3000     }
3001 }
3002
3003 /*-----------------------------------------------------------------*/
3004 /* geniCodeFunctionBody - create the function body                 */
3005 /*-----------------------------------------------------------------*/
3006 void 
3007 geniCodeFunctionBody (ast * tree,int lvl)
3008 {
3009   iCode *ic;
3010   operand *func;
3011   sym_link *fetype;
3012   int savelineno;
3013
3014   /* reset the auto generation */
3015   /* numbers */
3016   iTempNum = 0;
3017   iTempLblNum = 0;
3018   operandKey = 0;
3019   iCodeKey = 0;
3020   func = ast2iCode (tree->left,lvl+1);
3021   fetype = getSpec (operandType (func));
3022
3023   savelineno = lineno;
3024   lineno = OP_SYMBOL (func)->lineDef;
3025   /* create an entry label */
3026   geniCodeLabel (entryLabel);
3027   lineno = savelineno;
3028
3029   /* create a proc icode */
3030   ic = newiCode (FUNCTION, func, NULL);
3031   lineno=ic->lineno = OP_SYMBOL (func)->lineDef;
3032
3033   ADDTOCHAIN (ic);
3034
3035   /* for all parameters that are passed
3036      on registers add a "receive" */
3037   geniCodeReceive (tree->values.args);
3038
3039   /* generate code for the body */
3040   ast2iCode (tree->right,lvl+1);
3041
3042   /* create a label for return */
3043   geniCodeLabel (returnLabel);
3044
3045   /* now generate the end proc */
3046   ic = newiCode (ENDFUNCTION, func, NULL);
3047   ADDTOCHAIN (ic);
3048   return;
3049 }
3050
3051 /*-----------------------------------------------------------------*/
3052 /* geniCodeReturn - gen icode for 'return' statement               */
3053 /*-----------------------------------------------------------------*/
3054 void 
3055 geniCodeReturn (operand * op)
3056 {
3057   iCode *ic;
3058
3059   /* if the operand is present force an rvalue */
3060   if (op)
3061     op = geniCodeRValue (op, FALSE);
3062
3063   ic = newiCode (RETURN, op, NULL);
3064   ADDTOCHAIN (ic);
3065 }
3066
3067 /*-----------------------------------------------------------------*/
3068 /* geniCodeIfx - generates code for extended if statement          */
3069 /*-----------------------------------------------------------------*/
3070 void 
3071 geniCodeIfx (ast * tree,int lvl)
3072 {
3073   iCode *ic;
3074   operand *condition = ast2iCode (tree->left,lvl+1);
3075   sym_link *cetype;
3076
3077   /* if condition is null then exit */
3078   if (!condition)
3079     goto exit;
3080   else
3081     condition = geniCodeRValue (condition, FALSE);
3082
3083   cetype = getSpec (operandType (condition));
3084   /* if the condition is a literal */
3085   if (IS_LITERAL (cetype))
3086     {
3087       if (floatFromVal (condition->operand.valOperand))
3088         {
3089           if (tree->trueLabel)
3090             geniCodeGoto (tree->trueLabel);
3091           else
3092             assert (0);
3093         }
3094       else
3095         {
3096           if (tree->falseLabel)
3097             geniCodeGoto (tree->falseLabel);
3098           else
3099             assert (0);
3100         }
3101       goto exit;
3102     }
3103
3104   if (tree->trueLabel)
3105     {
3106       ic = newiCodeCondition (condition,
3107                               tree->trueLabel,
3108                               NULL);
3109       ADDTOCHAIN (ic);
3110
3111       if (tree->falseLabel)
3112         geniCodeGoto (tree->falseLabel);
3113     }
3114   else
3115     {
3116       ic = newiCodeCondition (condition,
3117                               NULL,
3118                               tree->falseLabel);
3119       ADDTOCHAIN (ic);
3120     }
3121
3122 exit:
3123   ast2iCode (tree->right,lvl+1);
3124 }
3125
3126 /*-----------------------------------------------------------------*/
3127 /* geniCodeJumpTable - tries to create a jump table for switch     */
3128 /*-----------------------------------------------------------------*/
3129 int 
3130 geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
3131 {
3132   int min = 0, max = 0, t, cnt = 0;
3133   value *vch;
3134   iCode *ic;
3135   operand *boundary;
3136   symbol *falseLabel;
3137   set *labels = NULL;
3138
3139   if (!tree || !caseVals)
3140     return 0;
3141
3142   /* the criteria for creating a jump table is */
3143   /* all integer numbers between the maximum & minimum must */
3144   /* be present , the maximum value should not exceed 255 */
3145   min = max = (int) floatFromVal (vch = caseVals);
3146   SNPRINTF (buffer, sizeof(buffer), 
3147             "_case_%d_%d",
3148            tree->values.switchVals.swNum,
3149            min);
3150   addSet (&labels, newiTempLabel (buffer));
3151
3152   /* if there is only one case value then no need */
3153   if (!(vch = vch->next))
3154     return 0;
3155
3156   while (vch)
3157     {
3158       if (((t = (int) floatFromVal (vch)) - max) != 1)
3159         return 0;
3160       SNPRINTF (buffer, sizeof(buffer), 
3161                 "_case_%d_%d",
3162                tree->values.switchVals.swNum,
3163                t);
3164       addSet (&labels, newiTempLabel (buffer));
3165       max = t;
3166       cnt++;
3167       vch = vch->next;
3168     }
3169
3170   /* if the number of case statements <= 2 then */
3171   /* it is not economical to create the jump table */
3172   /* since two compares are needed for boundary conditions */
3173   if ((!optimize.noJTabBoundary && cnt <= 2) || max > (255 / 3))
3174     return 0;
3175
3176   if (tree->values.switchVals.swDefault)
3177     {
3178         SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3179     }
3180   else
3181     {
3182         SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3183     }
3184     
3185
3186   falseLabel = newiTempLabel (buffer);
3187
3188   /* so we can create a jumptable */
3189   /* first we rule out the boundary conditions */
3190   /* if only optimization says so */
3191   if (!optimize.noJTabBoundary)
3192     {
3193       sym_link *cetype = getSpec (operandType (cond));
3194       /* no need to check the lower bound if
3195          the condition is unsigned & minimum value is zero */
3196       if (!(min == 0 && SPEC_USIGN (cetype)))
3197         {
3198           boundary = geniCodeLogic (cond, operandFromLit (min), '<');
3199           ic = newiCodeCondition (boundary, falseLabel, NULL);
3200           ADDTOCHAIN (ic);
3201         }
3202
3203       /* now for upper bounds */
3204       boundary = geniCodeLogic (cond, operandFromLit (max), '>');
3205       ic = newiCodeCondition (boundary, falseLabel, NULL);
3206       ADDTOCHAIN (ic);
3207     }
3208
3209   /* if the min is not zero then we no make it zero */
3210   if (min)
3211     {
3212       cond = geniCodeSubtract (cond, operandFromLit (min));
3213       setOperandType (cond, UCHARTYPE);
3214     }
3215
3216   /* now create the jumptable */
3217   ic = newiCode (JUMPTABLE, NULL, NULL);
3218   IC_JTCOND (ic) = cond;
3219   IC_JTLABELS (ic) = labels;
3220   ADDTOCHAIN (ic);
3221   return 1;
3222 }
3223
3224 /*-----------------------------------------------------------------*/
3225 /* geniCodeSwitch - changes a switch to a if statement             */
3226 /*-----------------------------------------------------------------*/
3227 void 
3228 geniCodeSwitch (ast * tree,int lvl)
3229 {
3230   iCode *ic;
3231   operand *cond = geniCodeRValue (ast2iCode (tree->left,lvl+1), FALSE);
3232   value *caseVals = tree->values.switchVals.swVals;
3233   symbol *trueLabel, *falseLabel;
3234
3235   /* if we can make this a jump table */
3236   if (geniCodeJumpTable (cond, caseVals, tree))
3237     goto jumpTable;             /* no need for the comparison */
3238
3239   /* for the cases defined do */
3240   while (caseVals)
3241     {
3242
3243       operand *compare = geniCodeLogic (cond,
3244                                         operandFromValue (caseVals),
3245                                         EQ_OP);
3246
3247       SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
3248                tree->values.switchVals.swNum,
3249                (int) floatFromVal (caseVals));
3250       trueLabel = newiTempLabel (buffer);
3251
3252       ic = newiCodeCondition (compare, trueLabel, NULL);
3253       ADDTOCHAIN (ic);
3254       caseVals = caseVals->next;
3255     }
3256
3257
3258
3259   /* if default is present then goto break else break */
3260   if (tree->values.switchVals.swDefault)
3261     {
3262         SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
3263     }
3264   else
3265     {
3266         SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
3267     }
3268
3269   falseLabel = newiTempLabel (buffer);
3270   geniCodeGoto (falseLabel);
3271
3272 jumpTable:
3273   ast2iCode (tree->right,lvl+1);
3274 }
3275
3276 /*-----------------------------------------------------------------*/
3277 /* geniCodeInline - intermediate code for inline assembler         */
3278 /*-----------------------------------------------------------------*/
3279 static void 
3280 geniCodeInline (ast * tree)
3281 {
3282   iCode *ic;
3283
3284   ic = newiCode (INLINEASM, NULL, NULL);
3285   IC_INLINE (ic) = tree->values.inlineasm;
3286   ADDTOCHAIN (ic);
3287 }
3288
3289 /*-----------------------------------------------------------------*/
3290 /* geniCodeArrayInit - intermediate code for array initializer     */
3291 /*-----------------------------------------------------------------*/
3292 static void 
3293 geniCodeArrayInit (ast * tree, operand *array)
3294 {
3295   iCode *ic;
3296
3297   if (!getenv("TRY_THE_NEW_INITIALIZER")) {
3298     ic = newiCode (ARRAYINIT, array, NULL);
3299     IC_ARRAYILIST (ic) = tree->values.constlist;
3300   } else {
3301     operand *left=newOperand(), *right=newOperand();
3302     left->type=right->type=SYMBOL;
3303     OP_SYMBOL(left)=AST_SYMBOL(tree->left);
3304     OP_SYMBOL(right)=AST_SYMBOL(tree->right);
3305     ic = newiCode (ARRAYINIT, left, right);
3306   }
3307   ADDTOCHAIN (ic);
3308 }
3309
3310 /*-----------------------------------------------------------------*/
3311 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some      */
3312 /* particular case. Ie : assigning or dereferencing array or ptr   */
3313 /*-----------------------------------------------------------------*/
3314 set * lvaluereqSet = NULL;
3315 typedef struct lvalItem
3316   {
3317     int req;
3318     int lvl;
3319   }
3320 lvalItem;
3321
3322 /*-----------------------------------------------------------------*/
3323 /* addLvaluereq - add a flag for lvalreq for current ast level     */
3324 /*-----------------------------------------------------------------*/
3325 void addLvaluereq(int lvl)
3326 {
3327   lvalItem * lpItem = (lvalItem *)Safe_alloc ( sizeof (lvalItem));
3328   lpItem->req=1;
3329   lpItem->lvl=lvl;
3330   addSetHead(&lvaluereqSet,lpItem);
3331
3332 }
3333 /*-----------------------------------------------------------------*/
3334 /* delLvaluereq - del a flag for lvalreq for current ast level     */
3335 /*-----------------------------------------------------------------*/
3336 void delLvaluereq()
3337 {
3338   lvalItem * lpItem;
3339   lpItem = getSet(&lvaluereqSet);
3340   if(lpItem) Safe_free(lpItem);
3341 }
3342 /*-----------------------------------------------------------------*/
3343 /* clearLvaluereq - clear lvalreq flag                             */
3344 /*-----------------------------------------------------------------*/
3345 void clearLvaluereq()
3346 {
3347   lvalItem * lpItem;
3348   lpItem = peekSet(lvaluereqSet);
3349   if(lpItem) lpItem->req = 0;
3350 }
3351 /*-----------------------------------------------------------------*/
3352 /* getLvaluereq - get the last lvalreq level                       */
3353 /*-----------------------------------------------------------------*/
3354 int getLvaluereqLvl()
3355 {
3356   lvalItem * lpItem;
3357   lpItem = peekSet(lvaluereqSet);
3358   if(lpItem) return lpItem->lvl;
3359   return 0;
3360 }
3361 /*-----------------------------------------------------------------*/
3362 /* isLvaluereq - is lvalreq valid for this level ?                 */
3363 /*-----------------------------------------------------------------*/
3364 int isLvaluereq(int lvl)
3365 {
3366   lvalItem * lpItem;
3367   lpItem = peekSet(lvaluereqSet);
3368   if(lpItem) return ((lpItem->req)&&(lvl <= (lpItem->lvl+1)));
3369   return 0;
3370 }
3371
3372 /*-----------------------------------------------------------------*/
3373 /* ast2iCode - creates an icodeList from an ast                    */
3374 /*-----------------------------------------------------------------*/
3375 operand *
3376 ast2iCode (ast * tree,int lvl)
3377 {
3378   operand *left = NULL;
3379   operand *right = NULL;
3380   if (!tree)
3381     return NULL;
3382
3383   /* set the global variables for filename & line number */
3384   if (tree->filename)
3385     filename = tree->filename;
3386   if (tree->lineno)
3387     lineno = tree->lineno;
3388   if (tree->block)
3389     block = tree->block;
3390   if (tree->level)
3391     scopeLevel = tree->level;
3392
3393   if (tree->type == EX_VALUE)
3394     return operandFromValue (tree->opval.val);
3395
3396   if (tree->type == EX_LINK)
3397     return operandFromLink (tree->opval.lnk);
3398
3399   /* if we find a nullop */
3400   if (tree->type == EX_OP &&
3401      (tree->opval.op == NULLOP ||
3402      tree->opval.op == BLOCK))
3403     {
3404       ast2iCode (tree->left,lvl+1);
3405       ast2iCode (tree->right,lvl+1);
3406       return NULL;
3407     }
3408
3409   /* special cases for not evaluating */
3410   if (tree->opval.op != ':' &&
3411       tree->opval.op != '?' &&
3412       tree->opval.op != CALL &&
3413       tree->opval.op != IFX &&
3414       tree->opval.op != LABEL &&
3415       tree->opval.op != GOTO &&
3416       tree->opval.op != SWITCH &&
3417       tree->opval.op != FUNCTION &&
3418       tree->opval.op != INLINEASM)
3419     {
3420
3421         if (IS_ASSIGN_OP (tree->opval.op) ||
3422            IS_DEREF_OP (tree) ||
3423            (tree->opval.op == '&' && !tree->right) ||
3424            tree->opval.op == PTR_OP)
3425           {
3426             addLvaluereq(lvl);
3427             if ((IS_ARRAY_OP (tree->left) && IS_ARRAY_OP (tree->left->left)) ||
3428                (IS_DEREF_OP (tree) && IS_ARRAY_OP (tree->left)))
3429               clearLvaluereq();
3430
3431             left = operandFromAst (tree->left,lvl);
3432             delLvaluereq();
3433             if (IS_DEREF_OP (tree) && IS_DEREF_OP (tree->left))
3434               left = geniCodeRValue (left, TRUE);
3435           }
3436         else
3437           {
3438             left = operandFromAst (tree->left,lvl);
3439           }
3440         if (tree->opval.op == INC_OP ||
3441             tree->opval.op == DEC_OP)
3442           {
3443             addLvaluereq(lvl);
3444             right = operandFromAst (tree->right,lvl);
3445             delLvaluereq();
3446           }
3447         else
3448           {
3449             right = operandFromAst (tree->right,lvl);
3450           }
3451       }
3452
3453   /* now depending on the type of operand */
3454   /* this will be a biggy                 */
3455   switch (tree->opval.op)
3456     {
3457
3458     case '[':                   /* array operation */
3459       {
3460         //sym_link *ltype = operandType (left);
3461         //left = geniCodeRValue (left, IS_PTR (ltype->next) ? TRUE : FALSE);
3462         left = geniCodeRValue (left, FALSE);
3463         right = geniCodeRValue (right, TRUE);
3464       }
3465
3466       return geniCodeArray (left, right,lvl);
3467
3468     case '.':                   /* structure dereference */
3469       if (IS_PTR (operandType (left)))
3470         left = geniCodeRValue (left, TRUE);
3471       else
3472         left = geniCodeRValue (left, FALSE);
3473
3474       return geniCodeStruct (left, right, tree->lvalue);
3475
3476     case PTR_OP:                /* structure pointer dereference */
3477       {
3478         sym_link *pType;
3479         pType = operandType (left);
3480         left = geniCodeRValue (left, TRUE);
3481
3482         setOClass (pType, getSpec (operandType (left)));
3483       }
3484
3485       return geniCodeStruct (left, right, tree->lvalue);
3486
3487     case INC_OP:                /* increment operator */
3488       if (left)
3489         return geniCodePostInc (left);
3490       else
3491         return geniCodePreInc (right);
3492
3493     case DEC_OP:                /* decrement operator */
3494       if (left)
3495         return geniCodePostDec (left);
3496       else
3497         return geniCodePreDec (right);
3498
3499     case '&':                   /* bitwise and or address of operator */
3500       if (right)
3501         {                       /* this is a bitwise operator   */
3502           left = geniCodeRValue (left, FALSE);
3503           right = geniCodeRValue (right, FALSE);
3504           return geniCodeBitwise (left, right, BITWISEAND, tree->ftype);
3505         }
3506       else
3507         return geniCodeAddressOf (left);
3508
3509     case '|':                   /* bitwise or & xor */
3510     case '^':
3511       return geniCodeBitwise (geniCodeRValue (left, FALSE),
3512                               geniCodeRValue (right, FALSE),
3513                               tree->opval.op,
3514                               tree->ftype);
3515
3516     case '/':
3517       return geniCodeDivision (geniCodeRValue (left, FALSE),
3518                                geniCodeRValue (right, FALSE));
3519
3520     case '%':
3521       return geniCodeModulus (geniCodeRValue (left, FALSE),
3522                               geniCodeRValue (right, FALSE));
3523     case '*':
3524       if (right)
3525         return geniCodeMultiply (geniCodeRValue (left, FALSE),
3526                                  geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
3527       else
3528         return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
3529
3530     case '-':
3531       if (right)
3532         return geniCodeSubtract (geniCodeRValue (left, FALSE),
3533                                  geniCodeRValue (right, FALSE));
3534       else
3535         return geniCodeUnaryMinus (geniCodeRValue (left, FALSE));
3536
3537     case '+':
3538       if (right)
3539         return geniCodeAdd (geniCodeRValue (left, FALSE),
3540                             geniCodeRValue (right, FALSE),lvl);
3541       else
3542         return geniCodeRValue (left, FALSE);    /* unary '+' has no meaning */
3543
3544     case LEFT_OP:
3545       return geniCodeLeftShift (geniCodeRValue (left, FALSE),
3546                                 geniCodeRValue (right, FALSE));
3547
3548     case RIGHT_OP:
3549       return geniCodeRightShift (geniCodeRValue (left, FALSE),
3550                                  geniCodeRValue (right, FALSE));
3551     case CAST:
3552       return geniCodeCast (operandType (left),
3553                            geniCodeRValue (right, FALSE), FALSE);
3554
3555     case '~':
3556     case '!':
3557     case RRC:
3558     case RLC:
3559       return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3560
3561     case GETHBIT:
3562       {
3563         operand *op = geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
3564         setOperandType (op, UCHARTYPE);
3565         return op;
3566       }
3567     case '>':
3568     case '<':
3569     case LE_OP:
3570     case GE_OP:
3571     case EQ_OP:
3572     case NE_OP:
3573     case AND_OP:
3574     case OR_OP:
3575       return geniCodeLogic (geniCodeRValue (left, FALSE),
3576                             geniCodeRValue (right, FALSE),
3577                             tree->opval.op);
3578     case '?':
3579       return geniCodeConditional (tree,lvl);
3580
3581     case SIZEOF:
3582       return operandFromLit (getSize (tree->right->ftype));
3583
3584     case '=':
3585       {
3586         sym_link *rtype = operandType (right);
3587         sym_link *ltype = operandType (left);
3588         if (IS_PTR (rtype) && IS_ITEMP (right)
3589             && right->isaddr && compareType (rtype->next, ltype) == 1)
3590           right = geniCodeRValue (right, TRUE);
3591         else
3592           right = geniCodeRValue (right, FALSE);
3593
3594         geniCodeAssign (left, right, 0);
3595         return right;
3596       }
3597     case MUL_ASSIGN:
3598       return
3599         geniCodeAssign (left,
3600                 geniCodeMultiply (geniCodeRValue (operandFromOperand (left),
3601                                                   FALSE),
3602                                   geniCodeRValue (right, FALSE),FALSE), 0);
3603
3604     case DIV_ASSIGN:
3605       return
3606         geniCodeAssign (left,
3607                 geniCodeDivision (geniCodeRValue (operandFromOperand (left),
3608                                                   FALSE),
3609                                   geniCodeRValue (right, FALSE)), 0);
3610     case MOD_ASSIGN:
3611       return
3612         geniCodeAssign (left,
3613                  geniCodeModulus (geniCodeRValue (operandFromOperand (left),
3614                                                   FALSE),
3615                                   geniCodeRValue (right, FALSE)), 0);
3616     case ADD_ASSIGN:
3617       {
3618         sym_link *rtype = operandType (right);
3619         sym_link *ltype = operandType (left);
3620         if (IS_PTR (rtype) && IS_ITEMP (right)
3621             && right->isaddr && compareType (rtype->next, ltype) == 1)
3622           right = geniCodeRValue (right, TRUE);
3623         else
3624           right = geniCodeRValue (right, FALSE);
3625
3626
3627         return geniCodeAssign (left,
3628                      geniCodeAdd (geniCodeRValue (operandFromOperand (left),
3629                                                   FALSE),
3630                                   right,lvl), 0);
3631       }
3632     case SUB_ASSIGN:
3633       {
3634         sym_link *rtype = operandType (right);
3635         sym_link *ltype = operandType (left);
3636         if (IS_PTR (rtype) && IS_ITEMP (right)
3637             && right->isaddr && compareType (rtype->next, ltype) == 1)
3638           {
3639             right = geniCodeRValue (right, TRUE);
3640           }
3641         else
3642           {
3643             right = geniCodeRValue (right, FALSE);
3644           }
3645         return
3646           geniCodeAssign (left,
3647                 geniCodeSubtract (geniCodeRValue (operandFromOperand (left),
3648                                                   FALSE),
3649                                   right), 0);
3650       }
3651     case LEFT_ASSIGN:
3652       return
3653         geniCodeAssign (left,
3654                 geniCodeLeftShift (geniCodeRValue (operandFromOperand (left)
3655                                                    ,FALSE),
3656                                    geniCodeRValue (right, FALSE)), 0);
3657     case RIGHT_ASSIGN:
3658       return
3659         geniCodeAssign (left,
3660                geniCodeRightShift (geniCodeRValue (operandFromOperand (left)
3661                                                    ,FALSE),
3662                                    geniCodeRValue (right, FALSE)), 0);
3663     case AND_ASSIGN:
3664       return
3665         geniCodeAssign (left,
3666                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3667                                                   FALSE),
3668                                   geniCodeRValue (right, FALSE),
3669                                   BITWISEAND,
3670                                   operandType (left)), 0);
3671     case XOR_ASSIGN:
3672       return
3673         geniCodeAssign (left,
3674                  geniCodeBitwise (geniCodeRValue (operandFromOperand (left),
3675                                                   FALSE),
3676                                   geniCodeRValue (right, FALSE),
3677                                   '^',
3678                                   operandType (left)), 0);
3679     case OR_ASSIGN:
3680       return
3681         geniCodeAssign (left,
3682                   geniCodeBitwise (geniCodeRValue (operandFromOperand (left)
3683                                                    ,FALSE),
3684                                    geniCodeRValue (right, FALSE),
3685                                    '|',
3686                                    operandType (left)), 0);
3687     case ',':
3688       return geniCodeRValue (right, FALSE);
3689
3690     case CALL:
3691       return geniCodeCall (ast2iCode (tree->left,lvl+1),
3692                            tree->right,lvl);
3693     case LABEL:
3694       geniCodeLabel (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3695       return ast2iCode (tree->right,lvl+1);
3696
3697     case GOTO:
3698       geniCodeGoto (ast2iCode (tree->left,lvl+1)->operand.symOperand);
3699       return ast2iCode (tree->right,lvl+1);
3700
3701     case FUNCTION:
3702       geniCodeFunctionBody (tree,lvl);
3703       return NULL;
3704
3705     case RETURN:
3706       geniCodeReturn (right);
3707       return NULL;
3708
3709     case IFX:
3710       geniCodeIfx (tree,lvl);
3711       return NULL;
3712
3713     case SWITCH:
3714       geniCodeSwitch (tree,lvl);
3715       return NULL;
3716
3717     case INLINEASM:
3718       geniCodeInline (tree);
3719       return NULL;
3720         
3721     case ARRAYINIT:
3722         geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
3723         return NULL;
3724     }
3725
3726   return NULL;
3727 }
3728
3729 /*-----------------------------------------------------------------*/
3730 /* reverseICChain - gets from the list and creates a linkedlist    */
3731 /*-----------------------------------------------------------------*/
3732 iCode *
3733 reverseiCChain ()
3734 {
3735   iCode *loop = NULL;
3736   iCode *prev = NULL;
3737
3738   while ((loop = getSet (&iCodeChain)))
3739     {
3740       loop->next = prev;
3741       if (prev)
3742         prev->prev = loop;
3743       prev = loop;
3744     }
3745
3746   return prev;
3747 }
3748
3749
3750 /*-----------------------------------------------------------------*/
3751 /* iCodeFromAst - given an ast will convert it to iCode            */
3752 /*-----------------------------------------------------------------*/
3753 iCode *
3754 iCodeFromAst (ast * tree)
3755 {
3756   returnLabel = newiTempLabel ("_return");
3757   entryLabel = newiTempLabel ("_entry");
3758   ast2iCode (tree,0);
3759   return reverseiCChain ();
3760 }
3761
3762 static const char *opTypeToStr(OPTYPE op)
3763 {
3764     switch(op)
3765     {
3766       case SYMBOL: return "symbol";
3767       case VALUE: return "value";
3768       case TYPE: return "type";
3769     }
3770     return "undefined type";    
3771 }
3772
3773
3774 operand *validateOpType(operand         *op, 
3775                         const char      *macro,
3776                         const char      *args,
3777                         OPTYPE          type,
3778                         const char      *file, 
3779                         unsigned        line)
3780 {    
3781     if (op && op->type == type)
3782     {
3783         return op;
3784     }
3785     fprintf(stderr, 
3786             "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
3787             " expected %s, got %s\n",
3788             macro, args, file, line, 
3789             opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
3790     exit(-1);
3791     return op; // never reached, makes compiler happy.
3792 }