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