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