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