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