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