Initial revision
[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 #include <stdio.h>
25 #include "SDCCglobl.h"
26 #include "SDCCast.h"
27 #include "SDCCmem.h"
28 #include "SDCCy.h"
29 #include "SDCChasht.h"
30 #include "SDCCicode.h"
31 #include "SDCCerr.h"
32 #include "SDCCralloc.h"
33
34 /*-----------------------------------------------------------------*/
35 /* global variables       */
36
37 set *iCodeChain = NULL ;
38 int iTempNum = 0;
39 int iTempLblNum = 0;
40 int operandKey = 0 ;
41 int iCodeKey = 0;
42 char *filename ;
43 int lineno ;
44 int block;
45 int scopeLevel;
46 int lvaluereq;
47
48 extern int labelKey ;
49
50 symbol *returnLabel ; /* function return label */
51 symbol *entryLabel  ; /* function entry  label */
52 /*-----------------------------------------------------------------*/
53 /* forward definition of some functions */
54 operand *geniCodeDivision (operand *,operand *);
55 operand *geniCodeAssign   (operand *,operand *,int);
56 operand *geniCodeArray (operand *,operand *);
57 operand *geniCodeArray2Ptr (operand *);
58 operand *geniCodeRValue (operand *, bool );
59 operand *geniCodeDerefPtr (operand *);
60
61 #define PRINTFUNC(x) void x (FILE *of, iCode *ic, char *s)
62
63 /* forward definition of print functions */
64 PRINTFUNC(picGetValueAtAddr);
65 PRINTFUNC(picSetValueAtAddr);
66 PRINTFUNC(picAddrOf);
67 PRINTFUNC(picGeneric);
68 PRINTFUNC(picGenericOne);
69 PRINTFUNC(picCast);
70 PRINTFUNC(picIncrement);
71 PRINTFUNC(picDecrement);
72 PRINTFUNC(picAssign);
73 PRINTFUNC(picLabel);
74 PRINTFUNC(picGoto);
75 PRINTFUNC(picIfx);
76 PRINTFUNC(picJumpTable);
77 PRINTFUNC(picInline);
78 PRINTFUNC(picReceive);
79
80 iCodeTable codeTable[] = {
81   { '!'                 ,  "not", picGenericOne    , NULL },
82   { '~'                 ,  "~"  , picGenericOne    , NULL },
83   { RRC                 ,  "rrc", picGenericOne    , NULL },
84   { RLC                 ,  "rlc", picGenericOne    , NULL },
85   { GETHBIT             ,"ghbit", picGenericOne    , NULL },
86   { UNARYMINUS          ,  "-"  , picGenericOne    , NULL },
87   { IPUSH               ,  "push",picGenericOne    , NULL },
88   { IPOP                ,  "pop", picGenericOne    , NULL },
89   { CALL                ,  "call",picGenericOne    , NULL },
90   { PCALL               , "pcall",picGenericOne    , NULL }, 
91   { FUNCTION            , "proc", picGenericOne    , NULL },
92   { ENDFUNCTION         ,"eproc", picGenericOne    , NULL },
93   { RETURN              ,  "ret", picGenericOne    , NULL },
94   { '+'                 ,  "+"  , picGeneric       , NULL },
95   { '-'                 ,  "-"  , picGeneric       , NULL },
96   { '*'                 ,  "*"  , picGeneric       , NULL },
97   { '/'                 ,  "/"  , picGeneric       , NULL },
98   { '%'                 ,  "%"  , picGeneric       , NULL },
99   { '>'                 ,  ">"  , picGeneric       , NULL },
100   { '<'                 ,  "<"  , picGeneric       , NULL },
101   { LE_OP               ,  "<=" , picGeneric       , NULL },
102   { GE_OP               ,  ">=" , picGeneric       , NULL },
103   { EQ_OP               ,  "==" , picGeneric       , NULL },
104   { NE_OP               ,  "!=" , picGeneric       , NULL },  
105   { AND_OP              ,  "&&" , picGeneric       , NULL },
106   { OR_OP               ,  "||" , picGeneric       , NULL },
107   { '^'                 ,  "^"  , picGeneric       , NULL },
108   { '|'                 ,  "|"  , picGeneric       , NULL },
109   { BITWISEAND          ,  "&"  , picGeneric       , NULL },
110   { LEFT_OP             ,  "<<" , picGeneric       , NULL },
111   { RIGHT_OP            ,  ">>" , picGeneric       , NULL },
112   { GET_VALUE_AT_ADDRESS,  "@"  , picGetValueAtAddr, NULL },
113   { ADDRESS_OF          ,  "&"  , picAddrOf        , NULL },
114   { CAST                ,  "<>" , picCast          , NULL },
115   { '='                 ,  ":=" , picAssign        , NULL },
116   { LABEL               ,  ""   , picLabel         , NULL },
117   { GOTO                ,  ""   , picGoto          , NULL },
118   { JUMPTABLE           ,"jtab" , picJumpTable     , NULL },
119   { IFX                 ,  "if" , picIfx           , NULL },
120   { INLINEASM           , ""    , picInline        , NULL },
121   { RECEIVE             , "recv", picReceive       , NULL },
122   { SEND                , "send", picGenericOne    , NULL }
123 };
124
125
126 /*-----------------------------------------------------------------*/
127 /* operandName - returns the name of the operand                   */
128 /*-----------------------------------------------------------------*/
129 int printOperand (operand *op, FILE *file)
130 {
131     link *opetype;
132     int pnl = 0;
133
134     if (!op)
135         return 1;
136
137     if (!file) {
138         file = stdout;
139         pnl = 1;
140     }
141     switch (op->type) {
142         
143     case VALUE:
144         opetype = getSpec (operandType(op));
145         if (SPEC_NOUN(opetype) == V_FLOAT)
146             fprintf (file,"%g {", SPEC_CVAL(opetype).v_float);
147         else 
148             fprintf (file,"0x%x {",(int) floatFromVal(op->operand.valOperand));
149         printTypeChain(operandType(op),file);
150         fprintf(file,"}");
151         break;
152         
153     case SYMBOL :
154 #define REGA 1
155 #ifdef REGA     
156         fprintf (file,"%s [k%d lr%d:%d so:%d]{ ia%d re%d rm%d}",/*{ar%d rm%d ru%d p%d a%d u%d i%d au%d k%d ks%d}"  ,*/
157                  (OP_SYMBOL(op)->rname[0] ? OP_SYMBOL(op)->rname : OP_SYMBOL(op)->name), 
158                  op->key,
159                  OP_LIVEFROM(op),OP_LIVETO(op),
160                  OP_SYMBOL(op)->stack,
161                  op->isaddr, OP_SYMBOL(op)->isreqv,OP_SYMBOL(op)->remat
162 /*               , */
163 /*               OP_SYMBOL(op)->allocreq,OP_SYMBOL(op)->remat, */
164 /*               OP_SYMBOL(op)->ruonly, */
165 /*               OP_SYMBOL(op)->isptr,op->isaddr,OP_SYMBOL(op)->used, */
166 /*               OP_SYMBOL(op)->isind, */
167 /*               OP_SYMBOL(op)->accuse, op->key, OP_SYMBOL(op)->key */
168                  );
169         {
170             fprintf(file,"{"); printTypeChain(operandType(op),file); 
171             if (SPIL_LOC(op) && IS_ITEMP(op))
172                 fprintf(file,"}{ sir@ %s",SPIL_LOC(op)->rname);
173             fprintf(file,"}");
174
175         }
176         
177         /* if assigned to registers */
178         if (OP_SYMBOL(op)->nRegs) {
179             if (OP_SYMBOL(op)->isspilt) {
180                 if (!OP_SYMBOL(op)->remat)
181                     if (OP_SYMBOL(op)->usl.spillLoc)
182                         fprintf(file,"[%s]",(OP_SYMBOL(op)->usl.spillLoc->rname[0] ?
183                                              OP_SYMBOL(op)->usl.spillLoc->rname :
184                                              OP_SYMBOL(op)->usl.spillLoc->name));
185                     else
186                         fprintf(file,"[err]");
187                 else
188                     fprintf(file,"[remat]");
189             }
190             else {
191                 int i;
192                 fprintf(file,"[");
193                 for(i=0;i<OP_SYMBOL(op)->nRegs;i++)
194                     fprintf(file,"%s ",(OP_SYMBOL(op)->regs[i] ? 
195                                         OP_SYMBOL(op)->regs[i]->name :
196                                         "err"));
197                 fprintf(file,"]");
198             }
199         } 
200 #else
201         fprintf(file,"%s",(OP_SYMBOL(op)->rname[0] ?
202                            OP_SYMBOL(op)->rname : OP_SYMBOL(op)->name));
203         /* if assigned to registers */
204         if (OP_SYMBOL(op)->nRegs && !OP_SYMBOL(op)->isspilt) {
205             int i;
206             fprintf(file,"[");
207             for(i=0;i<OP_SYMBOL(op)->nRegs;i++)
208                 fprintf(file,"%s ",(OP_SYMBOL(op)->regs[i] ? 
209                                     OP_SYMBOL(op)->regs[i]->name :
210                                     "err"));
211             fprintf(file,"]");
212         } 
213 #endif
214         break ;
215         
216     case TYPE:
217         fprintf(file,"(");
218         printTypeChain(op->operand.typeOperand,file);
219         fprintf(file,")");
220         break;
221     }
222     
223     if (pnl)
224         fprintf(file,"\n");
225     return 0;
226 }
227
228
229 /*-----------------------------------------------------------------*/
230 /*                    print functions                              */
231 /*-----------------------------------------------------------------*/
232 PRINTFUNC(picGetValueAtAddr)
233 {
234     fprintf(of,"\t");
235     printOperand (IC_RESULT(ic),of);
236     fprintf (of," = ");
237     fprintf (of,"@[");
238     printOperand (IC_LEFT(ic), of);
239     fprintf (of,"]");
240     
241     fprintf(of,"\n");
242 }
243
244 PRINTFUNC(picSetValueAtAddr)
245 {
246     fprintf(of,"\t");
247     fprintf(of,"*[");
248     printOperand(IC_LEFT(ic),of);
249     fprintf(of,"] = ");
250     printOperand(IC_RIGHT(ic),of);
251     fprintf (of,"\n");
252 }
253
254 PRINTFUNC(picAddrOf)
255 {
256     fprintf(of,"\t");
257     printOperand(IC_RESULT(ic),of);
258     if (IS_ITEMP(IC_LEFT(ic)))
259         fprintf(of," = ");
260     else
261         fprintf(of," = &[");
262     printOperand(IC_LEFT(ic),of);
263     if (IC_RIGHT(ic)) {
264         if (IS_ITEMP(IC_LEFT(ic)))
265             fprintf(of," offsetAdd ");
266         else
267             fprintf(of," , ");
268         printOperand(IC_RIGHT(ic),of);
269     }
270     if (IS_ITEMP(IC_LEFT(ic)))
271         fprintf (of,"\n");
272     else
273         fprintf (of,"]\n");
274 }
275
276 PRINTFUNC(picJumpTable)
277 {
278     symbol *sym;
279
280     fprintf(of,"\t");
281     fprintf(of,"%s\t",s);
282     printOperand(IC_JTCOND(ic),of);
283     fprintf(of,"\n");
284     for ( sym = setFirstItem(IC_JTLABELS(ic)); sym;
285           sym = setNextItem(IC_JTLABELS(ic))) 
286         fprintf(of,"\t\t\t%s\n",sym->name);
287 }
288
289 PRINTFUNC(picGeneric)
290 {
291     fprintf(of,"\t");
292     printOperand(IC_RESULT(ic),of);
293     fprintf(of," = ");
294     printOperand(IC_LEFT(ic),of);
295     fprintf(of," %s ",s);
296     printOperand(IC_RIGHT(ic),of);
297     fprintf(of,"\n");
298 }
299
300 PRINTFUNC(picGenericOne)
301 {
302     fprintf(of,"\t");
303     if ( IC_RESULT(ic) ) {
304         printOperand(IC_RESULT(ic),of);
305         fprintf (of," = ");
306     }
307     
308     if (IC_LEFT(ic)) {
309         fprintf (of,"%s ",s);
310         printOperand(IC_LEFT(ic),of);     
311     }
312     
313     if (! IC_RESULT(ic) && !IC_LEFT(ic))
314         fprintf (of,s);
315     
316     fprintf(of,"\n");
317 }
318
319 PRINTFUNC(picCast)
320 {
321     fprintf(of,"\t");
322     printOperand(IC_RESULT(ic),of);
323     fprintf (of," = ");
324     printOperand(IC_LEFT(ic),of);
325     printOperand(IC_RIGHT(ic),of);
326     fprintf(of,"\n");
327 }
328
329
330 PRINTFUNC(picAssign)
331 {
332     fprintf(of,"\t");
333     
334     if (IC_RESULT(ic)->isaddr && IS_ITEMP(IC_RESULT(ic)))
335         fprintf(of,"*(");
336     
337     printOperand(IC_RESULT(ic),of);  
338     
339     if (IC_RESULT(ic)->isaddr && IS_ITEMP(IC_RESULT(ic)))
340         fprintf(of,")");
341     
342     fprintf(of," %s ", s);
343     printOperand (IC_RIGHT(ic),of);
344     
345     fprintf(of,"\n");
346 }
347
348 PRINTFUNC(picLabel)
349 {
350     fprintf(of," %s($%d) :\n",IC_LABEL(ic)->name,IC_LABEL(ic)->key);
351 }
352
353 PRINTFUNC(picGoto)
354 {
355    fprintf(of,"\t");
356    fprintf (of," goto %s($%d)\n", IC_LABEL(ic)->name,IC_LABEL(ic)->key);
357 }
358
359 PRINTFUNC(picIfx)
360 {    
361     fprintf(of,"\t");
362     fprintf (of,"if ");
363     printOperand(IC_COND(ic),of);
364     
365     if ( ! IC_TRUE(ic) ) 
366         fprintf (of," == 0 goto %s($%d)\n",IC_FALSE(ic)->name,IC_FALSE(ic)->key);
367     else {
368         fprintf (of," != 0 goto %s($%d)\n",IC_TRUE(ic)->name,IC_TRUE(ic)->key);
369         if (IC_FALSE(ic))
370             fprintf (of,"\tzzgoto %s\n",IC_FALSE(ic)->name);
371     }
372 }
373
374 PRINTFUNC(picInline)
375 {
376     fprintf(of,"%s",IC_INLINE(ic));
377 }
378
379 PRINTFUNC(picReceive)
380 {
381     printOperand(IC_RESULT(ic),of);
382     fprintf(of," = %s ",s);
383     printOperand(IC_LEFT(ic),of);
384     fprintf(of,"\n");
385 }
386
387 /*-----------------------------------------------------------------*/
388 /* piCode - prints one iCode                                       */
389 /*-----------------------------------------------------------------*/
390 int piCode (void *item, FILE *of)
391 {
392     iCode *ic = item;
393     iCodeTable *icTab ;
394     
395     if (!of)
396         of = stdout;
397
398     icTab = getTableEntry(ic->op) ;
399     fprintf(stdout,"%s(%d:%d:%d:%d:%d)\t",
400                     ic->filename,ic->lineno,
401                     ic->seq,ic->key,ic->depth,ic->supportRtn);
402     icTab->iCodePrint(of,ic,icTab->printName);
403     return 1;
404 }
405
406 /*-----------------------------------------------------------------*/
407 /* printiCChain - prints intermediate code for humans              */
408 /*-----------------------------------------------------------------*/
409 void printiCChain (iCode *icChain, FILE *of)
410 {
411     iCode *loop ;
412     iCodeTable *icTab ;
413
414     if (!of)
415         of = stdout;
416     for ( loop = icChain ; loop ; loop = loop->next ) {
417         if ((icTab = getTableEntry (loop->op ))) {
418             fprintf(of,"%s(%d:%d:%d:%d:%d)\t",
419                     loop->filename,loop->lineno,
420                     loop->seq,loop->key,loop->depth,loop->supportRtn);
421
422             icTab->iCodePrint (of,loop,icTab->printName);
423         }
424     }
425 }
426
427
428 /*-----------------------------------------------------------------*/
429 /* newOperand - allocate, init & return a new iCode                */
430 /*-----------------------------------------------------------------*/
431 operand *newOperand ()
432 {
433     operand *op ;
434     
435     ALLOC(op,sizeof(operand));
436     
437     op->key = 0 ;
438     return op;
439 }
440
441 /*-----------------------------------------------------------------*/
442 /* newiCode - create and return a new iCode entry initialised      */
443 /*-----------------------------------------------------------------*/
444 iCode *newiCode (int op, operand *left, operand *right)
445 {
446     iCode *ic ;
447     
448     ALLOC(ic,sizeof(iCode));
449    
450     ic->lineno = lineno ;
451     ic->filename= filename ;
452     ic->block = block;
453     ic->level = scopeLevel;
454     ic->op = op;
455     ic->key= iCodeKey++ ;
456     IC_LEFT(ic) = left;
457     IC_RIGHT(ic)= right;
458
459     return ic;
460 }       
461
462 /*-----------------------------------------------------------------*/
463 /* newiCode for conditional statements                             */
464 /*-----------------------------------------------------------------*/
465 iCode *newiCodeCondition (operand *condition,
466                           symbol  *trueLabel, 
467                           symbol  *falseLabel )
468 {
469     iCode *ic ;
470     
471     ic = newiCode(IFX,NULL,NULL);
472     IC_COND(ic) = condition ;
473     IC_TRUE(ic) = trueLabel ;
474     IC_FALSE(ic) = falseLabel;
475     return ic;
476 }
477
478 /*-----------------------------------------------------------------*/
479 /* newiCodeLabelGoto - unconditional goto statement| label stmnt   */
480 /*-----------------------------------------------------------------*/
481 iCode *newiCodeLabelGoto (int op, symbol *label)
482 {
483     iCode *ic ;
484     
485     ic = newiCode(op,NULL,NULL);
486     ic->op = op ;
487     ic->argLabel.label = label ;
488     IC_LEFT(ic) = NULL ;
489     IC_RIGHT(ic) = NULL ;
490     IC_RESULT(ic) = NULL ;
491     return ic;
492 }
493
494 /*-----------------------------------------------------------------*/
495 /* newiTemp - allocate & return a newItemp Variable                */
496 /*-----------------------------------------------------------------*/
497 symbol *newiTemp (char *s)
498
499     symbol *itmp;
500     
501     if (s) 
502         sprintf(buffer,"%s",s);
503     else
504         sprintf (buffer,"iTemp%d",iTempNum++);  
505     itmp =  newSymbol (buffer,1);
506     strcpy(itmp->rname,itmp->name);
507     itmp->isitmp = 1;
508     
509     return itmp;
510 }
511
512 /*-----------------------------------------------------------------*/
513 /* newiTempLabel - creates a temp variable label                   */
514 /*-----------------------------------------------------------------*/
515 symbol *newiTempLabel (char *s)
516 {
517     symbol *itmplbl;
518
519     /* check if this alredy exists */
520     if (s && (itmplbl = findSym(LabelTab, NULL, s)))
521         return itmplbl ;
522
523     if (s) 
524         itmplbl = newSymbol(s,1);
525     else {
526         sprintf(buffer,"iTempLbl%d",iTempLblNum++);
527         itmplbl = newSymbol(buffer,1);  
528     }
529     
530     itmplbl->isitmp = 1;
531     itmplbl->islbl = 1;
532     itmplbl->key = labelKey++ ;
533     addSym (LabelTab, itmplbl, itmplbl->name,0,0);
534     return itmplbl ;  
535 }
536
537 /*-----------------------------------------------------------------*/
538 /* newiTempPreheaderLabel - creates a new preheader label          */
539 /*-----------------------------------------------------------------*/
540 symbol *newiTempPreheaderLabel()
541 {
542     symbol *itmplbl ;
543
544     sprintf(buffer,"preHeaderLbl%d",iTempLblNum++);
545     itmplbl = newSymbol(buffer,1);    
546     
547     itmplbl->isitmp = 1;
548     itmplbl->islbl = 1;
549     itmplbl->key = labelKey++ ;
550     addSym (LabelTab, itmplbl, itmplbl->name,0,0);
551     return itmplbl ;  
552 }
553
554
555 /*-----------------------------------------------------------------*/
556 /* initiCode - initialises some iCode related stuff                */
557 /*-----------------------------------------------------------------*/
558 void initiCode ()
559 {
560
561 }
562
563 /*-----------------------------------------------------------------*/
564 /* getTableEntry - gets the table entry for the given operator     */
565 /*-----------------------------------------------------------------*/
566 iCodeTable *getTableEntry (int oper )
567 {
568     int i ;
569     
570     for ( i = 0 ; i < (sizeof(codeTable)/sizeof(iCodeTable)); i++ ) 
571         if (oper == codeTable[i].icode)
572             return &codeTable[i] ;
573     
574     return NULL ;
575 }
576
577 /*-----------------------------------------------------------------*/
578 /* newiTempOperand - new intermediate temp operand                 */
579 /*-----------------------------------------------------------------*/
580 operand *newiTempOperand (link *type, char throwType)
581 {
582     symbol *itmp;
583     operand *op = newOperand();
584     link *etype;
585
586     op->type = SYMBOL ;
587     itmp = newiTemp(NULL);
588
589     etype = getSpec(type);
590
591     if (IS_LITERAL(etype) )
592         throwType = 0 ;
593
594     /* copy the type information */
595     if (type) 
596         itmp->etype = getSpec (itmp->type = (throwType ? type :
597                                              copyLinkChain(type)));
598     if (IS_LITERAL(itmp->etype)) {
599         SPEC_SCLS(itmp->etype) = S_REGISTER ;
600         SPEC_OCLS(itmp->etype) = reg;
601     }
602         
603     op->operand.symOperand = itmp;
604     op->key = itmp->key = ++operandKey ;
605     return op;
606 }
607
608 /*-----------------------------------------------------------------*/
609 /* operandType - returns the type chain for an operand             */
610 /*-----------------------------------------------------------------*/
611 link *operandType (operand *op) 
612 {
613     /* depending on type of operand */
614     switch (op->type) {
615         
616     case VALUE :
617         return op->operand.valOperand->type ;
618         
619     case SYMBOL:
620         return op->operand.symOperand->type ;
621         
622     case TYPE :
623         return op->operand.typeOperand ;
624     }
625     
626     werror (E_INTERNAL_ERROR,__FILE__,__LINE__,
627             " operand type not known ");
628     assert (0) ; /* should never come here */
629     /*  Just to keep the compiler happy */
630     return (link *)0;
631 }
632
633 /*-----------------------------------------------------------------*/
634 /* isParamterToCall - will return 1 if op is a parameter to args   */
635 /*-----------------------------------------------------------------*/
636 int isParameterToCall (value *args, operand *op)
637 {
638     value *tval = args ;
639
640     while (tval) {
641         if (tval->sym && 
642             isSymbolEqual(op->operand.symOperand,tval->sym))
643             return 1;
644         tval = tval->next ;
645     }
646     return 0;
647 }
648
649 /*-----------------------------------------------------------------*/
650 /* isOperandGlobal   - return 1 if operand is a global variable    */
651 /*-----------------------------------------------------------------*/
652 int isOperandGlobal ( operand *op )
653 {
654     if (!op)
655         return 0;
656
657     if (IS_ITEMP(op))
658         return 0;
659
660     if (op->type == SYMBOL &&       
661          (op->operand.symOperand->level == 0 ||  
662          IS_STATIC(op->operand.symOperand->etype) ||
663          IS_EXTERN(op->operand.symOperand->etype))
664           )
665         return 1;
666     
667     return 0;
668 }
669
670 /*-----------------------------------------------------------------*/
671 /* isOperandVolatile - return 1 if the operand is volatile         */
672 /*-----------------------------------------------------------------*/
673 int isOperandVolatile ( operand *op , bool chkTemp)
674 {
675     link *optype ;
676     link *opetype ;
677
678     if (IS_ITEMP(op) && !chkTemp)
679         return 0;
680
681     opetype = getSpec(optype = operandType(op));
682     
683     if (IS_PTR(optype) && DCL_PTR_VOLATILE(optype))
684         return 1;
685
686     if (IS_VOLATILE(opetype))
687         return 1;
688     return 0;
689 }
690
691 /*-----------------------------------------------------------------*/
692 /* isOperandLiteral - returns 1 if an operand contains a literal   */
693 /*-----------------------------------------------------------------*/
694 int isOperandLiteral ( operand *op )
695 {
696     link *opetype ;
697     
698     if (!op)
699         return 0;
700     
701     opetype = getSpec (operandType(op));
702
703     if (IS_LITERAL(opetype))
704         return 1;
705
706     return 0;
707 }
708 /*-----------------------------------------------------------------*/
709 /* isOperandInFarSpace - will return true if operand is in farSpace*/
710 /*-----------------------------------------------------------------*/
711 bool isOperandInFarSpace (operand *op)
712 {
713     link *etype;
714
715     if (!op)
716         return FALSE;
717
718     if (!IS_SYMOP(op))
719         return FALSE ;
720
721     if (!IS_TRUE_SYMOP(op)) {
722         if (SPIL_LOC(op))
723             etype = SPIL_LOC(op)->etype;
724         else            
725             return FALSE;
726     }
727
728     etype = getSpec(operandType(op));
729     return (IN_FARSPACE(SPEC_OCLS(etype)) ? TRUE : FALSE);
730 }
731
732 /*-----------------------------------------------------------------*/
733 /* operandLitValue - literal value of an operand                   */
734 /*-----------------------------------------------------------------*/
735 double operandLitValue ( operand *op )
736 {
737     assert(isOperandLiteral(op));
738     
739     return floatFromVal(op->operand.valOperand);    
740 }
741
742 /*-----------------------------------------------------------------*/
743 /* operandOperation - perforoms operations on operands             */
744 /*-----------------------------------------------------------------*/
745 operand *operandOperation (operand *left,operand *right,
746                            int op, link *type)
747 {
748     operand *retval = (operand *)0;
749         
750     assert(isOperandLiteral(left));
751     if (right) 
752         assert(isOperandLiteral(right));
753     
754     switch (op) {
755     case '+' :
756         retval =  operandFromValue (valCastLiteral(type,
757                                                    operandLitValue(left) + 
758                                                    operandLitValue(right)));
759         break ;
760     case '-' :
761         retval = operandFromValue(valCastLiteral(type,
762                                                  operandLitValue(left) -
763                                                  operandLitValue(right)));
764         break;
765     case '*':
766         retval = operandFromValue(valCastLiteral(type,
767                                                  operandLitValue(left) *
768                                                  operandLitValue(right)));
769         break;
770     case '/':
771         if ((unsigned long) operandLitValue(right) == 0){           
772             werror(E_DIVIDE_BY_ZERO);
773             retval = right;
774             
775         }
776         else
777             retval = operandFromValue (valCastLiteral(type,
778                                                       operandLitValue(left) /
779                                                       operandLitValue(right)));
780         break;
781     case '%':      
782         if ((unsigned long) operandLitValue(right) == 0){           
783             werror(E_DIVIDE_BY_ZERO);
784             retval = right;         
785         }
786         else
787             retval = operandFromLit ((unsigned long) operandLitValue(left) %
788                                      (unsigned long) operandLitValue(right));
789         break;
790     case LEFT_OP :
791         retval = operandFromLit ((unsigned long) operandLitValue(left) <<
792                                  (unsigned long) operandLitValue(right));
793         break;
794     case RIGHT_OP :
795         retval = operandFromLit ((unsigned long) operandLitValue(left) >>
796                                  (unsigned long) operandLitValue(right));
797         break;
798     case EQ_OP :
799         retval = operandFromLit (operandLitValue(left) ==
800                                  operandLitValue(right));
801         break;
802     case '<' :
803         retval = operandFromLit (operandLitValue(left) <
804                                  operandLitValue(right));
805         break;
806     case LE_OP :
807         retval = operandFromLit (operandLitValue(left) <=
808                                  operandLitValue(right));
809         break;
810     case NE_OP :
811         retval = operandFromLit (operandLitValue(left) !=
812                                  operandLitValue(right));
813         break;
814     case '>' :
815         retval = operandFromLit (operandLitValue(left) >
816                                  operandLitValue(right));
817         break;
818     case GE_OP :
819         retval = operandFromLit (operandLitValue(left) >=
820                                  operandLitValue(right));
821         break;
822     case BITWISEAND :
823         retval = operandFromLit ((unsigned long) operandLitValue(left) &
824                                  (unsigned long) operandLitValue(right));
825         break;
826     case '|' :
827         retval = operandFromLit ((unsigned long) operandLitValue(left) |
828                                  (unsigned long) operandLitValue(right));       
829         break;
830     case '^' :
831         retval = operandFromLit ((unsigned long) operandLitValue(left) ^
832                                  (unsigned long) operandLitValue(right));
833         break;
834     case AND_OP:
835         retval = operandFromLit (operandLitValue(left) &&
836                                  operandLitValue(right));
837         break;
838     case OR_OP:
839         retval = operandFromLit (operandLitValue(left) ||
840                                  operandLitValue(right));
841         break;
842     case RRC:
843         {
844             long i = operandLitValue(left);
845             
846             retval = operandFromLit ((i >> (getSize(operandType(left))*8 - 1)) |
847                                      (i << 1));
848         }
849         break;
850     case RLC:
851         {
852             long i = operandLitValue(left);
853             
854             retval = operandFromLit ((i << (getSize(operandType(left))*8 - 1)) |
855                                      (i >> 1));
856         }
857         break;
858         
859     case UNARYMINUS:
860         retval = operandFromLit(-1 * operandLitValue(left));
861         break;
862         
863     case '~':
864         retval = operandFromLit(~ ((long) operandLitValue(left)));
865         break;
866
867     case '!':
868         retval = operandFromLit(! operandLitValue(left));
869         break;
870
871     default :
872         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
873                " operandOperation invalid operator ");
874         assert (0);
875     }
876     
877     return retval;
878 }
879
880
881 /*-----------------------------------------------------------------*/
882 /* isOperandEqual - compares two operand & return 1 if they r =    */
883 /*-----------------------------------------------------------------*/
884 int isOperandEqual (operand *left, operand *right)
885 {
886     /* if the pointers are equal then they are equal */
887     if ( left == right )
888         return 1;
889     
890     /* if either of them null then false */
891     if ( !left || !right)
892         return 0;
893
894     if (left->type != right->type)
895         return 0;
896
897     if (IS_SYMOP(left) && IS_SYMOP(right))
898         return left->key == right->key ;
899
900     /* if types are the same */
901     switch (left->type) {
902     case SYMBOL :
903         return isSymbolEqual(left->operand.symOperand,
904                              right->operand.symOperand);
905     case VALUE :
906         return (floatFromVal(left->operand.valOperand) ==
907                 floatFromVal(right->operand.valOperand));
908     case TYPE :
909         if (checkType(left->operand.typeOperand,
910                       right->operand.typeOperand) == 1)
911             return 1;      
912     }
913
914     return 0;
915 }
916
917 /*-----------------------------------------------------------------*/
918 /* isiCodeEqual - comapres two iCodes are returns true if yes      */
919 /*-----------------------------------------------------------------*/
920 int isiCodeEqual (iCode *left, iCode *right)
921 {
922     /* if the same pointer */
923     if (left == right)
924         return 1;
925     
926     /* if either of them null */
927     if (!left || !right)
928         return 0;
929
930     /* if operand are the same */
931     if ( left->op == right->op ) {
932         
933         /* compare all the elements depending on type */
934         if (left->op != IFX ) {
935             if (!isOperandEqual(IC_LEFT(left),IC_LEFT(right)))
936                 return 0;
937             if (!isOperandEqual(IC_RIGHT(left),IC_RIGHT(right)))
938                 return 0;
939
940         } else {
941             if (!isOperandEqual(IC_COND(left),IC_COND(right)))
942                 return 0;
943             if (!isSymbolEqual (IC_TRUE(left),IC_TRUE(right)))
944                 return 0;
945             if (!isSymbolEqual(IC_FALSE(left),IC_FALSE(right)))
946                 return 0;
947         }
948         return 1;
949     }
950     return 0;
951 }
952
953 /*-----------------------------------------------------------------*/
954 /* operand from operand - creates an operand holder for the type   */
955 /*-----------------------------------------------------------------*/
956 operand *operandFromOperand (operand *op)
957 {
958     operand *nop = newOperand();
959     
960     nop->type = op->type;
961     nop->isaddr = op->isaddr ;
962     nop->key = op->key ;
963     nop->isvolatile = op->isvolatile ;
964     nop->isGlobal = op->isGlobal ;
965     nop->isLiteral= op->isLiteral ;
966     nop->noSpilLoc= op->noSpilLoc;
967     nop->usesDefs = op->usesDefs;
968     nop->isParm = op->isParm;
969     nop->parmBytes = op->parmBytes;
970
971     switch (nop->type) {
972     case SYMBOL :
973         nop->operand.symOperand = op->operand.symOperand ;      
974         break;
975     case VALUE :
976         nop->operand.valOperand = op->operand.valOperand;
977         break;
978     case TYPE :
979         nop->operand.typeOperand = op->operand.typeOperand ;
980         break ;
981     }   
982
983     return nop;
984 }
985
986 /*-----------------------------------------------------------------*/
987 /* opFromOpWithDU - makes a copy of the operand and DU chains      */
988 /*-----------------------------------------------------------------*/
989 operand *opFromOpWithDU (operand *op, bitVect *defs, bitVect *uses)
990 {
991     operand *nop = operandFromOperand(op);
992
993     if (nop->type == SYMBOL) {
994         OP_SYMBOL(nop)->defs = bitVectCopy(defs);
995         OP_SYMBOL(nop)->uses = bitVectCopy(uses);
996     }
997
998     return nop;
999 }
1000
1001 /*-----------------------------------------------------------------*/
1002 /* operandFromSymbol - creates an operand from a symbol            */
1003 /*-----------------------------------------------------------------*/
1004 operand *operandFromSymbol (symbol *sym)
1005 {
1006     operand *op ;
1007     iCode *ic ;
1008     
1009     /* if the symbol's type is a literal */
1010     /* then it is an enumerator type     */
1011     if (IS_LITERAL(sym->etype) && SPEC_ENUM(sym->etype)) 
1012         return operandFromValue (valFromType(sym->etype));
1013
1014     if (!sym->key)
1015         sym->key = ++operandKey ;
1016
1017     /* if this an implicit variable, means struct/union */
1018     /* member so just return it                         */
1019     if (sym->implicit || IS_FUNC(sym->type)) {
1020         op = newOperand();
1021         op->type = SYMBOL ;
1022         op->operand.symOperand = sym;
1023         op->key = sym->key ;
1024         op->isvolatile = isOperandVolatile(op,TRUE);
1025         op->isGlobal   = isOperandGlobal(op);
1026         return op;
1027     }
1028     
1029     /* under the following conditions create a
1030        register equivalent for a local symbol */
1031     if (!IS_AGGREGATE(sym->type) &&     /* not an aggregate */
1032         !IS_FUNC(sym->type)      &&     /* not a function   */
1033         !sym->_isparm            &&     /* not a parameter  */
1034         sym->level               &&     /* is a local variable */
1035         !sym->addrtaken          &&     /* whose address has not been taken */
1036         !sym->reqv               &&     /* does not already have a register euivalence */
1037         !IS_VOLATILE(sym->etype) &&     /* not declared as volatile */
1038         !IS_STATIC(sym->etype)   &&     /* and not declared static  */
1039         !sym->islbl              &&
1040         !IN_FARSPACE(SPEC_OCLS(sym->etype))) {     /* not a label */
1041         
1042         /* we will use it after all optimizations
1043            and before liveRange calculation */
1044         sym->reqv = newiTempOperand(sym->type,0);       
1045         sym->reqv->key = sym->key ;
1046         OP_SYMBOL(sym->reqv)->key = sym->key;
1047         OP_SYMBOL(sym->reqv)->isreqv = 1;
1048         OP_SYMBOL(sym->reqv)->islocal = 1;
1049         SPIL_LOC(sym->reqv) = sym;
1050     }
1051
1052     if (!IS_AGGREGATE(sym->type)) {
1053         op = newOperand();
1054         op->type = SYMBOL;
1055         op->operand.symOperand = sym;
1056         op->isaddr = 1;
1057         op->key = sym->key;
1058         op->isvolatile = isOperandVolatile(op,TRUE);
1059         op->isGlobal   = isOperandGlobal(op);
1060         op->isPtr = IS_PTR(operandType(op));
1061         op->isParm = sym->_isparm ;
1062         return op;
1063     }
1064     
1065     /* create :-                     */
1066     /*    itemp = &[_symbol]         */
1067     
1068     ic = newiCode(ADDRESS_OF,newOperand(),NULL);
1069     IC_LEFT(ic)->type = SYMBOL ;
1070     IC_LEFT(ic)->operand.symOperand = sym ;
1071     IC_LEFT(ic)->key = sym->key;    
1072     (IC_LEFT(ic))->isvolatile = isOperandVolatile(IC_LEFT(ic),TRUE);
1073     (IC_LEFT(ic))->isGlobal   = isOperandGlobal(IC_LEFT(ic));
1074     IC_LEFT(ic)->isPtr = IS_PTR(operandType(IC_LEFT(ic)));
1075
1076     /* create result */
1077     IC_RESULT(ic) = newiTempOperand(sym->type,0);
1078     if (IS_ARRAY(sym->type)) {
1079         IC_RESULT(ic) = geniCodeArray2Ptr (IC_RESULT(ic));
1080         IC_RESULT(ic)->isaddr = 0;
1081     } else
1082         IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(sym->type));
1083
1084     IC_RESULT(ic)->operand.symOperand->args = sym->args;
1085
1086     ADDTOCHAIN(ic);
1087     
1088     return IC_RESULT(ic) ;
1089 }
1090
1091 /*-----------------------------------------------------------------*/
1092 /* operandFromValue - creates an operand from value                */
1093 /*-----------------------------------------------------------------*/
1094 operand *operandFromValue (value *val)
1095 {
1096     operand *op ;
1097     
1098     /* if this is a symbol then do the symbol thing */
1099     if (val->sym)
1100         return operandFromSymbol (val->sym);
1101     
1102     /* this is not a symbol */
1103     op = newOperand();
1104     op->type = VALUE ;
1105     op->operand.valOperand = val ;
1106     op->isLiteral = isOperandLiteral(op);
1107     return op;
1108 }
1109
1110 /*-----------------------------------------------------------------*/
1111 /* operandFromLink - operand from typeChain                        */
1112 /*-----------------------------------------------------------------*/
1113 operand *operandFromLink (link *type)
1114 {
1115     operand *op ;
1116     
1117     /* operand from link */
1118     if ( ! type )
1119         return NULL ;
1120     
1121     op = newOperand();
1122     op->type = TYPE ;
1123     op->operand.typeOperand = copyLinkChain(type);
1124     return op;
1125 }
1126
1127 /*-----------------------------------------------------------------*/
1128 /* operandFromLit - makes an operand from a literal value          */
1129 /*-----------------------------------------------------------------*/
1130 operand *operandFromLit ( float i)
1131 {
1132     return operandFromValue (valueFromLit (i));
1133 }
1134
1135 /*-----------------------------------------------------------------*/
1136 /* operandFromAst - creates an operand from an ast                 */
1137 /*-----------------------------------------------------------------*/
1138 operand *operandFromAst ( ast *tree )
1139 {
1140     
1141     if (! tree )
1142         return NULL ;
1143     
1144     /* depending on type do */
1145     switch (tree->type ) {      
1146     case EX_OP : 
1147         return ast2iCode (tree) ;    
1148         break ;
1149         
1150     case EX_VALUE :
1151         return operandFromValue(tree->opval.val) ;
1152         break ;
1153         
1154     case EX_LINK :
1155         return operandFromLink (tree->opval.lnk) ; 
1156     }
1157     
1158     assert(0);
1159     /*  Just to keep the comiler happy */
1160     return (operand *)0;
1161 }
1162
1163 /*-----------------------------------------------------------------*/
1164 /* setOperandType - sets the operand's type to the given type      */
1165 /*-----------------------------------------------------------------*/
1166 void setOperandType (operand *op, link *type)
1167 {
1168     /* depending on the type of operand */
1169     switch (op->type) {
1170         
1171     case VALUE :
1172         op->operand.valOperand->etype = 
1173             getSpec( op->operand.valOperand->type = 
1174                      copyLinkChain (type )) ;
1175         return ;
1176         
1177     case SYMBOL :
1178         if (op->operand.symOperand->isitmp )
1179             op->operand.symOperand->etype = 
1180                 getSpec( op->operand.symOperand->type = 
1181                          copyLinkChain (type )) ;
1182         else
1183             werror (E_INTERNAL_ERROR,__FILE__,__LINE__,
1184                     "attempt to modify type of source");
1185         return;
1186         
1187     case TYPE:
1188         op->operand.typeOperand = copyLinkChain (type);
1189         return ;
1190     }
1191     
1192 }
1193
1194 /*-----------------------------------------------------------------*/
1195 /* geniCodeValueAtAddress - generate intermeditate code for value  */
1196 /*                          at address                             */
1197 /*-----------------------------------------------------------------*/
1198 operand *geniCodeRValue (operand *op, bool force)
1199 {
1200     iCode *ic ;
1201     link *type = operandType(op);
1202     link *etype= getSpec(type);
1203     
1204     /* if this is an array & already */
1205     /* an address then return this   */
1206     if (IS_AGGREGATE(type) || 
1207         (IS_PTR(type) && !force && !op->isaddr))
1208         return operandFromOperand(op);
1209         
1210     /* if this is not an address then must be */
1211     /* rvalue already so return this one      */
1212     if (!op->isaddr)
1213         return op ;
1214     
1215     /* if this is not a temp symbol then */
1216     if (!IS_ITEMP(op) && 
1217         !force        && 
1218         !IN_FARSPACE(SPEC_OCLS(etype))) {
1219         op = operandFromOperand(op);
1220         op->isaddr = 0;
1221         return op;
1222     }
1223     
1224     if (IS_SPEC(type) && 
1225         IS_TRUE_SYMOP(op) &&
1226         !IN_FARSPACE(SPEC_OCLS(etype))) {
1227         op = operandFromOperand(op);
1228         op->isaddr = 0;
1229         return op;
1230     }
1231
1232     ic = newiCode(GET_VALUE_AT_ADDRESS,op,NULL);
1233     if (IS_PTR(type) && op->isaddr && force) 
1234         type = type->next;
1235     
1236     type = copyLinkChain(type);
1237
1238     IC_RESULT(ic) = newiTempOperand (type,1);
1239     IC_RESULT(ic)->isaddr = 0;
1240  
1241 /*     ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1242
1243     /* if the right is a symbol */
1244     if (op->type == SYMBOL)
1245         IC_RESULT(ic)->operand.symOperand->args = 
1246             op->operand.symOperand->args ;
1247     ADDTOCHAIN(ic);
1248     
1249     return IC_RESULT(ic) ;
1250 }
1251
1252 /*-----------------------------------------------------------------*/
1253 /* geniCodeCast - changes the value from one type to another       */
1254 /*-----------------------------------------------------------------*/
1255 operand *geniCodeCast (link *type, operand *op, bool implicit) 
1256 {
1257     iCode *ic ;
1258     link *optype ;
1259     link *opetype = getSpec(optype = operandType(op));
1260     link *restype ;
1261     
1262     /* one of them has size zero then error */
1263     if (IS_VOID(optype)) {
1264         werror(E_CAST_ZERO);
1265         return op;
1266     }
1267
1268     /* if the operand is already the desired type then do nothing */
1269     if ( checkType (type,optype) == 1)  
1270         return op;
1271     
1272     /* if this is a literal then just change the type & return */
1273     if (IS_LITERAL(opetype) && !IS_PTR(type) && !IS_PTR(optype))
1274         return operandFromValue(valCastLiteral(type,
1275                                                operandLitValue(op)));
1276           
1277     /* if casting to some pointer type &&
1278        the destination is not a generic pointer 
1279        then give a warning : (only for implicit casts)*/
1280     if (IS_PTR(optype) && implicit &&
1281         (DCL_TYPE(optype) != DCL_TYPE(type)) && 
1282         !IS_GENPTR(type)) {
1283         werror(E_INCOMPAT_CAST);
1284         werror(E_CONTINUE,"from type '");
1285         printTypeChain(optype,stderr);fprintf(stderr,"' to type '");      
1286         printTypeChain(type,stderr);fprintf(stderr,"'\n");
1287     }
1288
1289     /* if they are the same size create an assignment */
1290     if (getSize(type) == getSize(optype) && 
1291         !IS_BITFIELD(type)               &&
1292         !IS_FLOAT(type)                  &&
1293         !IS_FLOAT(optype)                &&
1294         ((IS_SPEC(type) && IS_SPEC(optype)) ||
1295          (!IS_SPEC(type) && !IS_SPEC(optype)))) {
1296
1297         ic = newiCode('=',NULL,op);     
1298         IC_RESULT(ic) = newiTempOperand(type,0);
1299          SPIL_LOC(IC_RESULT(ic))  =
1300              (IS_TRUE_SYMOP(op) ? OP_SYMBOL(op) : NULL);
1301         IC_RESULT(ic)->isaddr = 0;
1302     } else { 
1303         ic = newiCode(CAST,operandFromLink(type),
1304                       geniCodeRValue(op,FALSE));
1305         
1306         IC_RESULT(ic)= newiTempOperand(type,0);
1307     }
1308     
1309     /* preserve the storage class & output class */
1310     /* of the original variable                  */
1311     restype = getSpec(operandType(IC_RESULT(ic)));
1312     SPEC_SCLS(restype) = SPEC_SCLS(opetype);
1313     SPEC_OCLS(restype) = SPEC_OCLS(opetype);
1314     
1315     ADDTOCHAIN(ic);
1316     return IC_RESULT(ic) ;
1317 }
1318
1319 /*-----------------------------------------------------------------*/
1320 /* geniCodeLabel - will create a Label                             */
1321 /*-----------------------------------------------------------------*/
1322 void geniCodeLabel (symbol *label)
1323 {
1324     iCode *ic;
1325     
1326     ic = newiCodeLabelGoto(LABEL,label);
1327     ADDTOCHAIN(ic);
1328 }
1329
1330 /*-----------------------------------------------------------------*/
1331 /* geniCodeGoto  - will create a Goto                              */
1332 /*-----------------------------------------------------------------*/
1333 void geniCodeGoto (symbol *label)
1334 {
1335     iCode *ic;
1336     
1337     ic = newiCodeLabelGoto(GOTO,label);
1338     ADDTOCHAIN(ic);
1339 }
1340
1341 /*-----------------------------------------------------------------*/
1342 /* geniCodeMultiply - gen intermediate code for multiplication     */
1343 /*-----------------------------------------------------------------*/
1344 operand *geniCodeMultiply (operand *left, operand *right)
1345
1346     iCode *ic ;
1347     int p2 = 0;
1348     link *resType ;
1349     LRTYPE ;
1350     
1351     /* if they are both literal then we know the result */
1352     if (IS_LITERAL(letype) && IS_LITERAL(retype)) 
1353         return operandFromValue (valMult(left->operand.valOperand,
1354                                          right->operand.valOperand));
1355         
1356     resType = computeType (ltype,rtype) ;
1357     left = geniCodeCast(resType,left,TRUE);
1358     right= geniCodeCast(resType,right,TRUE);
1359     
1360     /* if the right is a literal & power of 2 */
1361     /* then make it a left shift              */
1362     if (IS_LITERAL(retype) && !IS_FLOAT(letype) &&
1363         (p2 = powof2 ((unsigned long)floatFromVal(right->operand.valOperand)))) 
1364         ic = newiCode(LEFT_OP, left,operandFromLit(p2)); /* left shift */
1365     else {
1366         ic = newiCode('*',left,right);  /* normal multiplication */
1367         /* if the size left or right > 1 then support routine */
1368         if (getSize(ltype) > 1 || getSize(rtype) > 1)
1369             ic->supportRtn = 1;
1370
1371     }
1372     IC_RESULT(ic) = newiTempOperand(resType,1);
1373     
1374     ADDTOCHAIN(ic);
1375     return IC_RESULT(ic) ;
1376 }
1377
1378 /*-----------------------------------------------------------------*/
1379 /* geniCodeDivision - gen intermediate code for division           */
1380 /*-----------------------------------------------------------------*/
1381 operand *geniCodeDivision (operand *left, operand *right)
1382
1383     iCode *ic ;
1384     int p2 = 0;
1385     link *resType;
1386     link *rtype = operandType(right);
1387     link *retype= getSpec(rtype);
1388     link *ltype = operandType(left);
1389     link *letype= getSpec(ltype);
1390     
1391     resType = computeType (ltype,rtype) ;
1392     left = geniCodeCast(resType,left,TRUE);
1393     right= geniCodeCast(resType,right,TRUE);
1394     
1395     /* if the right is a literal & power of 2 */
1396     /* then make it a right shift             */
1397     if (IS_LITERAL(retype) && 
1398         !IS_FLOAT(letype)  &&
1399         (p2 = powof2 ((unsigned long) 
1400                       floatFromVal(right->operand.valOperand)))) 
1401         ic = newiCode(RIGHT_OP, left,operandFromLit(p2)); /* right shift */
1402     else {
1403         ic = newiCode('/',left,right);  /* normal division */
1404         /* if the size left or right > 1 then support routine */
1405         if (getSize(ltype) > 1 || getSize(rtype) > 1)
1406             ic->supportRtn = 1;
1407     }
1408     IC_RESULT(ic) = newiTempOperand(resType,0);
1409     
1410     ADDTOCHAIN(ic);
1411     return IC_RESULT(ic) ;
1412 }
1413 /*-----------------------------------------------------------------*/
1414 /* geniCodeModulus  - gen intermediate code for modulus            */
1415 /*-----------------------------------------------------------------*/
1416 operand *geniCodeModulus (operand *left, operand *right)
1417
1418     iCode *ic ;
1419     link *resType;
1420     LRTYPE ;
1421     
1422     /* if they are both literal then we know the result */
1423     if (IS_LITERAL(letype) && IS_LITERAL(retype)) 
1424         return operandFromValue (valMod(left->operand.valOperand,
1425                                         right->operand.valOperand));
1426     
1427     resType = computeType (ltype,rtype) ;
1428     left = geniCodeCast(resType,left,TRUE);
1429     right= geniCodeCast(resType,right,TRUE);
1430     
1431     /* now they are the same size */
1432     ic = newiCode('%',left,right);
1433
1434     /* if the size left or right > 1 then support routine */
1435     if (getSize(ltype) > 1 || getSize(rtype) > 1)
1436         ic->supportRtn = 1;
1437     IC_RESULT(ic) = newiTempOperand(resType,0);
1438     
1439     ADDTOCHAIN(ic);
1440     return IC_RESULT(ic) ;
1441 }
1442
1443 /*-----------------------------------------------------------------*/
1444 /* geniCodePtrPtrSubtract - subtracts pointer from pointer         */
1445 /*-----------------------------------------------------------------*/
1446 operand *geniCodePtrPtrSubtract (operand *left, operand *right)
1447 {
1448     iCode *ic ;
1449     operand *result;
1450     LRTYPE ;
1451     
1452     /* if they are both literals then */
1453     if (IS_LITERAL(letype) && IS_LITERAL(retype)) {
1454         result = operandFromValue (valMinus(left->operand.valOperand,
1455                                             right->operand.valOperand));
1456         goto subtractExit;
1457     }
1458     
1459     ic = newiCode('-',left,right);
1460     
1461     IC_RESULT(ic) = result = newiTempOperand(newIntLink(),1);
1462     ADDTOCHAIN(ic);
1463     
1464  subtractExit:
1465     return geniCodeDivision (result,
1466                              operandFromLit(getSize(ltype->next)));   
1467 }
1468
1469 /*-----------------------------------------------------------------*/
1470 /* geniCodeSubtract - generates code for subtraction               */
1471 /*-----------------------------------------------------------------*/
1472 operand *geniCodeSubtract (operand *left, operand *right)
1473 {
1474     iCode *ic ;
1475     int isarray= 0;
1476     link *resType;
1477     LRTYPE ;
1478     
1479     /* if they both pointers then */
1480     if ((IS_PTR(ltype) || IS_ARRAY(ltype)) &&
1481         (IS_PTR(rtype) || IS_ARRAY(rtype)))
1482         return geniCodePtrPtrSubtract (left,right);
1483     
1484     /* if they are both literal then we know the result */
1485     if (IS_LITERAL(letype) && IS_LITERAL(retype)) 
1486         return operandFromValue (valMinus(left->operand.valOperand,
1487                                           right->operand.valOperand));
1488     
1489     /* if left is an array or pointer */
1490     if ( IS_PTR(ltype) || IS_ARRAY(ltype) ) {    
1491         isarray = left->isaddr ;    
1492         right = geniCodeMultiply (right,
1493                                   operandFromLit(getSize(ltype->next)));
1494         resType = copyLinkChain(IS_ARRAY(ltype) ? ltype->next : ltype);
1495     }
1496     else { /* make them the same size */
1497         resType = computeType (ltype,rtype) ;
1498         left = geniCodeCast(resType,left,TRUE);
1499         right= geniCodeCast(resType,right,TRUE);    
1500     }
1501     
1502     ic = newiCode('-',left,right);
1503     
1504     IC_RESULT(ic)= newiTempOperand(resType,1);
1505     IC_RESULT(ic)->isaddr = (isarray ? 1 : 0);
1506
1507     /* if left or right is a float */
1508     if (IS_FLOAT(ltype) || IS_FLOAT(rtype))
1509         ic->supportRtn = 1;
1510
1511     ADDTOCHAIN(ic);
1512     return IC_RESULT(ic) ;
1513 }
1514
1515 /*-----------------------------------------------------------------*/
1516 /* geniCodeAdd - generates iCode for addition                      */
1517 /*-----------------------------------------------------------------*/
1518 operand *geniCodeAdd (operand *left, operand *right )
1519 {
1520     iCode *ic ;
1521     link *resType ;
1522     operand *size ;
1523     int isarray = 0;
1524     LRTYPE ;
1525     
1526     /* if left is an array then array access */
1527     if (IS_ARRAY(ltype)) 
1528         return geniCodeArray (left,right);           
1529     
1530     /* if the right side is LITERAL zero */
1531     /* return the left side              */
1532     if (IS_LITERAL(retype) && !floatFromVal(valFromType(retype)))
1533         return left;
1534     
1535     /* if left is literal zero return right */
1536     if (IS_LITERAL(letype) && !floatFromVal(valFromType(letype)))
1537         return right ;
1538     
1539     /* if left is an array or pointer then size */
1540     if (IS_PTR(ltype)) {    
1541         
1542         isarray = left->isaddr;
1543         size = 
1544             operandFromLit(getSize(ltype->next));
1545         right = geniCodeMultiply (right ,size);
1546         resType = copyLinkChain(ltype);
1547     }
1548     else { /* make them the same size */
1549         resType = computeType (ltype,rtype) ;
1550         left = geniCodeCast(resType,left,TRUE);
1551         right= geniCodeCast(resType,right,TRUE);
1552     }
1553     
1554     /* if they are both literals then we know */
1555     if (IS_LITERAL(letype) && IS_LITERAL(retype))
1556         return operandFromValue (valPlus(valFromType(letype),
1557                                          valFromType(retype)));
1558     
1559     ic = newiCode('+',left,right);
1560     
1561     IC_RESULT(ic) = newiTempOperand(resType,1);
1562     IC_RESULT(ic)->isaddr = ( isarray ? 1 : 0);
1563
1564     /* if left or right is a float then support
1565        routine */
1566     if (IS_FLOAT(ltype) || IS_FLOAT(rtype))
1567         ic->supportRtn = 1;
1568
1569     ADDTOCHAIN(ic);
1570     
1571     return IC_RESULT(ic) ;
1572     
1573 }
1574
1575 /*-----------------------------------------------------------------*/
1576 /* aggrToPtr - changes an aggregate to pointer to an aggregate     */
1577 /*-----------------------------------------------------------------*/
1578 link *aggrToPtr ( link *type, bool force)
1579 {
1580     link *etype ;
1581     link *ptype ;
1582
1583     
1584     if (IS_PTR(type) && !force)
1585         return type;
1586
1587     etype = getSpec(type);
1588     ptype = newLink();
1589
1590     ptype->next = type;
1591     /* if the output class is generic */
1592     if (SPEC_OCLS(etype) == generic)
1593         DCL_TYPE(ptype) = GPOINTER;
1594     else
1595         if (SPEC_OCLS(etype)->codesp ) {
1596             DCL_TYPE(ptype) = CPOINTER ;
1597             DCL_PTR_CONST(ptype) = 1;
1598         }
1599         else
1600             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
1601                 DCL_TYPE(ptype) = FPOINTER ;
1602             else
1603                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
1604                     DCL_TYPE(ptype) = PPOINTER ;
1605                 else
1606                     if (SPEC_OCLS(etype) == idata)
1607                         DCL_TYPE(ptype) = IPOINTER;
1608                     else
1609                         DCL_TYPE(ptype) = POINTER ;
1610     
1611     /* if the variable was declared a constant */
1612     /* then the pointer points to a constant */
1613     if (IS_CONSTANT(etype) )
1614         DCL_PTR_CONST(ptype) = 1;
1615
1616     /* the variable was volatile then pointer to volatile */
1617     if (IS_VOLATILE(etype))
1618         DCL_PTR_VOLATILE(ptype) = 1;
1619     return ptype; 
1620 }
1621
1622 /*-----------------------------------------------------------------*/
1623 /* geniCodeArray2Ptr - array to pointer                            */
1624 /*-----------------------------------------------------------------*/
1625 operand *geniCodeArray2Ptr (operand *op)
1626 {
1627     link *optype = operandType(op);
1628     link *opetype = getSpec(optype);
1629     
1630     /* set the pointer depending on the storage class */
1631     if (SPEC_OCLS(opetype)->codesp ) {
1632         DCL_TYPE(optype) = CPOINTER ;
1633         DCL_PTR_CONST(optype) = 1;
1634     }
1635     else
1636         if (SPEC_OCLS(opetype)->fmap && !SPEC_OCLS(opetype)->paged)
1637             DCL_TYPE(optype) = FPOINTER ;
1638         else
1639             if (SPEC_OCLS(opetype)->fmap && SPEC_OCLS(opetype)->paged)
1640                 DCL_TYPE(optype) = PPOINTER ;
1641             else
1642                 if (SPEC_OCLS(opetype) == idata)
1643                     DCL_TYPE(optype) = IPOINTER;
1644                 else
1645                     DCL_TYPE(optype) = POINTER ;
1646     
1647     /* if the variable was declared a constant */
1648     /* then the pointer points to a constant */
1649     if (IS_CONSTANT(opetype) )
1650         DCL_PTR_CONST(optype) = 1;
1651
1652     /* the variable was volatile then pointer to volatile */
1653     if (IS_VOLATILE(opetype))
1654         DCL_PTR_VOLATILE(optype) = 1;
1655     op->isaddr = 0;
1656     return op;
1657 }
1658
1659 /*-----------------------------------------------------------------*/
1660 /* geniCodeArray - array access                                    */
1661 /*-----------------------------------------------------------------*/
1662 operand *geniCodeArray (operand *left,operand *right)
1663 {
1664     iCode *ic;
1665     link *ltype = operandType(left);
1666     
1667     if (IS_PTR(ltype)) {
1668         operand *r ;
1669         int olval = lvaluereq ;
1670         lvaluereq = IS_PTR(ltype->next);
1671         r= geniCodeDerefPtr(geniCodeAdd(left,right));
1672         lvaluereq = olval;
1673         return r;
1674     }
1675
1676    /* array access */
1677     right = geniCodeMultiply(right,
1678                              operandFromLit(getSize(ltype->next)));
1679
1680     /* we can check for limits here */
1681     if (isOperandLiteral(right) &&
1682         IS_ARRAY(ltype)         &&
1683         DCL_ELEM(ltype)         &&
1684         (operandLitValue(right)/getSize(ltype->next)) >= DCL_ELEM(ltype)) {
1685         werror(E_ARRAY_BOUND);
1686         right = operandFromLit(0);
1687     }
1688
1689     ic = newiCode('+',left,right);    
1690
1691     IC_RESULT(ic) = newiTempOperand(((IS_PTR(ltype) && 
1692                                       !IS_AGGREGATE(ltype->next) &&
1693                                       !IS_PTR(ltype->next))
1694                                      ? ltype : ltype->next),0);
1695 /*     IC_RESULT(ic) = newiTempOperand(ltype->next,0); */
1696     IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(ltype->next));
1697     ADDTOCHAIN(ic);
1698     return IC_RESULT(ic) ;
1699 }
1700
1701 /*-----------------------------------------------------------------*/
1702 /* geniCodeStruct - generates intermediate code for structres      */
1703 /*-----------------------------------------------------------------*/
1704 operand *geniCodeStruct (operand *left, operand *right, bool islval)
1705 {
1706     iCode *ic ;
1707     link *type = operandType(left);
1708     link *etype = getSpec(type);
1709     link *retype ;
1710     symbol *element = getStructElement(SPEC_STRUCT(etype), 
1711                                        right->operand.symOperand);
1712     
1713     /* add the offset */
1714     ic = newiCode('+',left,operandFromLit(element->offset));
1715     
1716     IC_RESULT(ic) = newiTempOperand(element->type,0);
1717
1718     /* preserve the storage & output class of the struct */
1719     /* as well as the volatile attribute */
1720     retype = getSpec(operandType(IC_RESULT(ic)));
1721     SPEC_SCLS(retype) = SPEC_SCLS(etype);
1722     SPEC_OCLS(retype) = SPEC_OCLS(etype);
1723     SPEC_VOLATILE(retype) |= SPEC_VOLATILE(etype);    
1724
1725     if (IS_PTR(element->type)) 
1726         setOperandType(IC_RESULT(ic),aggrToPtr(operandType(IC_RESULT(ic)),TRUE));
1727     
1728     IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(element->type));
1729
1730     
1731     ADDTOCHAIN(ic);
1732     return (islval ? IC_RESULT(ic) : geniCodeRValue(IC_RESULT(ic),TRUE));
1733 }
1734
1735 /*-----------------------------------------------------------------*/
1736 /* geniCodePostInc - generate int code for Post increment          */
1737 /*-----------------------------------------------------------------*/
1738 operand *geniCodePostInc (operand *op)
1739 {
1740     iCode *ic ;
1741     operand *rOp ;
1742     link *optype = operandType(op);
1743     operand *result ;
1744     operand *rv = (IS_ITEMP(op) ? 
1745                    geniCodeRValue(op,(IS_PTR(optype) ? TRUE : FALSE)) :
1746                    op);            
1747     link *rvtype = operandType(rv);    
1748     int diff = (IS_PTR(rvtype) && DCL_TYPE(optype) != DCL_TYPE(rvtype));
1749     int size = 0;
1750     
1751     /* if this is not an address we have trouble */
1752     if ( ! op->isaddr ) {
1753         werror (E_LVALUE_REQUIRED,"++");
1754         return op ;
1755     }
1756     
1757     rOp = newiTempOperand((diff ? rvtype : optype),0);
1758     rOp->noSpilLoc = 1;
1759
1760     if (IS_ITEMP(rv))
1761         rv->noSpilLoc = 1;
1762
1763     geniCodeAssign(rOp,rv,0);
1764    
1765     size = (IS_PTR(rvtype) ? getSize(rvtype->next) : 1);
1766     ic = newiCode('+',rv,operandFromLit(size));          
1767     IC_RESULT(ic) = result =newiTempOperand((diff ? rvtype : optype),0);
1768     ADDTOCHAIN(ic);
1769
1770     geniCodeAssign(op,result,0);
1771     
1772     return rOp;
1773     
1774 }
1775
1776 /*-----------------------------------------------------------------*/
1777 /* geniCodePreInc - generate code for preIncrement                 */
1778 /*-----------------------------------------------------------------*/
1779 operand *geniCodePreInc (operand *op)
1780 {
1781     iCode *ic ;
1782     link *optype = operandType(op);    
1783     operand *rop = (IS_ITEMP(op) ? 
1784                     geniCodeRValue (op,(IS_PTR(optype) ? TRUE : FALSE)) :
1785                     op);
1786     link *roptype = operandType(rop);
1787     int diff = (IS_PTR(roptype) && (DCL_TYPE(roptype) != DCL_TYPE(optype)));
1788     operand *result;
1789     int size = 0;
1790     
1791     if ( ! op->isaddr ) {
1792         werror(E_LVALUE_REQUIRED,"++");
1793         return op ;
1794     }
1795
1796
1797     size = (IS_PTR(roptype) ? getSize(roptype->next) : 1);
1798     ic = newiCode('+',rop,operandFromLit(size));
1799     IC_RESULT(ic) = result = newiTempOperand((diff ? roptype : optype),0) ;
1800     ADDTOCHAIN(ic);
1801
1802     
1803     return geniCodeAssign(op,result,0) ;
1804 }
1805
1806 /*-----------------------------------------------------------------*/
1807 /* geniCodePostDec - generates code for Post decrement             */
1808 /*-----------------------------------------------------------------*/
1809 operand *geniCodePostDec (operand *op)
1810 {
1811     iCode *ic ;
1812     operand *rOp ;
1813     link *optype = operandType(op);
1814     operand *result ;
1815     operand *rv = (IS_ITEMP(op) ? 
1816                    geniCodeRValue(op,(IS_PTR(optype) ? TRUE : FALSE)) :
1817                    op);            
1818     link *rvtype = operandType(rv);    
1819     int diff = (IS_PTR(rvtype) && DCL_TYPE(optype) != DCL_TYPE(rvtype));
1820     int size = 0;
1821     
1822     /* if this is not an address we have trouble */
1823     if ( ! op->isaddr ) {
1824         werror (E_LVALUE_REQUIRED,"++");
1825         return op ;
1826     }
1827     
1828     rOp = newiTempOperand((diff ? rvtype : optype),0);
1829     rOp->noSpilLoc = 1;
1830
1831     if (IS_ITEMP(rv))
1832         rv->noSpilLoc = 1;
1833
1834     geniCodeAssign(rOp,rv,0);
1835    
1836     size = (IS_PTR(rvtype) ? getSize(rvtype->next) : 1);
1837     ic = newiCode('-',rv,operandFromLit(size));          
1838     IC_RESULT(ic) = result =newiTempOperand((diff ? rvtype : optype),0);
1839     ADDTOCHAIN(ic);
1840
1841     geniCodeAssign(op,result,0);
1842     
1843     return rOp;
1844     
1845 }
1846
1847 /*-----------------------------------------------------------------*/
1848 /* geniCodePreDec - generate code for pre  decrement               */
1849 /*-----------------------------------------------------------------*/
1850 operand *geniCodePreDec (operand *op)
1851 {  
1852     iCode *ic ;
1853     link *optype = operandType(op);    
1854     operand *rop = (IS_ITEMP(op) ? 
1855                     geniCodeRValue (op,(IS_PTR(optype) ? TRUE : FALSE)) :
1856                     op);
1857     link *roptype = operandType(rop);
1858     int diff = (IS_PTR(roptype) && (DCL_TYPE(roptype) != DCL_TYPE(optype)));
1859     operand *result;
1860     int size = 0;
1861     
1862     if ( ! op->isaddr ) {
1863         werror(E_LVALUE_REQUIRED,"++");
1864         return op ;
1865     }
1866
1867
1868     size = (IS_PTR(roptype) ? getSize(roptype->next) : 1);
1869     ic = newiCode('-',rop,operandFromLit(size));
1870     IC_RESULT(ic) = result = newiTempOperand((diff ? roptype : optype),0) ;
1871     ADDTOCHAIN(ic);
1872
1873     
1874     return geniCodeAssign(op,result,0) ;
1875 }
1876
1877
1878 /*-----------------------------------------------------------------*/
1879 /* geniCodeBitwise - gen int code for bitWise  operators           */
1880 /*-----------------------------------------------------------------*/
1881 operand *geniCodeBitwise (operand *left, operand *right, 
1882                           int oper, link *resType)
1883 {
1884     iCode *ic;   
1885     
1886     left = geniCodeCast(resType,left,TRUE);
1887     right= geniCodeCast(resType,right,TRUE);
1888     
1889     ic = newiCode(oper,left,right);
1890     IC_RESULT(ic) = newiTempOperand(resType,0);
1891     
1892     ADDTOCHAIN(ic);
1893     return IC_RESULT(ic) ;
1894 }
1895
1896 /*-----------------------------------------------------------------*/
1897 /* geniCodeAddressOf - gens icode for '&' address of operator      */
1898 /*-----------------------------------------------------------------*/
1899 operand *geniCodeAddressOf (operand *op) 
1900 {
1901     iCode *ic;
1902     link *p ;
1903     link *optype = operandType(op);
1904     link *opetype= getSpec(optype);
1905     
1906     /* this must be a lvalue */
1907     if (!op->isaddr && !IS_AGGREGATE(optype)) {
1908         werror (E_LVALUE_REQUIRED,"&");
1909         return op;
1910     }
1911     
1912     p = newLink();
1913     p->class = DECLARATOR ;
1914     /* set the pointer depending on the storage class */
1915     if (SPEC_OCLS(opetype)->codesp ) {
1916         DCL_TYPE(p) = CPOINTER ;
1917         DCL_PTR_CONST(p) = 1;
1918     }
1919     else
1920         if (SPEC_OCLS(opetype)->fmap && !SPEC_OCLS(opetype)->paged)
1921             DCL_TYPE(p) = FPOINTER ;
1922         else
1923             if (SPEC_OCLS(opetype)->fmap && SPEC_OCLS(opetype)->paged)
1924                 DCL_TYPE(p) = PPOINTER ;
1925             else
1926                 if (SPEC_OCLS(opetype) == idata)
1927                     DCL_TYPE(p) = IPOINTER;
1928                 else
1929                     if (SPEC_OCLS(opetype) == data ||
1930                         SPEC_OCLS(opetype) == overlay)
1931                         DCL_TYPE(p) = POINTER ;
1932                     else
1933                         DCL_TYPE(p) = GPOINTER;
1934     
1935     /* make sure we preserve the const & volatile */
1936     if (IS_CONSTANT(opetype)) 
1937         DCL_PTR_CONST(p) = 1;
1938
1939     if (IS_VOLATILE(opetype))
1940         DCL_PTR_VOLATILE(p) = 1;
1941     
1942     p->next = copyLinkChain(optype);
1943     
1944     /* if already a temp */
1945     if (IS_ITEMP(op)) {
1946         setOperandType (op,p);     
1947         op->isaddr= 0;
1948         return op;
1949     }
1950     
1951     /* other wise make this of the type coming in */
1952     ic = newiCode(ADDRESS_OF,op,NULL);
1953     IC_RESULT(ic) = newiTempOperand(p,1);
1954     IC_RESULT(ic)->isaddr = 0;
1955     ADDTOCHAIN(ic);
1956     return IC_RESULT(ic);
1957 }
1958 /*-----------------------------------------------------------------*/
1959 /* setOClass - sets the output class depending on the pointer type */
1960 /*-----------------------------------------------------------------*/
1961 void setOClass (link *ptr, link *spec)
1962 {
1963     switch (DCL_TYPE(ptr)) {
1964     case POINTER:
1965         SPEC_OCLS(spec) = data ;
1966         break ;
1967         
1968     case GPOINTER:
1969         SPEC_OCLS(spec) = generic;
1970         break;
1971         
1972     case FPOINTER:
1973         SPEC_OCLS(spec) = xdata ;
1974         break ;
1975         
1976     case CPOINTER:
1977         SPEC_OCLS(spec) = code ;
1978         break ;  
1979         
1980     case IPOINTER:
1981         SPEC_OCLS(spec) = idata;
1982         break;
1983
1984     case PPOINTER:
1985         SPEC_OCLS(spec) = xstack;
1986         break;
1987         
1988     }
1989 }
1990
1991 /*-----------------------------------------------------------------*/
1992 /* geniCodeDerefPtr - dereference pointer with '*'                 */
1993 /*-----------------------------------------------------------------*/
1994 operand *geniCodeDerefPtr (operand *op)
1995 {    
1996     link *rtype , *retype ;
1997     link *optype = operandType(op);  
1998
1999     /* if this is a pointer then generate the rvalue */
2000     if (IS_PTR(optype)) {
2001         if (IS_TRUE_SYMOP(op)) {
2002             op->isaddr = 1;
2003             op = geniCodeRValue(op,TRUE);
2004         }
2005         else    
2006             op = geniCodeRValue(op,TRUE);       
2007     }
2008     
2009     /* now get rid of the pointer part */
2010     if (lvaluereq && IS_ITEMP(op))
2011         retype = getSpec(rtype = copyLinkChain(optype)) ;
2012     else
2013         retype = getSpec(rtype = copyLinkChain(optype->next)) ;
2014     
2015     /* if this is a pointer then outputclass needs 2b updated */
2016     if (IS_PTR(optype)) 
2017         setOClass(optype,retype);    
2018         
2019     op = geniCodeRValue(op,TRUE);
2020     op->isGptr = IS_GENPTR(optype);
2021
2022     /* if the pointer was declared as a constant */
2023     /* then we cannot allow assignment to the derefed */
2024     if (IS_PTR_CONST(optype))
2025         SPEC_CONST(retype) = 1;
2026     
2027
2028     setOperandType(op,rtype);
2029     op->isaddr = (IS_PTR(rtype)    ||
2030                   IS_STRUCT(rtype) || 
2031                   IS_INT(rtype)    ||
2032                   IS_CHAR(rtype)   ||
2033                   IS_FLOAT(rtype) );
2034     
2035     return op;    
2036 }
2037
2038 /*-----------------------------------------------------------------*/
2039 /* geniCodeUnaryMinus - does a unary minus of the operand          */
2040 /*-----------------------------------------------------------------*/
2041 operand *geniCodeUnaryMinus (operand *op)
2042 {
2043     iCode *ic ;
2044     link *optype = operandType(op);
2045     
2046     if (IS_LITERAL(optype))
2047         return operandFromLit(- floatFromVal(op->operand.valOperand));
2048     
2049     ic = newiCode(UNARYMINUS,op,NULL);
2050     IC_RESULT(ic) = newiTempOperand(optype,0);
2051     ADDTOCHAIN(ic);
2052     return IC_RESULT(ic);
2053 }
2054
2055 /*-----------------------------------------------------------------*/
2056 /* geniCodeLeftShift - gen i code for left shift                   */
2057 /*-----------------------------------------------------------------*/
2058 operand *geniCodeLeftShift (operand *left, operand *right)
2059
2060     iCode *ic;
2061     link *ltype = operandType(left);
2062     
2063     ic = newiCode(LEFT_OP,left,right);
2064     IC_RESULT(ic) = newiTempOperand(ltype,0);
2065     ADDTOCHAIN(ic);
2066     return IC_RESULT(ic) ;  
2067 }
2068
2069 /*-----------------------------------------------------------------*/
2070 /* geniCodeRightShift - gen i code for right shift                 */
2071 /*-----------------------------------------------------------------*/
2072 operand *geniCodeRightShift (operand *left, operand *right)
2073
2074     iCode *ic;
2075     link *ltype = operandType(left);
2076     
2077     ic = newiCode(RIGHT_OP,left,right);
2078     IC_RESULT(ic) = newiTempOperand(ltype,0);
2079     ADDTOCHAIN(ic);
2080     return IC_RESULT(ic) ;  
2081 }
2082
2083 /*-----------------------------------------------------------------*/
2084 /* geniCodeLogic- logic code                                       */
2085 /*-----------------------------------------------------------------*/
2086 operand *geniCodeLogic (operand *left, operand *right, int op )
2087 {
2088     iCode *ic ;
2089     link *ctype; 
2090     link *rtype = operandType(right);
2091     link *ltype = operandType(left);
2092     
2093     /* left is integral type and right is literal then
2094        check if the literal value is within bounds */
2095     if (IS_INTEGRAL(ltype) && IS_LITERAL(rtype)) {
2096         int nbits = bitsForType(ltype);
2097         long v = operandLitValue(right);
2098
2099         if (v > ((long long) 1 << nbits) && v > 0)
2100             werror(W_CONST_RANGE," compare operation ");
2101     }
2102
2103     ctype = computeType(ltype,rtype);                         
2104     left = geniCodeCast(ctype,left,TRUE);
2105     right= geniCodeCast(ctype,right,TRUE);
2106
2107     ic = newiCode(op,left,right);
2108     IC_RESULT(ic) = newiTempOperand (newCharLink(),1);
2109
2110     /* if comparing anything greater than one byte
2111        and not a '==' || '!=' || '&&' || '||' (these
2112        will be inlined */
2113     if (getSize(ctype) > 1 && 
2114         op != EQ_OP        && 
2115         op != NE_OP        &&
2116         op != AND_OP       &&
2117         op != OR_OP        )
2118         ic->supportRtn = 1;
2119
2120     ADDTOCHAIN(ic);
2121     return IC_RESULT(ic);
2122 }
2123
2124 /*-----------------------------------------------------------------*/
2125 /* geniCodeUnary - for a a generic unary operation                 */
2126 /*-----------------------------------------------------------------*/
2127 operand *geniCodeUnary (operand *op, int oper )
2128 {
2129     iCode *ic = newiCode (oper,op,NULL);
2130     
2131     IC_RESULT(ic)= newiTempOperand(operandType(op),0);
2132     ADDTOCHAIN(ic);
2133     return IC_RESULT(ic) ;
2134 }
2135
2136 /*-----------------------------------------------------------------*/
2137 /* geniCodeConditional - geniCode for '?' ':' operation            */
2138 /*-----------------------------------------------------------------*/
2139 operand *geniCodeConditional (ast *tree)
2140 {
2141     iCode *ic ;
2142     symbol *falseLabel = newiTempLabel(NULL);
2143     symbol *exitLabel  = newiTempLabel(NULL);
2144     operand *cond = ast2iCode(tree->left);
2145     operand *true, *false , *result;
2146     
2147     ic = newiCodeCondition(geniCodeRValue(cond,FALSE),
2148                            NULL,falseLabel);
2149     ADDTOCHAIN(ic);
2150     
2151     true = ast2iCode(tree->right->left);
2152     
2153     /* move the value to a new Operand */
2154     result = newiTempOperand(operandType(true),0);
2155     geniCodeAssign(result,geniCodeRValue(true,FALSE),0);
2156     
2157     /* generate an unconditional goto */
2158     geniCodeGoto(exitLabel);
2159     
2160     /* now for the right side */
2161     geniCodeLabel(falseLabel);
2162     
2163     false = ast2iCode(tree->right->right);
2164     geniCodeAssign(result,geniCodeRValue(false,FALSE),0);
2165     
2166     /* create the exit label */
2167     geniCodeLabel(exitLabel);
2168     
2169     return result ;
2170 }
2171
2172 /*-----------------------------------------------------------------*/
2173 /* geniCodeAssign - generate code for assignment                   */
2174 /*-----------------------------------------------------------------*/
2175 operand *geniCodeAssign (operand *left, operand *right, int nosupdate)
2176 {
2177     iCode *ic ;
2178     link *ltype = operandType(left);
2179     link *rtype = operandType(right);
2180     
2181     if (!left->isaddr && !IS_ITEMP(left)) {
2182         werror(E_LVALUE_REQUIRED,"assignment");
2183         return left;
2184     }
2185         
2186     /* left is integral type and right is literal then
2187        check if the literal value is within bounds */
2188     if (IS_INTEGRAL(ltype) && IS_LITERAL(rtype)) {
2189         int nbits = bitsForType(ltype);
2190         long v = operandLitValue(right);
2191
2192         if (v > ((long long)1 << nbits) && v > 0)
2193             werror(W_CONST_RANGE," = operation");
2194     }
2195     /* if the left & right type don't exactly match */
2196     /* if pointer set then make sure the check is
2197        done with the type & not the pointer */
2198     /* then cast rights type to left */   
2199
2200     /* first check the type for pointer assignement */
2201     if (left->isaddr && IS_PTR(ltype) && IS_ITEMP(left) &&
2202         checkType(ltype,rtype)<0) {
2203         if (checkType(ltype->next,rtype) < 0)
2204             right = geniCodeCast(ltype->next,right,TRUE);
2205     } else
2206         if (checkType(ltype,rtype) < 0 )
2207             right = geniCodeCast(ltype,right,TRUE);
2208
2209     /* if left is a true symbol & ! volatile 
2210        create an assignment to temporary for
2211        the right & then assign this temporary
2212        to the symbol this is SSA . isn't it simple
2213        and folks have published mountains of paper on it */
2214     if (IS_TRUE_SYMOP(left) && 
2215         !isOperandVolatile(left,FALSE) &&
2216         isOperandGlobal(left)) {
2217         symbol *sym = NULL;
2218
2219         if (IS_TRUE_SYMOP(right))
2220             sym = OP_SYMBOL(right);
2221         ic = newiCode('=',NULL,right);
2222         IC_RESULT(ic) = right = newiTempOperand(ltype,0);       
2223         SPIL_LOC(right)  = sym ;
2224         ADDTOCHAIN(ic);
2225     }
2226     
2227     ic = newiCode('=',NULL,right);
2228     IC_RESULT(ic) = left;
2229     ADDTOCHAIN(ic);    
2230
2231     /* if left isgptr flag is set then support
2232        routine will be required */
2233     if (left->isGptr)
2234         ic->supportRtn = 1;
2235
2236     ic->nosupdate = nosupdate;
2237     return left;
2238 }
2239
2240 /*-----------------------------------------------------------------*/
2241 /* geniCodeSEParms - generate code for side effecting fcalls       */
2242 /*-----------------------------------------------------------------*/
2243 static void geniCodeSEParms (ast *parms)
2244 {
2245     if (!parms)
2246         return ;
2247
2248     if (parms->type == EX_OP && parms->opval.op == PARAM) {
2249         geniCodeSEParms (parms->left) ;
2250         geniCodeSEParms (parms->right);
2251         return ;
2252     }
2253
2254     /* hack don't like this but too lazy to think of
2255        something better */
2256     if (IS_ADDRESS_OF_OP(parms))
2257         parms->left->lvalue = 1;
2258     
2259     if (IS_CAST_OP(parms) && 
2260         IS_PTR(parms->ftype) && 
2261         IS_ADDRESS_OF_OP(parms->right))
2262         parms->right->left->lvalue = 1;
2263
2264     parms->opval.oprnd = 
2265         geniCodeRValue(ast2iCode (parms),TRUE);   
2266    
2267     parms->type = EX_OPERAND ;
2268 }
2269
2270 /*-----------------------------------------------------------------*/
2271 /* geniCodeParms - generates parameters                            */
2272 /*-----------------------------------------------------------------*/
2273 static void geniCodeParms ( ast *parms , int *stack, link *fetype)
2274 {
2275     iCode *ic ;
2276     operand *pval ; 
2277     
2278     if ( ! parms )
2279         return ;
2280     
2281     /* if this is a param node then do the left & right */
2282     if (parms->type == EX_OP && parms->opval.op == PARAM) {
2283         geniCodeParms (parms->left, stack,fetype) ;
2284         geniCodeParms (parms->right, stack,fetype);
2285         return ;
2286     }
2287     
2288     /* get the parameter value */
2289     if (parms->type == EX_OPERAND)
2290         pval = parms->opval.oprnd ;
2291     else {
2292         /* maybe this else should go away ?? */
2293         /* hack don't like this but too lazy to think of
2294            something better */
2295         if (IS_ADDRESS_OF_OP(parms))
2296             parms->left->lvalue = 1;
2297     
2298         if (IS_CAST_OP(parms) && 
2299             IS_PTR(parms->ftype) && 
2300             IS_ADDRESS_OF_OP(parms->right))
2301             parms->right->left->lvalue = 1;
2302
2303         pval = geniCodeRValue(ast2iCode (parms),FALSE); 
2304     }
2305
2306     /* if register parm then make it a send */
2307     if ((parms->argSym && IS_REGPARM(parms->argSym->etype)) ||
2308         IS_REGPARM(parms->etype)) {
2309         ic = newiCode(SEND,pval,NULL);
2310         ADDTOCHAIN(ic);
2311     } else {
2312         /* now decide whether to push or assign */
2313         if (!(options.stackAuto || IS_RENT(fetype))) { 
2314             
2315             /* assign */
2316             operand *top = operandFromSymbol(parms->argSym);
2317             geniCodeAssign(top,pval,1);
2318         }
2319         else { 
2320
2321             /* push */
2322             ic = newiCode(IPUSH,pval,NULL);
2323             ic->parmPush = 1;
2324             /* update the stack adjustment */
2325             *stack += getSize(operandType(pval));
2326             ADDTOCHAIN(ic);
2327         }
2328     }
2329     
2330 }
2331
2332 /*-----------------------------------------------------------------*/
2333 /* geniCodeCall - generates temp code for calling                  */
2334 /*-----------------------------------------------------------------*/
2335 operand *geniCodeCall (operand *left, ast *parms)
2336
2337     iCode *ic ;
2338     operand *result ;
2339     link *type, *etype;
2340     int stack = 0 ;
2341     
2342     /* take care of parameters with side-effecting
2343        function calls in them, this is required to take care 
2344        of overlaying function parameters */
2345     geniCodeSEParms ( parms );
2346
2347     /* first the parameters */
2348     geniCodeParms ( parms , &stack , getSpec(operandType(left)));
2349     
2350     /* now call : if symbol then pcall */
2351     if (IS_ITEMP(left)) 
2352         ic = newiCode(PCALL,left,NULL);
2353     else
2354         ic = newiCode(CALL,left,NULL);
2355     
2356     IC_ARGS(ic) = left->operand.symOperand->args ;
2357     type = copyLinkChain(operandType(left)->next);
2358     etype = getSpec(type);
2359     SPEC_EXTR(etype) = 0;
2360     IC_RESULT(ic) = result = newiTempOperand(type,1);
2361     
2362     ADDTOCHAIN(ic);
2363     
2364     /* stack adjustment after call */
2365     left->parmBytes = stack;
2366
2367     return result;
2368 }
2369
2370 /*-----------------------------------------------------------------*/
2371 /* geniCodeReceive - generate intermediate code for "receive"      */
2372 /*-----------------------------------------------------------------*/
2373 static void geniCodeReceive (value *args)
2374 {   
2375     /* for all arguments that are passed in registers */
2376     while (args) {
2377
2378         if (IS_REGPARM(args->etype)) {
2379             operand *opr = operandFromValue(args);
2380             operand *opl ;
2381             symbol *sym  = OP_SYMBOL(opr);
2382             iCode *ic ;
2383
2384             /* we will use it after all optimizations
2385                and before liveRange calculation */          
2386             if (!sym->addrtaken && 
2387                 !IS_VOLATILE(sym->etype) &&
2388                 !IN_FARSPACE(SPEC_OCLS(sym->etype))) {
2389                 opl = newiTempOperand(args->type,0);
2390                 sym->reqv = opl ;           
2391                 sym->reqv->key = sym->key ;
2392                 OP_SYMBOL(sym->reqv)->key = sym->key;
2393                 OP_SYMBOL(sym->reqv)->isreqv = 1;
2394                 OP_SYMBOL(sym->reqv)->islocal= 0;
2395                 SPIL_LOC(sym->reqv) =  sym;
2396             }
2397
2398             ic = newiCode(RECEIVE,NULL,NULL);
2399             currFunc->recvSize = getSize(sym->etype);
2400             IC_RESULT(ic) = opr;
2401             ADDTOCHAIN(ic);
2402         }
2403         
2404         args = args->next;
2405     }
2406 }
2407
2408 /*-----------------------------------------------------------------*/
2409 /* geniCodeFunctionBody - create the function body                 */
2410 /*-----------------------------------------------------------------*/
2411 void geniCodeFunctionBody (ast *tree)
2412 {
2413     iCode *ic ;
2414     operand *func ;
2415     link *fetype  ;
2416     int savelineno ;
2417     
2418     /* reset the auto generation */
2419     /* numbers */
2420     iTempNum = 0 ;
2421     iTempLblNum = 0;   
2422     operandKey = 0 ;
2423     iCodeKey = 0 ;
2424     func  = ast2iCode(tree->left);
2425     fetype = getSpec(operandType(func));
2426     
2427     savelineno = lineno;
2428     lineno = OP_SYMBOL(func)->lineDef;
2429     /* create an entry label */
2430     geniCodeLabel(entryLabel);    
2431     lineno = savelineno;
2432
2433     /* create a proc icode */
2434     ic = newiCode(FUNCTION,func,NULL);
2435     /* if the function has parmas   then */
2436     /* save the parameters information    */
2437     ic->argLabel.args = tree->values.args ;
2438     ic->lineno = OP_SYMBOL(func)->lineDef;
2439
2440     ADDTOCHAIN(ic);   
2441     
2442     /* for all parameters that are passed
2443        on registers add a "receive" */
2444     geniCodeReceive( tree->values.args );
2445
2446     /* generate code for the body */
2447     ast2iCode(tree->right);
2448     
2449     /* create a label for return */
2450     geniCodeLabel(returnLabel);
2451     
2452     /* now generate the end proc */
2453     ic = newiCode(ENDFUNCTION,func,NULL);
2454     ADDTOCHAIN(ic);
2455     return ;
2456 }
2457
2458 /*-----------------------------------------------------------------*/
2459 /* geniCodeReturn - gen icode for 'return' statement               */
2460 /*-----------------------------------------------------------------*/
2461 void geniCodeReturn (operand *op)
2462 {
2463     iCode *ic;
2464     
2465     /* if the operand is present force an rvalue */
2466     if (op) 
2467         op = geniCodeRValue(op,FALSE);    
2468     
2469     ic = newiCode(RETURN,op,NULL);
2470     ADDTOCHAIN(ic);
2471 }
2472
2473 /*-----------------------------------------------------------------*/
2474 /* geniCodeIfx - generates code for extended if statement          */
2475 /*-----------------------------------------------------------------*/
2476 void geniCodeIfx (ast *tree)
2477 {
2478     iCode *ic;
2479     operand *condition = ast2iCode(tree->left);
2480 /*     link *ctype = operandType(condition);     */
2481     link *cetype; 
2482     
2483     /* if condition is null then exit */
2484     if (!condition)
2485         goto exit ;
2486     else
2487         condition = geniCodeRValue(condition,FALSE);
2488     
2489     cetype = getSpec(operandType(condition));
2490     /* if the condition is a literal */
2491     if (IS_LITERAL(cetype)) {
2492         if (floatFromVal(condition->operand.valOperand)) {
2493             if (tree->trueLabel)
2494                 geniCodeGoto(tree->trueLabel);
2495             else
2496                 assert(1);
2497         }
2498         else {
2499             if (tree->falseLabel)
2500                 geniCodeGoto (tree->falseLabel);
2501             else
2502                 assert(1);
2503         }
2504         goto exit;
2505     }
2506     
2507     if ( tree->trueLabel ) {
2508         ic = newiCodeCondition(condition,
2509                                tree->trueLabel,
2510                                NULL );
2511         ADDTOCHAIN(ic);
2512         
2513         if ( tree->falseLabel) 
2514             geniCodeGoto(tree->falseLabel);     
2515     }
2516     else {
2517         ic = newiCodeCondition (condition,
2518                                 NULL,
2519                                 tree->falseLabel);
2520         ADDTOCHAIN(ic);
2521     }
2522     
2523  exit:
2524     ast2iCode(tree->right);
2525 }
2526
2527 /*-----------------------------------------------------------------*/
2528 /* geniCodeJumpTable - tries to create a jump table for switch     */
2529 /*-----------------------------------------------------------------*/
2530 int geniCodeJumpTable (operand *cond, value *caseVals, ast *tree)
2531 {
2532     int min = 0 ,max = 0, t, cnt = 0;
2533     value *vch;
2534     iCode *ic;
2535     operand *boundary;
2536     symbol *falseLabel;
2537     set *labels = NULL ;
2538
2539     if (!tree || !caseVals)
2540         return 0;
2541
2542     /* the criteria for creating a jump table is */
2543     /* all integer numbers between the maximum & minimum must */
2544     /* be present , the maximum value should not exceed 255 */
2545     min = max = (int)floatFromVal(vch = caseVals);
2546     sprintf(buffer,"_case_%d_%d",
2547             tree->values.switchVals.swNum,
2548             min);
2549     addSet(&labels,newiTempLabel(buffer));
2550
2551     /* if there is only one case value then no need */
2552     if (!(vch = vch->next ))
2553         return 0;
2554
2555     while (vch) {
2556         if (((t = (int)floatFromVal(vch)) - max) != 1)
2557             return 0;
2558         sprintf(buffer,"_case_%d_%d",
2559                 tree->values.switchVals.swNum,
2560                 t);
2561         addSet(&labels,newiTempLabel(buffer));
2562         max = t;
2563         cnt++ ;
2564         vch = vch->next ;
2565     }
2566     
2567     /* if the number of case statements <= 2 then */
2568     /* it is not economical to create the jump table */
2569     /* since two compares are needed for boundary conditions */
2570     if ((! optimize.noJTabBoundary  && cnt <= 2) || max > (255/3))
2571         return 0;
2572     
2573     if ( tree->values.switchVals.swDefault )
2574         sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2575     else
2576         sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum  );
2577     
2578     falseLabel = newiTempLabel (buffer);
2579
2580     /* so we can create a jumptable */
2581     /* first we rule out the boundary conditions */
2582     /* if only optimization says so */
2583     if ( ! optimize.noJTabBoundary ) {
2584         link *cetype = getSpec(operandType(cond));
2585         /* no need to check the lower bound if
2586            the condition is unsigned & minimum value is zero */
2587         if (!( min == 0  && SPEC_USIGN(cetype))) {
2588             boundary = geniCodeLogic (cond,operandFromLit(min),'<');
2589             ic = newiCodeCondition (boundary,falseLabel,NULL);
2590             ADDTOCHAIN(ic);
2591         }
2592
2593         /* now for upper bounds */
2594         boundary = geniCodeLogic(cond,operandFromLit(max),'>');
2595         ic = newiCodeCondition (boundary,falseLabel,NULL);
2596         ADDTOCHAIN(ic);
2597     }
2598
2599     /* if the min is not zero then we no make it zero */
2600     if (min) {
2601         cond = geniCodeSubtract(cond,operandFromLit(min));
2602         setOperandType(cond,ucharType);
2603     }
2604
2605     /* now create the jumptable */
2606     ic = newiCode(JUMPTABLE,NULL,NULL);
2607     IC_JTCOND(ic) = cond;
2608     IC_JTLABELS(ic) = labels;
2609     ADDTOCHAIN(ic);
2610     return 1;       
2611 }
2612
2613 /*-----------------------------------------------------------------*/
2614 /* geniCodeSwitch - changes a switch to a if statement             */
2615 /*-----------------------------------------------------------------*/
2616 void geniCodeSwitch (ast *tree)
2617 {
2618     iCode *ic ;
2619     operand *cond = geniCodeRValue(ast2iCode (tree->left),FALSE);
2620     value *caseVals = tree->values.switchVals.swVals ;
2621     symbol *trueLabel , *falseLabel;
2622     
2623     /* if we can make this a jump table */
2624     if ( geniCodeJumpTable (cond,caseVals,tree) )
2625         goto jumpTable ; /* no need for the comparison */
2626
2627     /* for the cases defined do */
2628     while (caseVals) {
2629         
2630         operand *compare = geniCodeLogic (cond,
2631                                           operandFromValue(caseVals),
2632                                           EQ_OP);
2633         
2634         sprintf(buffer,"_case_%d_%d",
2635                 tree->values.switchVals.swNum,
2636                 (int) floatFromVal(caseVals));
2637         trueLabel = newiTempLabel(buffer);
2638         
2639         ic = newiCodeCondition(compare,trueLabel,NULL);
2640         ADDTOCHAIN(ic);
2641         caseVals = caseVals->next;
2642     }
2643
2644
2645     
2646     /* if default is present then goto break else break */
2647     if ( tree->values.switchVals.swDefault )
2648         sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2649     else
2650         sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum  );
2651     
2652     falseLabel = newiTempLabel (buffer);
2653     geniCodeGoto(falseLabel);
2654  
2655  jumpTable:   
2656     ast2iCode(tree->right);
2657
2658
2659 /*-----------------------------------------------------------------*/
2660 /* geniCodeInline - intermediate code for inline assembler         */
2661 /*-----------------------------------------------------------------*/
2662 static void geniCodeInline (ast *tree)
2663 {
2664     iCode *ic;
2665
2666     ic = newiCode(INLINEASM,NULL,NULL);
2667     IC_INLINE(ic) = tree->values.inlineasm;
2668     ADDTOCHAIN(ic);
2669 }
2670
2671 /*-----------------------------------------------------------------*/
2672 /* ast2iCode - creates an icodeList from an ast                    */
2673 /*-----------------------------------------------------------------*/
2674 operand *ast2iCode (ast *tree)
2675 {
2676     operand *left = NULL;
2677     operand *right= NULL;
2678     
2679     if (!tree)
2680         return NULL ;
2681     
2682     /* set the global variables for filename & line number */
2683     if ( tree->filename )
2684         filename =  tree->filename ;
2685     if ( tree->lineno)
2686         lineno   = tree->lineno ;
2687     if (tree->block)
2688         block = tree->block ;
2689     if (tree->level)
2690         scopeLevel = tree->level;
2691     
2692     if (tree->type == EX_VALUE )
2693         return operandFromValue(tree->opval.val);
2694     
2695     if (tree->type == EX_LINK )
2696         return operandFromLink (tree->opval.lnk);
2697     
2698     /* if we find a nullop */
2699     if (tree->type == EX_OP && 
2700         ( tree->opval.op == NULLOP || 
2701           tree->opval.op == BLOCK )) {
2702         ast2iCode (tree->left);
2703         ast2iCode (tree->right);
2704         return NULL ;
2705     }
2706     
2707     /* special cases for not evaluating */
2708     if ( tree->opval.op != ':'   && 
2709          tree->opval.op != '?'   &&
2710          tree->opval.op != CALL  && 
2711          tree->opval.op != IFX   &&
2712          tree->opval.op != LABEL &&
2713          tree->opval.op != GOTO  &&     
2714          tree->opval.op != SWITCH &&
2715          tree->opval.op != FUNCTION &&
2716          tree->opval.op != INLINEASM ) {
2717         if (IS_ASSIGN_OP(tree->opval.op) || IS_DEREF_OP(tree)) {
2718             lvaluereq++;
2719             left = operandFromAst(tree->left);
2720             lvaluereq--;
2721         } else {
2722             left =  operandFromAst(tree->left);
2723         }
2724         right= operandFromAst(tree->right);
2725     }
2726     
2727     /* now depending on the type of operand */
2728     /* this will be a biggy                 */
2729     switch (tree->opval.op) {
2730         
2731     case '[' :    /* array operation */
2732         left= geniCodeRValue (left,FALSE);
2733         right=geniCodeRValue (right,TRUE);                 
2734         
2735         return geniCodeArray (left,right);
2736         
2737     case '.' :   /* structure dereference */
2738         if (IS_PTR(operandType(left)))
2739             left = geniCodeRValue(left,TRUE);
2740         else
2741             left = geniCodeRValue(left,FALSE);            
2742         
2743         return geniCodeStruct (left,right,tree->lvalue);
2744         
2745     case PTR_OP: /* structure pointer dereference */
2746         {
2747             link *pType;
2748             pType = operandType(left);
2749             left = geniCodeRValue(left,TRUE);
2750             
2751             setOClass (pType,getSpec(operandType(left)));
2752         }              
2753         
2754         return geniCodeStruct (left, right,tree->lvalue);
2755         
2756     case INC_OP: /* increment operator */
2757         if ( left )
2758             return geniCodePostInc (left);
2759         else
2760             return geniCodePreInc (right);
2761         
2762     case DEC_OP: /* decrement operator */
2763         if ( left )
2764             return geniCodePostDec (left);
2765         else
2766             return geniCodePreDec (right);
2767         
2768     case '&' : /* bitwise and or address of operator */
2769         if ( right ) { /* this is a bitwise operator   */
2770             left= geniCodeRValue(left,FALSE);
2771             right= geniCodeRValue(right,FALSE);     
2772             return geniCodeBitwise (left,right,BITWISEAND,tree->ftype);
2773         } else
2774             return geniCodeAddressOf (left);
2775         
2776     case '|': /* bitwise or & xor */
2777     case '^':
2778         return geniCodeBitwise (geniCodeRValue(left,FALSE),
2779                                 geniCodeRValue(right,FALSE),
2780                                 tree->opval.op,
2781                                 tree->ftype);
2782         
2783     case '/':
2784         return geniCodeDivision (geniCodeRValue(left,FALSE),
2785                                  geniCodeRValue(right,FALSE));
2786         
2787     case '%' :
2788         return geniCodeModulus (geniCodeRValue(left,FALSE),
2789                                 geniCodeRValue(right,FALSE));
2790     case '*':
2791         if ( right ) 
2792             return geniCodeMultiply (geniCodeRValue(left,FALSE),
2793                                      geniCodeRValue(right,FALSE));
2794         else        
2795             return geniCodeDerefPtr (geniCodeRValue(left,FALSE));
2796         
2797     case '-' :
2798         if ( right ) 
2799             return geniCodeSubtract (geniCodeRValue(left,FALSE),
2800                                      geniCodeRValue(right,FALSE));
2801         else
2802             return geniCodeUnaryMinus (geniCodeRValue(left,FALSE));
2803         
2804     case '+' :
2805         if ( right ) 
2806             return geniCodeAdd (geniCodeRValue(left,FALSE),
2807                                 geniCodeRValue(right,FALSE));
2808         else
2809             return geniCodeRValue(left,FALSE) ; /* unary '+' has no meaning */
2810         
2811     case LEFT_OP:
2812         return geniCodeLeftShift (geniCodeRValue(left,FALSE),
2813                                   geniCodeRValue(right,FALSE));
2814         
2815     case RIGHT_OP:
2816         return geniCodeRightShift (geniCodeRValue(left,FALSE),
2817                                    geniCodeRValue(right,FALSE));
2818     case CAST:
2819         return geniCodeCast (operandType(left),
2820                              geniCodeRValue(right,FALSE),FALSE);
2821         
2822     case '~' :
2823     case '!' :
2824     case RRC:
2825     case RLC:   
2826         return geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
2827         
2828     case GETHBIT:
2829         {
2830             operand *op = geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
2831             setOperandType(op,ucharType);
2832             return op;
2833         }
2834     case '>' :
2835     case '<' :
2836     case LE_OP:
2837     case GE_OP:
2838     case EQ_OP:
2839     case NE_OP:
2840     case AND_OP:
2841     case OR_OP:
2842         return geniCodeLogic (geniCodeRValue(left,FALSE),
2843                               geniCodeRValue(right,FALSE),
2844                               tree->opval.op);
2845     case '?' : 
2846         return geniCodeConditional (tree); 
2847         
2848     case SIZEOF:
2849         return operandFromLit(getSize(tree->right->ftype));
2850         
2851     case '='        :
2852         {
2853             link *rtype = operandType(right);
2854             link *ltype = operandType(left);
2855             if (IS_PTR(rtype) && IS_ITEMP(right) 
2856                 && right->isaddr && checkType(rtype->next,ltype)==1)
2857                 right =  geniCodeRValue(right,TRUE);
2858             else
2859                 right = geniCodeRValue(right,FALSE);
2860
2861             geniCodeAssign (left,right,0);
2862             return right ;
2863         }              
2864     case MUL_ASSIGN:
2865         return 
2866             geniCodeAssign(left,
2867                            geniCodeMultiply(geniCodeRValue (operandFromOperand(left),
2868                                                             FALSE),
2869                                             geniCodeRValue(right,FALSE)),0);
2870                                                 
2871     case DIV_ASSIGN:
2872         return 
2873             geniCodeAssign(left,
2874                            geniCodeDivision(geniCodeRValue(operandFromOperand(left),
2875                                                            FALSE),
2876                                             geniCodeRValue(right,FALSE)),0);
2877     case MOD_ASSIGN:
2878         return 
2879             geniCodeAssign(left,
2880                            geniCodeModulus(geniCodeRValue(operandFromOperand(left),
2881                                                           FALSE),
2882                                            geniCodeRValue(right,FALSE)),0);
2883     case ADD_ASSIGN: 
2884         {
2885             link *rtype = operandType(right);
2886             link *ltype = operandType(left);
2887             if (IS_PTR(rtype) && IS_ITEMP(right) 
2888                 && right->isaddr && checkType(rtype->next,ltype)==1)
2889                 right =  geniCodeRValue(right,TRUE);
2890             else
2891                 right = geniCodeRValue(right,FALSE);
2892
2893            
2894             return geniCodeAssign(left,
2895                                   geniCodeAdd (geniCodeRValue(operandFromOperand(left),
2896                                                               FALSE),
2897                                                right),0);
2898         }
2899     case SUB_ASSIGN:
2900         {
2901             link *rtype = operandType(right);
2902             link *ltype = operandType(left);
2903             if (IS_PTR(rtype) && IS_ITEMP(right) 
2904                 && right->isaddr && checkType(rtype->next,ltype)==1) {
2905                 right =  geniCodeRValue(right,TRUE);
2906             }
2907             else {
2908                 right = geniCodeRValue(right,FALSE);
2909             }
2910             return 
2911                 geniCodeAssign (left,
2912                                 geniCodeSubtract(geniCodeRValue(operandFromOperand(left),
2913                                                                 FALSE),
2914                                                  right),0);
2915         }
2916     case LEFT_ASSIGN:
2917         return 
2918             geniCodeAssign (left,
2919                             geniCodeLeftShift(geniCodeRValue(operandFromOperand(left)
2920                                                              ,FALSE),
2921                                               geniCodeRValue(right,FALSE)),0);
2922     case RIGHT_ASSIGN:
2923         return 
2924             geniCodeAssign(left,
2925                            geniCodeRightShift(geniCodeRValue(operandFromOperand(left)
2926                                                              ,FALSE),
2927                                               geniCodeRValue(right,FALSE)),0);
2928     case AND_ASSIGN:
2929         return 
2930             geniCodeAssign (left,
2931                             geniCodeBitwise(geniCodeRValue(operandFromOperand(left),
2932                                                            FALSE),
2933                                             geniCodeRValue(right,FALSE),
2934                                             BITWISEAND,
2935                                             operandType(left)),0);
2936     case XOR_ASSIGN:
2937         return 
2938             geniCodeAssign (left,
2939                             geniCodeBitwise (geniCodeRValue(operandFromOperand(left),
2940                                                             FALSE),
2941                                              geniCodeRValue(right,FALSE),
2942                                              '^',
2943                                              operandType(left)),0);
2944     case OR_ASSIGN:
2945         return 
2946             geniCodeAssign (left,
2947                             geniCodeBitwise (geniCodeRValue(operandFromOperand(left)
2948                                                             ,FALSE),
2949                                              geniCodeRValue(right,FALSE),
2950                                              '|',
2951                                              operandType(left)),0);
2952     case ',' :
2953         return geniCodeRValue(right,FALSE);
2954         
2955     case CALL:
2956         return geniCodeCall (ast2iCode(tree->left),
2957                              tree->right);
2958     case LABEL:
2959         geniCodeLabel(ast2iCode(tree->left)->operand.symOperand);
2960         return ast2iCode (tree->right);
2961         
2962     case GOTO:
2963         geniCodeGoto (ast2iCode(tree->left)->operand.symOperand);
2964         return ast2iCode (tree->right);
2965         
2966     case FUNCTION:
2967         geniCodeFunctionBody ( tree );
2968         return NULL ;
2969         
2970     case RETURN:
2971         geniCodeReturn (right);
2972         return NULL ;
2973         
2974     case IFX:
2975         geniCodeIfx (tree);
2976         return NULL ;
2977         
2978     case SWITCH:
2979         geniCodeSwitch (tree);
2980         return NULL;
2981
2982     case INLINEASM:
2983         geniCodeInline (tree);
2984         return NULL ;
2985     }
2986     
2987     return NULL;
2988 }
2989
2990 /*-----------------------------------------------------------------*/
2991 /* reverseICChain - gets from the list and creates a linkedlist    */
2992 /*-----------------------------------------------------------------*/
2993 iCode *reverseiCChain ()
2994 {
2995     iCode *loop = NULL ;
2996     iCode *prev = NULL ;
2997     
2998     while ((loop = getSet(&iCodeChain))) {
2999         loop->next = prev ;
3000         if ( prev )
3001             prev->prev = loop; 
3002         prev = loop ;
3003     }
3004     
3005     return prev;
3006 }
3007
3008
3009 /*-----------------------------------------------------------------*/
3010 /* iCodeFromAst - given an ast will convert it to iCode            */
3011 /*-----------------------------------------------------------------*/
3012 iCode *iCodeFromAst ( ast *tree )
3013 {
3014     returnLabel = newiTempLabel("_return");
3015     entryLabel  = newiTempLabel("_entry") ;
3016     ast2iCode (tree);
3017     return reverseiCChain ();
3018 }
3019