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