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