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