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