1) fixed one more array deref problem
[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     }
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 /* isParamterToCall - will return 1 if op is a parameter to args   */
661 /*-----------------------------------------------------------------*/
662 int isParameterToCall (value *args, operand *op)
663 {
664     value *tval = args ;
665
666     while (tval) {
667         if (tval->sym && 
668             isSymbolEqual(op->operand.symOperand,tval->sym))
669             return 1;
670         tval = tval->next ;
671     }
672     return 0;
673 }
674
675 /*-----------------------------------------------------------------*/
676 /* isOperandGlobal   - return 1 if operand is a global variable    */
677 /*-----------------------------------------------------------------*/
678 int isOperandGlobal ( operand *op )
679 {
680     if (!op)
681         return 0;
682
683     if (IS_ITEMP(op))
684         return 0;
685
686     if (op->type == SYMBOL &&       
687          (op->operand.symOperand->level == 0 ||  
688          IS_STATIC(op->operand.symOperand->etype) ||
689          IS_EXTERN(op->operand.symOperand->etype))
690           )
691         return 1;
692     
693     return 0;
694 }
695
696 /*-----------------------------------------------------------------*/
697 /* isOperandVolatile - return 1 if the operand is volatile         */
698 /*-----------------------------------------------------------------*/
699 int isOperandVolatile ( operand *op , bool chkTemp)
700 {
701     link *optype ;
702     link *opetype ;
703
704     if (IS_ITEMP(op) && !chkTemp)
705         return 0;
706
707     opetype = getSpec(optype = operandType(op));
708     
709     if (IS_PTR(optype) && DCL_PTR_VOLATILE(optype))
710         return 1;
711
712     if (IS_VOLATILE(opetype))
713         return 1;
714     return 0;
715 }
716
717 /*-----------------------------------------------------------------*/
718 /* isOperandLiteral - returns 1 if an operand contains a literal   */
719 /*-----------------------------------------------------------------*/
720 int isOperandLiteral ( operand *op )
721 {
722     link *opetype ;
723     
724     if (!op)
725         return 0;
726     
727     opetype = getSpec (operandType(op));
728
729     if (IS_LITERAL(opetype))
730         return 1;
731
732     return 0;
733 }
734 /*-----------------------------------------------------------------*/
735 /* isOperandInFarSpace - will return true if operand is in farSpace*/
736 /*-----------------------------------------------------------------*/
737 bool isOperandInFarSpace (operand *op)
738 {
739     link *etype;
740
741     if (!op)
742         return FALSE;
743
744     if (!IS_SYMOP(op))
745         return FALSE ;
746
747     if (!IS_TRUE_SYMOP(op)) {
748         if (SPIL_LOC(op))
749             etype = SPIL_LOC(op)->etype;
750         else            
751             return FALSE;
752     }
753
754     etype = getSpec(operandType(op));
755     return (IN_FARSPACE(SPEC_OCLS(etype)) ? TRUE : FALSE);
756 }
757
758 /*-----------------------------------------------------------------*/
759 /* operandLitValue - literal value of an operand                   */
760 /*-----------------------------------------------------------------*/
761 double operandLitValue ( operand *op )
762 {
763     assert(isOperandLiteral(op));
764     
765     return floatFromVal(op->operand.valOperand);    
766 }
767
768 /*-----------------------------------------------------------------*/
769 /* operandOperation - perforoms operations on operands             */
770 /*-----------------------------------------------------------------*/
771 operand *operandOperation (operand *left,operand *right,
772                            int op, link *type)
773 {
774     operand *retval = (operand *)0;
775         
776     assert(isOperandLiteral(left));
777     if (right) 
778         assert(isOperandLiteral(right));
779     
780     switch (op) {
781     case '+' :
782         retval =  operandFromValue (valCastLiteral(type,
783                                                    operandLitValue(left) + 
784                                                    operandLitValue(right)));
785         break ;
786     case '-' :
787         retval = operandFromValue(valCastLiteral(type,
788                                                  operandLitValue(left) -
789                                                  operandLitValue(right)));
790         break;
791     case '*':
792         retval = operandFromValue(valCastLiteral(type,
793                                                  operandLitValue(left) *
794                                                  operandLitValue(right)));
795         break;
796     case '/':
797         if ((unsigned long) operandLitValue(right) == 0){           
798             werror(E_DIVIDE_BY_ZERO);
799             retval = right;
800             
801         }
802         else
803             retval = operandFromValue (valCastLiteral(type,
804                                                       operandLitValue(left) /
805                                                       operandLitValue(right)));
806         break;
807     case '%':      
808         if ((unsigned long) operandLitValue(right) == 0){           
809             werror(E_DIVIDE_BY_ZERO);
810             retval = right;         
811         }
812         else
813             retval = operandFromLit ((unsigned long) operandLitValue(left) %
814                                      (unsigned long) operandLitValue(right));
815         break;
816     case LEFT_OP :
817         retval = operandFromLit ((unsigned long) operandLitValue(left) <<
818                                  (unsigned long) operandLitValue(right));
819         break;
820     case RIGHT_OP :
821         retval = operandFromLit ((unsigned long) operandLitValue(left) >>
822                                  (unsigned long) operandLitValue(right));
823         break;
824     case EQ_OP :
825         retval = operandFromLit (operandLitValue(left) ==
826                                  operandLitValue(right));
827         break;
828     case '<' :
829         retval = operandFromLit (operandLitValue(left) <
830                                  operandLitValue(right));
831         break;
832     case LE_OP :
833         retval = operandFromLit (operandLitValue(left) <=
834                                  operandLitValue(right));
835         break;
836     case NE_OP :
837         retval = operandFromLit (operandLitValue(left) !=
838                                  operandLitValue(right));
839         break;
840     case '>' :
841         retval = operandFromLit (operandLitValue(left) >
842                                  operandLitValue(right));
843         break;
844     case GE_OP :
845         retval = operandFromLit (operandLitValue(left) >=
846                                  operandLitValue(right));
847         break;
848     case BITWISEAND :
849         retval = operandFromLit ((unsigned long) operandLitValue(left) &
850                                  (unsigned long) operandLitValue(right));
851         break;
852     case '|' :
853         retval = operandFromLit ((unsigned long) operandLitValue(left) |
854                                  (unsigned long) operandLitValue(right));       
855         break;
856     case '^' :
857         retval = operandFromLit ((unsigned long) operandLitValue(left) ^
858                                  (unsigned long) operandLitValue(right));
859         break;
860     case AND_OP:
861         retval = operandFromLit (operandLitValue(left) &&
862                                  operandLitValue(right));
863         break;
864     case OR_OP:
865         retval = operandFromLit (operandLitValue(left) ||
866                                  operandLitValue(right));
867         break;
868     case RRC:
869         {
870             long i = operandLitValue(left);
871             
872             retval = operandFromLit ((i >> (getSize(operandType(left))*8 - 1)) |
873                                      (i << 1));
874         }
875         break;
876     case RLC:
877         {
878             long i = operandLitValue(left);
879             
880             retval = operandFromLit ((i << (getSize(operandType(left))*8 - 1)) |
881                                      (i >> 1));
882         }
883         break;
884         
885     case UNARYMINUS:
886         retval = operandFromLit(-1 * operandLitValue(left));
887         break;
888         
889     case '~':
890         retval = operandFromLit(~ ((long) operandLitValue(left)));
891         break;
892
893     case '!':
894         retval = operandFromLit(! operandLitValue(left));
895         break;
896
897     default :
898         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
899                " operandOperation invalid operator ");
900         assert (0);
901     }
902     
903     return retval;
904 }
905
906
907 /*-----------------------------------------------------------------*/
908 /* isOperandEqual - compares two operand & return 1 if they r =    */
909 /*-----------------------------------------------------------------*/
910 int isOperandEqual (operand *left, operand *right)
911 {
912     /* if the pointers are equal then they are equal */
913     if ( left == right )
914         return 1;
915     
916     /* if either of them null then false */
917     if ( !left || !right)
918         return 0;
919
920     if (left->type != right->type)
921         return 0;
922
923     if (IS_SYMOP(left) && IS_SYMOP(right))
924         return left->key == right->key ;
925
926     /* if types are the same */
927     switch (left->type) {
928     case SYMBOL :
929         return isSymbolEqual(left->operand.symOperand,
930                              right->operand.symOperand);
931     case VALUE :
932         return (floatFromVal(left->operand.valOperand) ==
933                 floatFromVal(right->operand.valOperand));
934     case TYPE :
935         if (checkType(left->operand.typeOperand,
936                       right->operand.typeOperand) == 1)
937             return 1;      
938     }
939
940     return 0;
941 }
942
943 /*-----------------------------------------------------------------*/
944 /* isiCodeEqual - comapres two iCodes are returns true if yes      */
945 /*-----------------------------------------------------------------*/
946 int isiCodeEqual (iCode *left, iCode *right)
947 {
948     /* if the same pointer */
949     if (left == right)
950         return 1;
951     
952     /* if either of them null */
953     if (!left || !right)
954         return 0;
955
956     /* if operand are the same */
957     if ( left->op == right->op ) {
958         
959         /* compare all the elements depending on type */
960         if (left->op != IFX ) {
961             if (!isOperandEqual(IC_LEFT(left),IC_LEFT(right)))
962                 return 0;
963             if (!isOperandEqual(IC_RIGHT(left),IC_RIGHT(right)))
964                 return 0;
965
966         } else {
967             if (!isOperandEqual(IC_COND(left),IC_COND(right)))
968                 return 0;
969             if (!isSymbolEqual (IC_TRUE(left),IC_TRUE(right)))
970                 return 0;
971             if (!isSymbolEqual(IC_FALSE(left),IC_FALSE(right)))
972                 return 0;
973         }
974         return 1;
975     }
976     return 0;
977 }
978
979 /*-----------------------------------------------------------------*/
980 /* newiTempFromOp - create a temp Operand with same attributes     */
981 /*-----------------------------------------------------------------*/
982 operand *newiTempFromOp (operand *op)
983 {
984     operand *nop;
985
986     if (!op)
987         return NULL;
988     
989     if (!IS_ITEMP(op))
990         return op;
991
992     nop = newiTempOperand(operandType(op),TRUE);
993     nop->isaddr = op->isaddr ;
994     nop->isvolatile = op->isvolatile ;
995     nop->isGlobal = op->isGlobal ;
996     nop->isLiteral= op->isLiteral ;
997     nop->noSpilLoc= op->noSpilLoc;
998     nop->usesDefs = op->usesDefs;
999     nop->isParm = op->isParm;
1000     nop->parmBytes = op->parmBytes;
1001     return nop;
1002 }
1003
1004 /*-----------------------------------------------------------------*/
1005 /* operand from operand - creates an operand holder for the type   */
1006 /*-----------------------------------------------------------------*/
1007 operand *operandFromOperand (operand *op)
1008 {
1009     operand *nop ;
1010     
1011     if (!op)
1012         return NULL;
1013     nop = newOperand();
1014     nop->type = op->type;
1015     nop->isaddr = op->isaddr ;
1016     nop->key = op->key ;
1017     nop->isvolatile = op->isvolatile ;
1018     nop->isGlobal = op->isGlobal ;
1019     nop->isLiteral= op->isLiteral ;
1020     nop->noSpilLoc= op->noSpilLoc;
1021     nop->usesDefs = op->usesDefs;
1022     nop->isParm = op->isParm;
1023     nop->parmBytes = op->parmBytes;
1024
1025     switch (nop->type) {
1026     case SYMBOL :
1027         nop->operand.symOperand = op->operand.symOperand ;      
1028         break;
1029     case VALUE :
1030         nop->operand.valOperand = op->operand.valOperand;
1031         break;
1032     case TYPE :
1033         nop->operand.typeOperand = op->operand.typeOperand ;
1034         break ;
1035     }   
1036
1037     return nop;
1038 }
1039
1040 /*-----------------------------------------------------------------*/
1041 /* opFromOpWithDU - makes a copy of the operand and DU chains      */
1042 /*-----------------------------------------------------------------*/
1043 operand *opFromOpWithDU (operand *op, bitVect *defs, bitVect *uses)
1044 {
1045     operand *nop = operandFromOperand(op);
1046
1047     if (nop->type == SYMBOL) {
1048         OP_SYMBOL(nop)->defs = bitVectCopy(defs);
1049         OP_SYMBOL(nop)->uses = bitVectCopy(uses);
1050     }
1051
1052     return nop;
1053 }
1054
1055 /*-----------------------------------------------------------------*/
1056 /* operandFromSymbol - creates an operand from a symbol            */
1057 /*-----------------------------------------------------------------*/
1058 operand *operandFromSymbol (symbol *sym)
1059 {
1060     operand *op ;
1061     iCode *ic ;
1062     
1063     /* if the symbol's type is a literal */
1064     /* then it is an enumerator type     */
1065     if (IS_LITERAL(sym->etype) && SPEC_ENUM(sym->etype)) 
1066         return operandFromValue (valFromType(sym->etype));
1067
1068     if (!sym->key)
1069         sym->key = ++operandKey ;
1070
1071     /* if this an implicit variable, means struct/union */
1072     /* member so just return it                         */
1073     if (sym->implicit || IS_FUNC(sym->type)) {
1074         op = newOperand();
1075         op->type = SYMBOL ;
1076         op->operand.symOperand = sym;
1077         op->key = sym->key ;
1078         op->isvolatile = isOperandVolatile(op,TRUE);
1079         op->isGlobal   = isOperandGlobal(op);
1080         op->parmBytes  = sym->argStack;
1081         return op;
1082     }
1083     
1084     /* under the following conditions create a
1085        register equivalent for a local symbol */
1086     if (!IS_AGGREGATE(sym->type) &&     /* not an aggregate */
1087         !IS_FUNC(sym->type)      &&     /* not a function   */
1088         !sym->_isparm            &&     /* not a parameter  */
1089         sym->level               &&     /* is a local variable */
1090         !sym->addrtaken          &&     /* whose address has not been taken */
1091         !sym->reqv               &&     /* does not already have a register euivalence */
1092         !IS_VOLATILE(sym->etype) &&     /* not declared as volatile */
1093         !IS_STATIC(sym->etype)   &&     /* and not declared static  */
1094         !sym->islbl              &&     /* not a label */
1095         !IN_FARSPACE(SPEC_OCLS(sym->etype)) && /* not in far space */
1096         !IS_BITVAR(sym->etype)          /* not a bit variable */
1097         ) {
1098         
1099         /* we will use it after all optimizations
1100            and before liveRange calculation */
1101         sym->reqv = newiTempOperand(sym->type,0);       
1102         sym->reqv->key = sym->key ;
1103         OP_SYMBOL(sym->reqv)->key = sym->key;
1104         OP_SYMBOL(sym->reqv)->isreqv = 1;
1105         OP_SYMBOL(sym->reqv)->islocal = 1;
1106         SPIL_LOC(sym->reqv) = sym;
1107     }
1108
1109     if (!IS_AGGREGATE(sym->type)) {
1110         op = newOperand();
1111         op->type = SYMBOL;
1112         op->operand.symOperand = sym;
1113         op->isaddr = 1;
1114         op->key = sym->key;
1115         op->isvolatile = isOperandVolatile(op,TRUE);
1116         op->isGlobal   = isOperandGlobal(op);
1117         op->isPtr = IS_PTR(operandType(op));
1118         op->isParm = sym->_isparm ;
1119         return op;
1120     }
1121     
1122     /* create :-                     */
1123     /*    itemp = &[_symbol]         */
1124     
1125     ic = newiCode(ADDRESS_OF,newOperand(),NULL);
1126     IC_LEFT(ic)->type = SYMBOL ;
1127     IC_LEFT(ic)->operand.symOperand = sym ;
1128     IC_LEFT(ic)->key = sym->key;    
1129     (IC_LEFT(ic))->isvolatile = isOperandVolatile(IC_LEFT(ic),TRUE);
1130     (IC_LEFT(ic))->isGlobal   = isOperandGlobal(IC_LEFT(ic));
1131     IC_LEFT(ic)->isPtr = IS_PTR(operandType(IC_LEFT(ic)));
1132
1133     /* create result */
1134     IC_RESULT(ic) = newiTempOperand(sym->type,0);
1135     if (IS_ARRAY(sym->type)) {
1136         IC_RESULT(ic) = geniCodeArray2Ptr (IC_RESULT(ic));
1137         IC_RESULT(ic)->isaddr = 0;
1138     } else
1139         IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(sym->type));
1140
1141     IC_RESULT(ic)->operand.symOperand->args = sym->args;
1142
1143     ADDTOCHAIN(ic);
1144     
1145     return IC_RESULT(ic) ;
1146 }
1147
1148 /*-----------------------------------------------------------------*/
1149 /* operandFromValue - creates an operand from value                */
1150 /*-----------------------------------------------------------------*/
1151 operand *operandFromValue (value *val)
1152 {
1153     operand *op ;
1154     
1155     /* if this is a symbol then do the symbol thing */
1156     if (val->sym)
1157         return operandFromSymbol (val->sym);
1158     
1159     /* this is not a symbol */
1160     op = newOperand();
1161     op->type = VALUE ;
1162     op->operand.valOperand = val ;
1163     op->isLiteral = isOperandLiteral(op);
1164     return op;
1165 }
1166
1167 /*-----------------------------------------------------------------*/
1168 /* operandFromLink - operand from typeChain                        */
1169 /*-----------------------------------------------------------------*/
1170 operand *operandFromLink (link *type)
1171 {
1172     operand *op ;
1173     
1174     /* operand from link */
1175     if ( ! type )
1176         return NULL ;
1177     
1178     op = newOperand();
1179     op->type = TYPE ;
1180     op->operand.typeOperand = copyLinkChain(type);
1181     return op;
1182 }
1183
1184 /*-----------------------------------------------------------------*/
1185 /* operandFromLit - makes an operand from a literal value          */
1186 /*-----------------------------------------------------------------*/
1187 operand *operandFromLit ( float i)
1188 {
1189     return operandFromValue (valueFromLit (i));
1190 }
1191
1192 /*-----------------------------------------------------------------*/
1193 /* operandFromAst - creates an operand from an ast                 */
1194 /*-----------------------------------------------------------------*/
1195 operand *operandFromAst ( ast *tree )
1196 {
1197     
1198     if (! tree )
1199         return NULL ;
1200     
1201     /* depending on type do */
1202     switch (tree->type ) {      
1203     case EX_OP : 
1204         return ast2iCode (tree) ;    
1205         break ;
1206         
1207     case EX_VALUE :
1208         return operandFromValue(tree->opval.val) ;
1209         break ;
1210         
1211     case EX_LINK :
1212         return operandFromLink (tree->opval.lnk) ; 
1213     }
1214     
1215     assert(0);
1216     /*  Just to keep the comiler happy */
1217     return (operand *)0;
1218 }
1219
1220 /*-----------------------------------------------------------------*/
1221 /* setOperandType - sets the operand's type to the given type      */
1222 /*-----------------------------------------------------------------*/
1223 void setOperandType (operand *op, link *type)
1224 {
1225     /* depending on the type of operand */
1226     switch (op->type) {
1227         
1228     case VALUE :
1229         op->operand.valOperand->etype = 
1230             getSpec( op->operand.valOperand->type = 
1231                      copyLinkChain (type )) ;
1232         return ;
1233         
1234     case SYMBOL :
1235         if (op->operand.symOperand->isitmp )
1236             op->operand.symOperand->etype = 
1237                 getSpec( op->operand.symOperand->type = 
1238                          copyLinkChain (type )) ;
1239         else
1240             werror (E_INTERNAL_ERROR,__FILE__,__LINE__,
1241                     "attempt to modify type of source");
1242         return;
1243         
1244     case TYPE:
1245         op->operand.typeOperand = copyLinkChain (type);
1246         return ;
1247     }
1248     
1249 }
1250
1251 /*-----------------------------------------------------------------*/
1252 /* geniCodeValueAtAddress - generate intermeditate code for value  */
1253 /*                          at address                             */
1254 /*-----------------------------------------------------------------*/
1255 operand *geniCodeRValue (operand *op, bool force)
1256 {
1257     iCode *ic ;
1258     link *type = operandType(op);
1259     link *etype= getSpec(type);
1260     
1261     /* if this is an array & already */
1262     /* an address then return this   */
1263     if (IS_AGGREGATE(type) || 
1264         (IS_PTR(type) && !force && !op->isaddr))
1265         return operandFromOperand(op);
1266         
1267     /* if this is not an address then must be */
1268     /* rvalue already so return this one      */
1269     if (!op->isaddr)
1270         return op ;
1271     
1272     /* if this is not a temp symbol then */
1273     if (!IS_ITEMP(op) && 
1274         !force        && 
1275         !IN_FARSPACE(SPEC_OCLS(etype))) {
1276         op = operandFromOperand(op);
1277         op->isaddr = 0;
1278         return op;
1279     }
1280     
1281     if (IS_SPEC(type) && 
1282         IS_TRUE_SYMOP(op) &&
1283         !IN_FARSPACE(SPEC_OCLS(etype))) {
1284         op = operandFromOperand(op);
1285         op->isaddr = 0;
1286         return op;
1287     }
1288
1289     ic = newiCode(GET_VALUE_AT_ADDRESS,op,NULL);
1290     if (IS_PTR(type) && op->isaddr && force) 
1291         type = type->next;
1292     
1293     type = copyLinkChain(type);
1294
1295     IC_RESULT(ic) = newiTempOperand (type,1);
1296     IC_RESULT(ic)->isaddr = 0;
1297  
1298 /*     ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
1299
1300     /* if the right is a symbol */
1301     if (op->type == SYMBOL)
1302         IC_RESULT(ic)->operand.symOperand->args = 
1303             op->operand.symOperand->args ;
1304     ADDTOCHAIN(ic);
1305     
1306     return IC_RESULT(ic) ;
1307 }
1308
1309 /*-----------------------------------------------------------------*/
1310 /* geniCodeCast - changes the value from one type to another       */
1311 /*-----------------------------------------------------------------*/
1312 operand *geniCodeCast (link *type, operand *op, bool implicit) 
1313 {
1314     iCode *ic ;
1315     link *optype ;
1316     link *opetype = getSpec(optype = operandType(op));
1317     link *restype ;
1318     
1319     /* one of them has size zero then error */
1320     if (IS_VOID(optype)) {
1321         werror(E_CAST_ZERO);
1322         return op;
1323     }
1324
1325     /* if the operand is already the desired type then do nothing */
1326     if ( checkType (type,optype) == 1)  
1327         return op;
1328     
1329     /* if this is a literal then just change the type & return */
1330     if (IS_LITERAL(opetype) && !IS_PTR(type) && !IS_PTR(optype))
1331         return operandFromValue(valCastLiteral(type,
1332                                                operandLitValue(op)));
1333           
1334     /* if casting to some pointer type &&
1335        the destination is not a generic pointer 
1336        then give a warning : (only for implicit casts)*/
1337     if (IS_PTR(optype) && implicit &&
1338         (DCL_TYPE(optype) != DCL_TYPE(type)) && 
1339         !IS_GENPTR(type)) {
1340         werror(E_INCOMPAT_CAST);
1341         werror(E_CONTINUE,"from type '");
1342         printTypeChain(optype,stderr);fprintf(stderr,"' to type '");      
1343         printTypeChain(type,stderr);fprintf(stderr,"'\n");
1344     }
1345
1346     /* if they are the same size create an assignment */
1347     if (getSize(type) == getSize(optype) && 
1348         !IS_BITFIELD(type)               &&
1349         !IS_FLOAT(type)                  &&
1350         !IS_FLOAT(optype)                &&
1351         ((IS_SPEC(type) && IS_SPEC(optype)) ||
1352          (!IS_SPEC(type) && !IS_SPEC(optype)))) {
1353
1354         ic = newiCode('=',NULL,op);     
1355         IC_RESULT(ic) = newiTempOperand(type,0);
1356          SPIL_LOC(IC_RESULT(ic))  =
1357              (IS_TRUE_SYMOP(op) ? OP_SYMBOL(op) : NULL);
1358         IC_RESULT(ic)->isaddr = 0;
1359     } else { 
1360         ic = newiCode(CAST,operandFromLink(type),
1361                       geniCodeRValue(op,FALSE));
1362         
1363         IC_RESULT(ic)= newiTempOperand(type,0);
1364     }
1365     
1366     /* preserve the storage class & output class */
1367     /* of the original variable                  */
1368     restype = getSpec(operandType(IC_RESULT(ic)));
1369     SPEC_SCLS(restype) = SPEC_SCLS(opetype);
1370     SPEC_OCLS(restype) = SPEC_OCLS(opetype);
1371     
1372     ADDTOCHAIN(ic);
1373     return IC_RESULT(ic) ;
1374 }
1375
1376 /*-----------------------------------------------------------------*/
1377 /* geniCodeLabel - will create a Label                             */
1378 /*-----------------------------------------------------------------*/
1379 void geniCodeLabel (symbol *label)
1380 {
1381     iCode *ic;
1382     
1383     ic = newiCodeLabelGoto(LABEL,label);
1384     ADDTOCHAIN(ic);
1385 }
1386
1387 /*-----------------------------------------------------------------*/
1388 /* geniCodeGoto  - will create a Goto                              */
1389 /*-----------------------------------------------------------------*/
1390 void geniCodeGoto (symbol *label)
1391 {
1392     iCode *ic;
1393     
1394     ic = newiCodeLabelGoto(GOTO,label);
1395     ADDTOCHAIN(ic);
1396 }
1397
1398 /*-----------------------------------------------------------------*/
1399 /* geniCodeMultiply - gen intermediate code for multiplication     */
1400 /*-----------------------------------------------------------------*/
1401 operand *geniCodeMultiply (operand *left, operand *right)
1402
1403     iCode *ic ;
1404     int p2 = 0;
1405     link *resType ;
1406     LRTYPE ;
1407     
1408     /* if they are both literal then we know the result */
1409     if (IS_LITERAL(letype) && IS_LITERAL(retype)) 
1410         return operandFromValue (valMult(left->operand.valOperand,
1411                                          right->operand.valOperand));
1412         
1413     resType = computeType (ltype,rtype) ;
1414     left = geniCodeCast(resType,left,TRUE);
1415     right= geniCodeCast(resType,right,TRUE);
1416     
1417     /* if the right is a literal & power of 2 */
1418     /* then make it a left shift              */
1419     if (IS_LITERAL(retype) && !IS_FLOAT(letype) &&
1420         (p2 = powof2 ((unsigned long)floatFromVal(right->operand.valOperand)))) 
1421         ic = newiCode(LEFT_OP, left,operandFromLit(p2)); /* left shift */
1422     else {
1423         ic = newiCode('*',left,right);  /* normal multiplication */
1424         /* if the size left or right > 1 then support routine */
1425         if (getSize(ltype) > 1 || getSize(rtype) > 1)
1426             ic->supportRtn = 1;
1427
1428     }
1429     IC_RESULT(ic) = newiTempOperand(resType,1);
1430     
1431     ADDTOCHAIN(ic);
1432     return IC_RESULT(ic) ;
1433 }
1434
1435 /*-----------------------------------------------------------------*/
1436 /* geniCodeDivision - gen intermediate code for division           */
1437 /*-----------------------------------------------------------------*/
1438 operand *geniCodeDivision (operand *left, operand *right)
1439
1440     iCode *ic ;
1441     int p2 = 0;
1442     link *resType;
1443     link *rtype = operandType(right);
1444     link *retype= getSpec(rtype);
1445     link *ltype = operandType(left);
1446     link *letype= getSpec(ltype);
1447     
1448     resType = computeType (ltype,rtype) ;
1449     left = geniCodeCast(resType,left,TRUE);
1450     right= geniCodeCast(resType,right,TRUE);
1451     
1452     /* if the right is a literal & power of 2 */
1453     /* then make it a right shift             */
1454     if (IS_LITERAL(retype) && 
1455         !IS_FLOAT(letype)  &&
1456         (p2 = powof2 ((unsigned long) 
1457                       floatFromVal(right->operand.valOperand)))) 
1458         ic = newiCode(RIGHT_OP, left,operandFromLit(p2)); /* right shift */
1459     else {
1460         ic = newiCode('/',left,right);  /* normal division */
1461         /* if the size left or right > 1 then support routine */
1462         if (getSize(ltype) > 1 || getSize(rtype) > 1)
1463             ic->supportRtn = 1;
1464     }
1465     IC_RESULT(ic) = newiTempOperand(resType,0);
1466     
1467     ADDTOCHAIN(ic);
1468     return IC_RESULT(ic) ;
1469 }
1470 /*-----------------------------------------------------------------*/
1471 /* geniCodeModulus  - gen intermediate code for modulus            */
1472 /*-----------------------------------------------------------------*/
1473 operand *geniCodeModulus (operand *left, operand *right)
1474
1475     iCode *ic ;
1476     link *resType;
1477     LRTYPE ;
1478     
1479     /* if they are both literal then we know the result */
1480     if (IS_LITERAL(letype) && IS_LITERAL(retype)) 
1481         return operandFromValue (valMod(left->operand.valOperand,
1482                                         right->operand.valOperand));
1483     
1484     resType = computeType (ltype,rtype) ;
1485     left = geniCodeCast(resType,left,TRUE);
1486     right= geniCodeCast(resType,right,TRUE);
1487     
1488     /* now they are the same size */
1489     ic = newiCode('%',left,right);
1490
1491     /* if the size left or right > 1 then support routine */
1492     if (getSize(ltype) > 1 || getSize(rtype) > 1)
1493         ic->supportRtn = 1;
1494     IC_RESULT(ic) = newiTempOperand(resType,0);
1495     
1496     ADDTOCHAIN(ic);
1497     return IC_RESULT(ic) ;
1498 }
1499
1500 /*-----------------------------------------------------------------*/
1501 /* geniCodePtrPtrSubtract - subtracts pointer from pointer         */
1502 /*-----------------------------------------------------------------*/
1503 operand *geniCodePtrPtrSubtract (operand *left, operand *right)
1504 {
1505     iCode *ic ;
1506     operand *result;
1507     LRTYPE ;
1508     
1509     /* if they are both literals then */
1510     if (IS_LITERAL(letype) && IS_LITERAL(retype)) {
1511         result = operandFromValue (valMinus(left->operand.valOperand,
1512                                             right->operand.valOperand));
1513         goto subtractExit;
1514     }
1515     
1516     ic = newiCode('-',left,right);
1517     
1518     IC_RESULT(ic) = result = newiTempOperand(newIntLink(),1);
1519     ADDTOCHAIN(ic);
1520     
1521  subtractExit:
1522     return geniCodeDivision (result,
1523                              operandFromLit(getSize(ltype->next)));   
1524 }
1525
1526 /*-----------------------------------------------------------------*/
1527 /* geniCodeSubtract - generates code for subtraction               */
1528 /*-----------------------------------------------------------------*/
1529 operand *geniCodeSubtract (operand *left, operand *right)
1530 {
1531     iCode *ic ;
1532     int isarray= 0;
1533     link *resType;
1534     LRTYPE ;
1535     
1536     /* if they both pointers then */
1537     if ((IS_PTR(ltype) || IS_ARRAY(ltype)) &&
1538         (IS_PTR(rtype) || IS_ARRAY(rtype)))
1539         return geniCodePtrPtrSubtract (left,right);
1540     
1541     /* if they are both literal then we know the result */
1542     if (IS_LITERAL(letype) && IS_LITERAL(retype)) 
1543         return operandFromValue (valMinus(left->operand.valOperand,
1544                                           right->operand.valOperand));
1545     
1546     /* if left is an array or pointer */
1547     if ( IS_PTR(ltype) || IS_ARRAY(ltype) ) {    
1548         isarray = left->isaddr ;    
1549         right = geniCodeMultiply (right,
1550                                   operandFromLit(getSize(ltype->next)));
1551         resType = copyLinkChain(IS_ARRAY(ltype) ? ltype->next : ltype);
1552     }
1553     else { /* make them the same size */
1554         resType = computeType (ltype,rtype) ;
1555         left = geniCodeCast(resType,left,TRUE);
1556         right= geniCodeCast(resType,right,TRUE);    
1557     }
1558     
1559     ic = newiCode('-',left,right);
1560     
1561     IC_RESULT(ic)= newiTempOperand(resType,1);
1562     IC_RESULT(ic)->isaddr = (isarray ? 1 : 0);
1563
1564     /* if left or right is a float */
1565     if (IS_FLOAT(ltype) || IS_FLOAT(rtype))
1566         ic->supportRtn = 1;
1567
1568     ADDTOCHAIN(ic);
1569     return IC_RESULT(ic) ;
1570 }
1571
1572 /*-----------------------------------------------------------------*/
1573 /* geniCodeAdd - generates iCode for addition                      */
1574 /*-----------------------------------------------------------------*/
1575 operand *geniCodeAdd (operand *left, operand *right )
1576 {
1577     iCode *ic ;
1578     link *resType ;
1579     operand *size ;
1580     int isarray = 0;
1581     LRTYPE ;
1582     
1583     /* if left is an array then array access */
1584     if (IS_ARRAY(ltype)) 
1585         return geniCodeArray (left,right);           
1586     
1587     /* if the right side is LITERAL zero */
1588     /* return the left side              */
1589     if (IS_LITERAL(retype) && !floatFromVal(valFromType(retype)))
1590         return left;
1591     
1592     /* if left is literal zero return right */
1593     if (IS_LITERAL(letype) && !floatFromVal(valFromType(letype)))
1594         return right ;
1595     
1596     /* if left is an array or pointer then size */
1597     if (IS_PTR(ltype)) {    
1598         
1599         isarray = left->isaddr;
1600         size = 
1601             operandFromLit(getSize(ltype->next));
1602         right = geniCodeMultiply (right ,size);
1603         resType = copyLinkChain(ltype);
1604     }
1605     else { /* make them the same size */
1606         resType = computeType (ltype,rtype) ;
1607         left = geniCodeCast(resType,left,TRUE);
1608         right= geniCodeCast(resType,right,TRUE);
1609     }
1610     
1611     /* if they are both literals then we know */
1612     if (IS_LITERAL(letype) && IS_LITERAL(retype))
1613         return operandFromValue (valPlus(valFromType(letype),
1614                                          valFromType(retype)));
1615     
1616     ic = newiCode('+',left,right);
1617     
1618     IC_RESULT(ic) = newiTempOperand(resType,1);
1619     IC_RESULT(ic)->isaddr = ( isarray ? 1 : 0);
1620
1621     /* if left or right is a float then support
1622        routine */
1623     if (IS_FLOAT(ltype) || IS_FLOAT(rtype))
1624         ic->supportRtn = 1;
1625
1626     ADDTOCHAIN(ic);
1627     
1628     return IC_RESULT(ic) ;
1629     
1630 }
1631
1632 /*-----------------------------------------------------------------*/
1633 /* aggrToPtr - changes an aggregate to pointer to an aggregate     */
1634 /*-----------------------------------------------------------------*/
1635 link *aggrToPtr ( link *type, bool force)
1636 {
1637     link *etype ;
1638     link *ptype ;
1639
1640     
1641     if (IS_PTR(type) && !force)
1642         return type;
1643
1644     etype = getSpec(type);
1645     ptype = newLink();
1646
1647     ptype->next = type;
1648     /* if the output class is generic */
1649     if ((DCL_TYPE(ptype) = PTR_TYPE(SPEC_OCLS(etype))) == CPOINTER)
1650         DCL_PTR_CONST(ptype) = 1;
1651
1652     /* if the variable was declared a constant */
1653     /* then the pointer points to a constant */
1654     if (IS_CONSTANT(etype) )
1655         DCL_PTR_CONST(ptype) = 1;
1656
1657     /* the variable was volatile then pointer to volatile */
1658     if (IS_VOLATILE(etype))
1659         DCL_PTR_VOLATILE(ptype) = 1;
1660     return ptype; 
1661 }
1662
1663 /*-----------------------------------------------------------------*/
1664 /* geniCodeArray2Ptr - array to pointer                            */
1665 /*-----------------------------------------------------------------*/
1666 operand *geniCodeArray2Ptr (operand *op)
1667 {
1668     link *optype = operandType(op);
1669     link *opetype = getSpec(optype);
1670
1671     /* set the pointer depending on the storage class */    
1672     if ((DCL_TYPE(optype) = PTR_TYPE(SPEC_OCLS(opetype))) == CPOINTER)
1673         DCL_PTR_CONST(optype) = 1;
1674
1675     
1676     /* if the variable was declared a constant */
1677     /* then the pointer points to a constant */
1678     if (IS_CONSTANT(opetype) )
1679         DCL_PTR_CONST(optype) = 1;
1680
1681     /* the variable was volatile then pointer to volatile */
1682     if (IS_VOLATILE(opetype))
1683         DCL_PTR_VOLATILE(optype) = 1;
1684     op->isaddr = 0;
1685     return op;
1686 }
1687
1688 /*-----------------------------------------------------------------*/
1689 /* geniCodeArray - array access                                    */
1690 /*-----------------------------------------------------------------*/
1691 operand *geniCodeArray (operand *left,operand *right)
1692 {
1693     iCode *ic;
1694     link *ltype = operandType(left);
1695     
1696     if (IS_PTR(ltype)) {
1697         if (IS_PTR(ltype->next) && left->isaddr)
1698             left = geniCodeRValue(left,FALSE);
1699         return geniCodeDerefPtr(geniCodeAdd(left,right));
1700     }
1701
1702     /* array access */
1703     right = geniCodeMultiply(right,
1704                              operandFromLit(getSize(ltype->next)));
1705
1706     /* we can check for limits here */
1707     if (isOperandLiteral(right) &&
1708         IS_ARRAY(ltype)         &&
1709         DCL_ELEM(ltype)         &&
1710         (operandLitValue(right)/getSize(ltype->next)) >= DCL_ELEM(ltype)) {
1711         werror(E_ARRAY_BOUND);
1712         right = operandFromLit(0);
1713     }
1714
1715     ic = newiCode('+',left,right);    
1716
1717     IC_RESULT(ic) = newiTempOperand(((IS_PTR(ltype) && 
1718                                       !IS_AGGREGATE(ltype->next) &&
1719                                       !IS_PTR(ltype->next))
1720                                      ? ltype : ltype->next),0);
1721
1722     IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(ltype->next));
1723     ADDTOCHAIN(ic);
1724     return IC_RESULT(ic) ;
1725 }
1726
1727 /*-----------------------------------------------------------------*/
1728 /* geniCodeStruct - generates intermediate code for structres      */
1729 /*-----------------------------------------------------------------*/
1730 operand *geniCodeStruct (operand *left, operand *right, bool islval)
1731 {
1732     iCode *ic ;
1733     link *type = operandType(left);
1734     link *etype = getSpec(type);
1735     link *retype ;
1736     symbol *element = getStructElement(SPEC_STRUCT(etype), 
1737                                        right->operand.symOperand);
1738     
1739     /* add the offset */
1740     ic = newiCode('+',left,operandFromLit(element->offset));
1741     
1742     IC_RESULT(ic) = newiTempOperand(element->type,0);
1743
1744     /* preserve the storage & output class of the struct */
1745     /* as well as the volatile attribute */
1746     retype = getSpec(operandType(IC_RESULT(ic)));
1747     SPEC_SCLS(retype) = SPEC_SCLS(etype);
1748     SPEC_OCLS(retype) = SPEC_OCLS(etype);
1749     SPEC_VOLATILE(retype) |= SPEC_VOLATILE(etype);    
1750
1751     if (IS_PTR(element->type)) 
1752         setOperandType(IC_RESULT(ic),aggrToPtr(operandType(IC_RESULT(ic)),TRUE));
1753     
1754     IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(element->type));
1755
1756     
1757     ADDTOCHAIN(ic);
1758     return (islval ? IC_RESULT(ic) : geniCodeRValue(IC_RESULT(ic),TRUE));
1759 }
1760
1761 /*-----------------------------------------------------------------*/
1762 /* geniCodePostInc - generate int code for Post increment          */
1763 /*-----------------------------------------------------------------*/
1764 operand *geniCodePostInc (operand *op)
1765 {
1766     iCode *ic ;
1767     operand *rOp ;
1768     link *optype = operandType(op);
1769     operand *result ;
1770     operand *rv = (IS_ITEMP(op) ? 
1771                    geniCodeRValue(op,(IS_PTR(optype) ? TRUE : FALSE)) :
1772                    op);            
1773     link *rvtype = operandType(rv);    
1774     int size = 0;
1775     
1776     /* if this is not an address we have trouble */
1777     if ( ! op->isaddr ) {
1778         werror (E_LVALUE_REQUIRED,"++");
1779         return op ;
1780     }
1781     
1782     rOp = newiTempOperand(rvtype,0);
1783     rOp->noSpilLoc = 1;
1784
1785     if (IS_ITEMP(rv))
1786         rv->noSpilLoc = 1;
1787
1788     geniCodeAssign(rOp,rv,0);
1789    
1790     size = (IS_PTR(rvtype) ? getSize(rvtype->next) : 1);
1791     ic = newiCode('+',rv,operandFromLit(size));          
1792     IC_RESULT(ic) = result =newiTempOperand(rvtype,0);
1793     ADDTOCHAIN(ic);
1794
1795     geniCodeAssign(op,result,0);
1796     
1797     return rOp;
1798     
1799 }
1800
1801 /*-----------------------------------------------------------------*/
1802 /* geniCodePreInc - generate code for preIncrement                 */
1803 /*-----------------------------------------------------------------*/
1804 operand *geniCodePreInc (operand *op)
1805 {
1806     iCode *ic ;
1807     link *optype = operandType(op);    
1808     operand *rop = (IS_ITEMP(op) ? 
1809                     geniCodeRValue (op,(IS_PTR(optype) ? TRUE : FALSE)) :
1810                     op);
1811     link *roptype = operandType(rop);
1812     operand *result;
1813     int size = 0;
1814     
1815     if ( ! op->isaddr ) {
1816         werror(E_LVALUE_REQUIRED,"++");
1817         return op ;
1818     }
1819
1820
1821     size = (IS_PTR(roptype) ? getSize(roptype->next) : 1);
1822     ic = newiCode('+',rop,operandFromLit(size));
1823     IC_RESULT(ic) = result = newiTempOperand(roptype,0) ;
1824     ADDTOCHAIN(ic);
1825
1826     
1827     return geniCodeAssign(op,result,0) ;
1828 }
1829
1830 /*-----------------------------------------------------------------*/
1831 /* geniCodePostDec - generates code for Post decrement             */
1832 /*-----------------------------------------------------------------*/
1833 operand *geniCodePostDec (operand *op)
1834 {
1835     iCode *ic ;
1836     operand *rOp ;
1837     link *optype = operandType(op);
1838     operand *result ;
1839     operand *rv = (IS_ITEMP(op) ? 
1840                    geniCodeRValue(op,(IS_PTR(optype) ? TRUE : FALSE)) :
1841                    op);            
1842     link *rvtype = operandType(rv);    
1843     int size = 0;
1844     
1845     /* if this is not an address we have trouble */
1846     if ( ! op->isaddr ) {
1847         werror (E_LVALUE_REQUIRED,"++");
1848         return op ;
1849     }
1850     
1851     rOp = newiTempOperand(rvtype,0);
1852     rOp->noSpilLoc = 1;
1853
1854     if (IS_ITEMP(rv))
1855         rv->noSpilLoc = 1;
1856
1857     geniCodeAssign(rOp,rv,0);
1858    
1859     size = (IS_PTR(rvtype) ? getSize(rvtype->next) : 1);
1860     ic = newiCode('-',rv,operandFromLit(size));          
1861     IC_RESULT(ic) = result =newiTempOperand(rvtype,0);
1862     ADDTOCHAIN(ic);
1863
1864     geniCodeAssign(op,result,0);
1865     
1866     return rOp;
1867     
1868 }
1869
1870 /*-----------------------------------------------------------------*/
1871 /* geniCodePreDec - generate code for pre  decrement               */
1872 /*-----------------------------------------------------------------*/
1873 operand *geniCodePreDec (operand *op)
1874 {  
1875     iCode *ic ;
1876     link *optype = operandType(op);    
1877     operand *rop = (IS_ITEMP(op) ? 
1878                     geniCodeRValue (op,(IS_PTR(optype) ? TRUE : FALSE)) :
1879                     op);
1880     link *roptype = operandType(rop);
1881     operand *result;
1882     int size = 0;
1883     
1884     if ( ! op->isaddr ) {
1885         werror(E_LVALUE_REQUIRED,"++");
1886         return op ;
1887     }
1888
1889
1890     size = (IS_PTR(roptype) ? getSize(roptype->next) : 1);
1891     ic = newiCode('-',rop,operandFromLit(size));
1892     IC_RESULT(ic) = result = newiTempOperand(roptype,0) ;
1893     ADDTOCHAIN(ic);
1894
1895     
1896     return geniCodeAssign(op,result,0) ;
1897 }
1898
1899
1900 /*-----------------------------------------------------------------*/
1901 /* geniCodeBitwise - gen int code for bitWise  operators           */
1902 /*-----------------------------------------------------------------*/
1903 operand *geniCodeBitwise (operand *left, operand *right, 
1904                           int oper, link *resType)
1905 {
1906     iCode *ic;   
1907     
1908     left = geniCodeCast(resType,left,TRUE);
1909     right= geniCodeCast(resType,right,TRUE);
1910     
1911     ic = newiCode(oper,left,right);
1912     IC_RESULT(ic) = newiTempOperand(resType,0);
1913     
1914     ADDTOCHAIN(ic);
1915     return IC_RESULT(ic) ;
1916 }
1917
1918 /*-----------------------------------------------------------------*/
1919 /* geniCodeAddressOf - gens icode for '&' address of operator      */
1920 /*-----------------------------------------------------------------*/
1921 operand *geniCodeAddressOf (operand *op) 
1922 {
1923     iCode *ic;
1924     link *p ;
1925     link *optype = operandType(op);
1926     link *opetype= getSpec(optype);
1927     
1928     /* this must be a lvalue */
1929     if (!op->isaddr && !IS_AGGREGATE(optype)) {
1930         werror (E_LVALUE_REQUIRED,"&");
1931         return op;
1932     }
1933     
1934     p = newLink();
1935     p->class = DECLARATOR ;
1936     
1937     /* set the pointer depending on the storage class */
1938     if ((DCL_TYPE(p) = PTR_TYPE(SPEC_OCLS(opetype))) == CPOINTER)
1939         DCL_PTR_CONST(p) = 1;
1940
1941     /* make sure we preserve the const & volatile */
1942     if (IS_CONSTANT(opetype)) 
1943         DCL_PTR_CONST(p) = 1;
1944
1945     if (IS_VOLATILE(opetype))
1946         DCL_PTR_VOLATILE(p) = 1;
1947     
1948     p->next = copyLinkChain(optype);
1949     
1950     /* if already a temp */
1951     if (IS_ITEMP(op)) {
1952         setOperandType (op,p);     
1953         op->isaddr= 0;
1954         return op;
1955     }
1956     
1957     /* other wise make this of the type coming in */
1958     ic = newiCode(ADDRESS_OF,op,NULL);
1959     IC_RESULT(ic) = newiTempOperand(p,1);
1960     IC_RESULT(ic)->isaddr = 0;
1961     ADDTOCHAIN(ic);
1962     return IC_RESULT(ic);
1963 }
1964 /*-----------------------------------------------------------------*/
1965 /* setOClass - sets the output class depending on the pointer type */
1966 /*-----------------------------------------------------------------*/
1967 void setOClass (link *ptr, link *spec)
1968 {
1969     switch (DCL_TYPE(ptr)) {
1970     case POINTER:
1971         SPEC_OCLS(spec) = data ;
1972         break ;
1973         
1974     case GPOINTER:
1975         SPEC_OCLS(spec) = generic;
1976         break;
1977         
1978     case FPOINTER:
1979         SPEC_OCLS(spec) = xdata ;
1980         break ;
1981         
1982     case CPOINTER:
1983         SPEC_OCLS(spec) = code ;
1984         break ;  
1985         
1986     case IPOINTER:
1987         SPEC_OCLS(spec) = idata;
1988         break;
1989
1990     case PPOINTER:
1991         SPEC_OCLS(spec) = xstack;
1992         break;
1993     }
1994 }
1995
1996 /*-----------------------------------------------------------------*/
1997 /* geniCodeDerefPtr - dereference pointer with '*'                 */
1998 /*-----------------------------------------------------------------*/
1999 operand *geniCodeDerefPtr (operand *op)
2000 {    
2001     link *rtype , *retype ;
2002     link *optype = operandType(op);  
2003
2004     /* if this is a pointer then generate the rvalue */
2005     if (IS_PTR(optype)) {
2006         if (IS_TRUE_SYMOP(op)) {
2007             op->isaddr = 1;
2008             op = geniCodeRValue(op,TRUE);
2009         }
2010         else    
2011             op = geniCodeRValue(op,TRUE);       
2012     }
2013     
2014     /* now get rid of the pointer part */
2015     if (lvaluereq && IS_ITEMP(op) )
2016     {
2017         retype = getSpec(rtype = copyLinkChain(optype)) ;
2018     }
2019     else
2020     {
2021         retype = getSpec(rtype = copyLinkChain(optype->next)) ;
2022     }
2023     
2024     /* if this is a pointer then outputclass needs 2b updated */
2025     if (IS_PTR(optype)) 
2026         setOClass(optype,retype);    
2027         
2028     op->isGptr = IS_GENPTR(optype);
2029
2030     /* if the pointer was declared as a constant */
2031     /* then we cannot allow assignment to the derefed */
2032     if (IS_PTR_CONST(optype))
2033         SPEC_CONST(retype) = 1;
2034     
2035     op->isaddr = (IS_PTR(rtype)    ||
2036                   IS_STRUCT(rtype) || 
2037                   IS_INT(rtype)    ||
2038                   IS_CHAR(rtype)   ||
2039                   IS_FLOAT(rtype) );
2040
2041     if (!lvaluereq)
2042         op = geniCodeRValue(op,TRUE);
2043
2044     setOperandType(op,rtype);
2045     
2046     return op;    
2047 }
2048
2049 /*-----------------------------------------------------------------*/
2050 /* geniCodeUnaryMinus - does a unary minus of the operand          */
2051 /*-----------------------------------------------------------------*/
2052 operand *geniCodeUnaryMinus (operand *op)
2053 {
2054     iCode *ic ;
2055     link *optype = operandType(op);
2056     
2057     if (IS_LITERAL(optype))
2058         return operandFromLit(- floatFromVal(op->operand.valOperand));
2059     
2060     ic = newiCode(UNARYMINUS,op,NULL);
2061     IC_RESULT(ic) = newiTempOperand(optype,0);
2062     ADDTOCHAIN(ic);
2063     return IC_RESULT(ic);
2064 }
2065
2066 /*-----------------------------------------------------------------*/
2067 /* geniCodeLeftShift - gen i code for left shift                   */
2068 /*-----------------------------------------------------------------*/
2069 operand *geniCodeLeftShift (operand *left, operand *right)
2070
2071     iCode *ic;
2072     link *ltype = operandType(left);
2073     
2074     ic = newiCode(LEFT_OP,left,right);
2075     IC_RESULT(ic) = newiTempOperand(ltype,0);
2076     ADDTOCHAIN(ic);
2077     return IC_RESULT(ic) ;  
2078 }
2079
2080 /*-----------------------------------------------------------------*/
2081 /* geniCodeRightShift - gen i code for right shift                 */
2082 /*-----------------------------------------------------------------*/
2083 operand *geniCodeRightShift (operand *left, operand *right)
2084
2085     iCode *ic;
2086     link *ltype = operandType(left);
2087     
2088     ic = newiCode(RIGHT_OP,left,right);
2089     IC_RESULT(ic) = newiTempOperand(ltype,0);
2090     ADDTOCHAIN(ic);
2091     return IC_RESULT(ic) ;  
2092 }
2093
2094 #ifdef __BORLANDC__
2095 #define LONG_LONG __int64
2096 #else
2097 #define LONG_LONG long long
2098 #endif
2099
2100 /*-----------------------------------------------------------------*/
2101 /* geniCodeLogic- logic code                                       */
2102 /*-----------------------------------------------------------------*/
2103 operand *geniCodeLogic (operand *left, operand *right, int op )
2104 {
2105     iCode *ic ;
2106     link *ctype; 
2107     link *rtype = operandType(right);
2108     link *ltype = operandType(left);
2109     
2110     /* left is integral type and right is literal then
2111        check if the literal value is within bounds */
2112     if (IS_INTEGRAL(ltype) && IS_LITERAL(rtype)) {
2113         int nbits = bitsForType(ltype);
2114         long v = operandLitValue(right);
2115
2116         if (v > ((LONG_LONG) 1 << nbits) && v > 0)
2117             werror(W_CONST_RANGE," compare operation ");
2118     }
2119
2120     ctype = computeType(ltype,rtype);                         
2121     left = geniCodeCast(ctype,left,TRUE);
2122     right= geniCodeCast(ctype,right,TRUE);
2123
2124     ic = newiCode(op,left,right);
2125     IC_RESULT(ic) = newiTempOperand (newCharLink(),1);
2126
2127     /* if comparing anything greater than one byte
2128        and not a '==' || '!=' || '&&' || '||' (these
2129        will be inlined */
2130     if (getSize(ctype) > 1 && 
2131         op != EQ_OP        && 
2132         op != NE_OP        &&
2133         op != AND_OP       &&
2134         op != OR_OP        )
2135         ic->supportRtn = 1;
2136
2137     ADDTOCHAIN(ic);
2138     return IC_RESULT(ic);
2139 }
2140
2141 /*-----------------------------------------------------------------*/
2142 /* geniCodeUnary - for a a generic unary operation                 */
2143 /*-----------------------------------------------------------------*/
2144 operand *geniCodeUnary (operand *op, int oper )
2145 {
2146     iCode *ic = newiCode (oper,op,NULL);
2147     
2148     IC_RESULT(ic)= newiTempOperand(operandType(op),0);
2149     ADDTOCHAIN(ic);
2150     return IC_RESULT(ic) ;
2151 }
2152
2153 /*-----------------------------------------------------------------*/
2154 /* geniCodeConditional - geniCode for '?' ':' operation            */
2155 /*-----------------------------------------------------------------*/
2156 operand *geniCodeConditional (ast *tree)
2157 {
2158     iCode *ic ;
2159     symbol *falseLabel = newiTempLabel(NULL);
2160     symbol *exitLabel  = newiTempLabel(NULL);
2161     operand *cond = ast2iCode(tree->left);
2162     operand *true, *false , *result;
2163     
2164     ic = newiCodeCondition(geniCodeRValue(cond,FALSE),
2165                            NULL,falseLabel);
2166     ADDTOCHAIN(ic);
2167     
2168     true = ast2iCode(tree->right->left);
2169     
2170     /* move the value to a new Operand */
2171     result = newiTempOperand(operandType(true),0);
2172     geniCodeAssign(result,geniCodeRValue(true,FALSE),0);
2173     
2174     /* generate an unconditional goto */
2175     geniCodeGoto(exitLabel);
2176     
2177     /* now for the right side */
2178     geniCodeLabel(falseLabel);
2179     
2180     false = ast2iCode(tree->right->right);
2181     geniCodeAssign(result,geniCodeRValue(false,FALSE),0);
2182     
2183     /* create the exit label */
2184     geniCodeLabel(exitLabel);
2185     
2186     return result ;
2187 }
2188
2189 /*-----------------------------------------------------------------*/
2190 /* geniCodeAssign - generate code for assignment                   */
2191 /*-----------------------------------------------------------------*/
2192 operand *geniCodeAssign (operand *left, operand *right, int nosupdate)
2193 {
2194     iCode *ic ;
2195     link *ltype = operandType(left);
2196     link *rtype = operandType(right);
2197     
2198     if (!left->isaddr && !IS_ITEMP(left)) {
2199         werror(E_LVALUE_REQUIRED,"assignment");
2200         return left;
2201     }
2202         
2203     /* left is integral type and right is literal then
2204        check if the literal value is within bounds */
2205     if (IS_INTEGRAL(ltype) && IS_LITERAL(rtype)) {
2206         int nbits = bitsForType(ltype);
2207         long v = operandLitValue(right);
2208
2209         if (v > ((LONG_LONG)1 << nbits) && v > 0)
2210             werror(W_CONST_RANGE," = operation");
2211     }
2212
2213     /* if the left & right type don't exactly match */
2214     /* if pointer set then make sure the check is
2215        done with the type & not the pointer */
2216     /* then cast rights type to left */   
2217
2218     /* first check the type for pointer assignement */
2219     if (left->isaddr && IS_PTR(ltype) && IS_ITEMP(left) &&
2220         checkType(ltype,rtype)<0) {
2221         if (checkType(ltype->next,rtype) < 0)
2222             right = geniCodeCast(ltype->next,right,TRUE);
2223     } else
2224         if (checkType(ltype,rtype) < 0 )
2225             right = geniCodeCast(ltype,right,TRUE);
2226
2227     /* if left is a true symbol & ! volatile 
2228        create an assignment to temporary for
2229        the right & then assign this temporary
2230        to the symbol this is SSA . isn't it simple
2231        and folks have published mountains of paper on it */
2232     if (IS_TRUE_SYMOP(left) && 
2233         !isOperandVolatile(left,FALSE) &&
2234         isOperandGlobal(left)) {
2235         symbol *sym = NULL;
2236
2237         if (IS_TRUE_SYMOP(right))
2238             sym = OP_SYMBOL(right);
2239         ic = newiCode('=',NULL,right);
2240         IC_RESULT(ic) = right = newiTempOperand(ltype,0);       
2241         SPIL_LOC(right)  = sym ;
2242         ADDTOCHAIN(ic);
2243     }
2244     
2245     ic = newiCode('=',NULL,right);
2246     IC_RESULT(ic) = left;
2247     ADDTOCHAIN(ic);    
2248
2249     /* if left isgptr flag is set then support
2250        routine will be required */
2251     if (left->isGptr)
2252         ic->supportRtn = 1;
2253
2254     ic->nosupdate = nosupdate;
2255     return left;
2256 }
2257
2258 /*-----------------------------------------------------------------*/
2259 /* geniCodeSEParms - generate code for side effecting fcalls       */
2260 /*-----------------------------------------------------------------*/
2261 static void geniCodeSEParms (ast *parms)
2262 {
2263     if (!parms)
2264         return ;
2265
2266     if (parms->type == EX_OP && parms->opval.op == PARAM) {
2267         geniCodeSEParms (parms->left) ;
2268         geniCodeSEParms (parms->right);
2269         return ;
2270     }
2271
2272     /* hack don't like this but too lazy to think of
2273        something better */
2274     if (IS_ADDRESS_OF_OP(parms))
2275         parms->left->lvalue = 1;
2276     
2277     if (IS_CAST_OP(parms) && 
2278         IS_PTR(parms->ftype) && 
2279         IS_ADDRESS_OF_OP(parms->right))
2280         parms->right->left->lvalue = 1;
2281
2282     parms->opval.oprnd = 
2283         geniCodeRValue(ast2iCode (parms),FALSE);
2284    
2285     parms->type = EX_OPERAND ;
2286 }
2287
2288 /*-----------------------------------------------------------------*/
2289 /* geniCodeParms - generates parameters                            */
2290 /*-----------------------------------------------------------------*/
2291 static void geniCodeParms ( ast *parms , int *stack, link *fetype)
2292 {
2293     iCode *ic ;
2294     operand *pval ; 
2295     
2296     if ( ! parms )
2297         return ;
2298     
2299     /* if this is a param node then do the left & right */
2300     if (parms->type == EX_OP && parms->opval.op == PARAM) {
2301         geniCodeParms (parms->left, stack,fetype) ;
2302         geniCodeParms (parms->right, stack,fetype);
2303         return ;
2304     }
2305     
2306     /* get the parameter value */
2307     if (parms->type == EX_OPERAND)
2308         pval = parms->opval.oprnd ;
2309     else {
2310         /* maybe this else should go away ?? */
2311         /* hack don't like this but too lazy to think of
2312            something better */
2313         if (IS_ADDRESS_OF_OP(parms))
2314             parms->left->lvalue = 1;
2315     
2316         if (IS_CAST_OP(parms) && 
2317             IS_PTR(parms->ftype) && 
2318             IS_ADDRESS_OF_OP(parms->right))
2319             parms->right->left->lvalue = 1;
2320
2321         pval = geniCodeRValue(ast2iCode (parms),FALSE); 
2322     }
2323
2324     /* if register parm then make it a send */
2325     if ((parms->argSym && IS_REGPARM(parms->argSym->etype)) ||
2326         IS_REGPARM(parms->etype)) {
2327         ic = newiCode(SEND,pval,NULL);
2328         ADDTOCHAIN(ic);
2329     } else {
2330         /* now decide whether to push or assign */
2331         if (!(options.stackAuto || IS_RENT(fetype))) { 
2332             
2333             /* assign */
2334             operand *top = operandFromSymbol(parms->argSym);
2335             geniCodeAssign(top,pval,1);
2336         }
2337         else { 
2338             link *p = operandType(pval);
2339             /* push */
2340             ic = newiCode(IPUSH,pval,NULL);
2341             ic->parmPush = 1;
2342             /* update the stack adjustment */
2343             *stack += getSize(IS_AGGREGATE(p)? aggrToPtr(p,FALSE):p);
2344             ADDTOCHAIN(ic);
2345         }
2346     }
2347     
2348 }
2349
2350 /*-----------------------------------------------------------------*/
2351 /* geniCodeCall - generates temp code for calling                  */
2352 /*-----------------------------------------------------------------*/
2353 operand *geniCodeCall (operand *left, ast *parms)
2354
2355     iCode *ic ;
2356     operand *result ;
2357     link *type, *etype;
2358     int stack = 0 ;
2359     
2360     /* take care of parameters with side-effecting
2361        function calls in them, this is required to take care 
2362        of overlaying function parameters */
2363     geniCodeSEParms ( parms );
2364
2365     /* first the parameters */
2366     geniCodeParms ( parms , &stack , getSpec(operandType(left)));
2367     
2368     /* now call : if symbol then pcall */
2369     if (IS_ITEMP(left)) 
2370         ic = newiCode(PCALL,left,NULL);
2371     else
2372         ic = newiCode(CALL,left,NULL);
2373     
2374     IC_ARGS(ic) = left->operand.symOperand->args ;
2375     type = copyLinkChain(operandType(left)->next);
2376     etype = getSpec(type);
2377     SPEC_EXTR(etype) = 0;
2378     IC_RESULT(ic) = result = newiTempOperand(type,1);
2379     
2380     ADDTOCHAIN(ic);
2381     
2382     /* stack adjustment after call */
2383     left->parmBytes = stack;
2384
2385     return result;
2386 }
2387
2388 /*-----------------------------------------------------------------*/
2389 /* geniCodeReceive - generate intermediate code for "receive"      */
2390 /*-----------------------------------------------------------------*/
2391 static void geniCodeReceive (value *args)
2392 {   
2393     /* for all arguments that are passed in registers */
2394     while (args) {
2395
2396         if (IS_REGPARM(args->etype)) {
2397             operand *opr = operandFromValue(args);
2398             operand *opl ;
2399             symbol *sym  = OP_SYMBOL(opr);
2400             iCode *ic ;
2401
2402             /* we will use it after all optimizations
2403                and before liveRange calculation */          
2404             if (!sym->addrtaken && 
2405                 !IS_VOLATILE(sym->etype) &&
2406                 !IN_FARSPACE(SPEC_OCLS(sym->etype))) {
2407                 opl = newiTempOperand(args->type,0);
2408                 sym->reqv = opl ;           
2409                 sym->reqv->key = sym->key ;
2410                 OP_SYMBOL(sym->reqv)->key = sym->key;
2411                 OP_SYMBOL(sym->reqv)->isreqv = 1;
2412                 OP_SYMBOL(sym->reqv)->islocal= 0;
2413                 SPIL_LOC(sym->reqv) =  sym;
2414             }
2415
2416             ic = newiCode(RECEIVE,NULL,NULL);
2417             currFunc->recvSize = getSize(sym->etype);
2418             IC_RESULT(ic) = opr;
2419             ADDTOCHAIN(ic);
2420         }
2421         
2422         args = args->next;
2423     }
2424 }
2425
2426 /*-----------------------------------------------------------------*/
2427 /* geniCodeFunctionBody - create the function body                 */
2428 /*-----------------------------------------------------------------*/
2429 void geniCodeFunctionBody (ast *tree)
2430 {
2431     iCode *ic ;
2432     operand *func ;
2433     link *fetype  ;
2434     int savelineno ;
2435     
2436     /* reset the auto generation */
2437     /* numbers */
2438     iTempNum = 0 ;
2439     iTempLblNum = 0;   
2440     operandKey = 0 ;
2441     iCodeKey = 0 ;
2442     func  = ast2iCode(tree->left);
2443     fetype = getSpec(operandType(func));
2444     
2445     savelineno = lineno;
2446     lineno = OP_SYMBOL(func)->lineDef;
2447     /* create an entry label */
2448     geniCodeLabel(entryLabel);    
2449     lineno = savelineno;
2450
2451     /* create a proc icode */
2452     ic = newiCode(FUNCTION,func,NULL);
2453     /* if the function has parmas   then */
2454     /* save the parameters information    */
2455     ic->argLabel.args = tree->values.args ;
2456     ic->lineno = OP_SYMBOL(func)->lineDef;
2457
2458     ADDTOCHAIN(ic);   
2459     
2460     /* for all parameters that are passed
2461        on registers add a "receive" */
2462     geniCodeReceive( tree->values.args );
2463
2464     /* generate code for the body */
2465     ast2iCode(tree->right);
2466     
2467     /* create a label for return */
2468     geniCodeLabel(returnLabel);
2469     
2470     /* now generate the end proc */
2471     ic = newiCode(ENDFUNCTION,func,NULL);
2472     ADDTOCHAIN(ic);
2473     return ;
2474 }
2475
2476 /*-----------------------------------------------------------------*/
2477 /* geniCodeReturn - gen icode for 'return' statement               */
2478 /*-----------------------------------------------------------------*/
2479 void geniCodeReturn (operand *op)
2480 {
2481     iCode *ic;
2482     
2483     /* if the operand is present force an rvalue */
2484     if (op) 
2485         op = geniCodeRValue(op,FALSE);    
2486     
2487     ic = newiCode(RETURN,op,NULL);
2488     ADDTOCHAIN(ic);
2489 }
2490
2491 /*-----------------------------------------------------------------*/
2492 /* geniCodeIfx - generates code for extended if statement          */
2493 /*-----------------------------------------------------------------*/
2494 void geniCodeIfx (ast *tree)
2495 {
2496     iCode *ic;
2497     operand *condition = ast2iCode(tree->left);
2498     link *cetype; 
2499     
2500     /* if condition is null then exit */
2501     if (!condition)
2502         goto exit ;
2503     else
2504         condition = geniCodeRValue(condition,FALSE);
2505     
2506     cetype = getSpec(operandType(condition));
2507     /* if the condition is a literal */
2508     if (IS_LITERAL(cetype)) {
2509         if (floatFromVal(condition->operand.valOperand)) {
2510             if (tree->trueLabel)
2511                 geniCodeGoto(tree->trueLabel);
2512             else
2513                 assert(1);
2514         }
2515         else {
2516             if (tree->falseLabel)
2517                 geniCodeGoto (tree->falseLabel);
2518             else
2519                 assert(1);
2520         }
2521         goto exit;
2522     }
2523     
2524     if ( tree->trueLabel ) {
2525         ic = newiCodeCondition(condition,
2526                                tree->trueLabel,
2527                                NULL );
2528         ADDTOCHAIN(ic);
2529         
2530         if ( tree->falseLabel) 
2531             geniCodeGoto(tree->falseLabel);     
2532     }
2533     else {
2534         ic = newiCodeCondition (condition,
2535                                 NULL,
2536                                 tree->falseLabel);
2537         ADDTOCHAIN(ic);
2538     }
2539     
2540  exit:
2541     ast2iCode(tree->right);
2542 }
2543
2544 /*-----------------------------------------------------------------*/
2545 /* geniCodeJumpTable - tries to create a jump table for switch     */
2546 /*-----------------------------------------------------------------*/
2547 int geniCodeJumpTable (operand *cond, value *caseVals, ast *tree)
2548 {
2549     int min = 0 ,max = 0, t, cnt = 0;
2550     value *vch;
2551     iCode *ic;
2552     operand *boundary;
2553     symbol *falseLabel;
2554     set *labels = NULL ;
2555
2556     if (!tree || !caseVals)
2557         return 0;
2558
2559     /* the criteria for creating a jump table is */
2560     /* all integer numbers between the maximum & minimum must */
2561     /* be present , the maximum value should not exceed 255 */
2562     min = max = (int)floatFromVal(vch = caseVals);
2563     sprintf(buffer,"_case_%d_%d",
2564             tree->values.switchVals.swNum,
2565             min);
2566     addSet(&labels,newiTempLabel(buffer));
2567
2568     /* if there is only one case value then no need */
2569     if (!(vch = vch->next ))
2570         return 0;
2571
2572     while (vch) {
2573         if (((t = (int)floatFromVal(vch)) - max) != 1)
2574             return 0;
2575         sprintf(buffer,"_case_%d_%d",
2576                 tree->values.switchVals.swNum,
2577                 t);
2578         addSet(&labels,newiTempLabel(buffer));
2579         max = t;
2580         cnt++ ;
2581         vch = vch->next ;
2582     }
2583     
2584     /* if the number of case statements <= 2 then */
2585     /* it is not economical to create the jump table */
2586     /* since two compares are needed for boundary conditions */
2587     if ((! optimize.noJTabBoundary  && cnt <= 2) || max > (255/3))
2588         return 0;
2589     
2590     if ( tree->values.switchVals.swDefault )
2591         sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2592     else
2593         sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum  );
2594     
2595     falseLabel = newiTempLabel (buffer);
2596
2597     /* so we can create a jumptable */
2598     /* first we rule out the boundary conditions */
2599     /* if only optimization says so */
2600     if ( ! optimize.noJTabBoundary ) {
2601         link *cetype = getSpec(operandType(cond));
2602         /* no need to check the lower bound if
2603            the condition is unsigned & minimum value is zero */
2604         if (!( min == 0  && SPEC_USIGN(cetype))) {
2605             boundary = geniCodeLogic (cond,operandFromLit(min),'<');
2606             ic = newiCodeCondition (boundary,falseLabel,NULL);
2607             ADDTOCHAIN(ic);
2608         }
2609
2610         /* now for upper bounds */
2611         boundary = geniCodeLogic(cond,operandFromLit(max),'>');
2612         ic = newiCodeCondition (boundary,falseLabel,NULL);
2613         ADDTOCHAIN(ic);
2614     }
2615
2616     /* if the min is not zero then we no make it zero */
2617     if (min) {
2618         cond = geniCodeSubtract(cond,operandFromLit(min));
2619         setOperandType(cond, UCHARTYPE);
2620     }
2621
2622     /* now create the jumptable */
2623     ic = newiCode(JUMPTABLE,NULL,NULL);
2624     IC_JTCOND(ic) = cond;
2625     IC_JTLABELS(ic) = labels;
2626     ADDTOCHAIN(ic);
2627     return 1;       
2628 }
2629
2630 /*-----------------------------------------------------------------*/
2631 /* geniCodeSwitch - changes a switch to a if statement             */
2632 /*-----------------------------------------------------------------*/
2633 void geniCodeSwitch (ast *tree)
2634 {
2635     iCode *ic ;
2636     operand *cond = geniCodeRValue(ast2iCode (tree->left),FALSE);
2637     value *caseVals = tree->values.switchVals.swVals ;
2638     symbol *trueLabel , *falseLabel;
2639     
2640     /* if we can make this a jump table */
2641     if ( geniCodeJumpTable (cond,caseVals,tree) )
2642         goto jumpTable ; /* no need for the comparison */
2643
2644     /* for the cases defined do */
2645     while (caseVals) {
2646         
2647         operand *compare = geniCodeLogic (cond,
2648                                           operandFromValue(caseVals),
2649                                           EQ_OP);
2650         
2651         sprintf(buffer,"_case_%d_%d",
2652                 tree->values.switchVals.swNum,
2653                 (int) floatFromVal(caseVals));
2654         trueLabel = newiTempLabel(buffer);
2655         
2656         ic = newiCodeCondition(compare,trueLabel,NULL);
2657         ADDTOCHAIN(ic);
2658         caseVals = caseVals->next;
2659     }
2660
2661
2662     
2663     /* if default is present then goto break else break */
2664     if ( tree->values.switchVals.swDefault )
2665         sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2666     else
2667         sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum  );
2668     
2669     falseLabel = newiTempLabel (buffer);
2670     geniCodeGoto(falseLabel);
2671  
2672  jumpTable:   
2673     ast2iCode(tree->right);
2674
2675
2676 /*-----------------------------------------------------------------*/
2677 /* geniCodeInline - intermediate code for inline assembler         */
2678 /*-----------------------------------------------------------------*/
2679 static void geniCodeInline (ast *tree)
2680 {
2681     iCode *ic;
2682
2683     ic = newiCode(INLINEASM,NULL,NULL);
2684     IC_INLINE(ic) = tree->values.inlineasm;
2685     ADDTOCHAIN(ic);
2686 }
2687
2688 /*-----------------------------------------------------------------*/
2689 /* ast2iCode - creates an icodeList from an ast                    */
2690 /*-----------------------------------------------------------------*/
2691 operand *ast2iCode (ast *tree)
2692 {
2693     operand *left = NULL;
2694     operand *right= NULL;
2695     
2696     if (!tree)
2697         return NULL ;
2698     
2699     /* set the global variables for filename & line number */
2700     if ( tree->filename )
2701         filename =  tree->filename ;
2702     if ( tree->lineno)
2703         lineno   = tree->lineno ;
2704     if (tree->block)
2705         block = tree->block ;
2706     if (tree->level)
2707         scopeLevel = tree->level;
2708     
2709     if (tree->type == EX_VALUE )
2710         return operandFromValue(tree->opval.val);
2711     
2712     if (tree->type == EX_LINK )
2713         return operandFromLink (tree->opval.lnk);
2714     
2715     /* if we find a nullop */
2716     if (tree->type == EX_OP && 
2717         ( tree->opval.op == NULLOP || 
2718           tree->opval.op == BLOCK )) {
2719         ast2iCode (tree->left);
2720         ast2iCode (tree->right);
2721         return NULL ;
2722     }
2723     
2724     /* special cases for not evaluating */
2725     if ( tree->opval.op != ':'   && 
2726          tree->opval.op != '?'   &&
2727          tree->opval.op != CALL  && 
2728          tree->opval.op != IFX   &&
2729          tree->opval.op != LABEL &&
2730          tree->opval.op != GOTO  &&     
2731          tree->opval.op != SWITCH &&
2732          tree->opval.op != FUNCTION &&
2733          tree->opval.op != INLINEASM ) {
2734         if (IS_ASSIGN_OP(tree->opval.op) || 
2735             IS_DEREF_OP(tree)            || 
2736             (tree->opval.op == '&' && !tree->right) ||
2737             tree->opval.op == PTR_OP) {
2738             lvaluereq++;
2739             left = operandFromAst(tree->left);
2740             lvaluereq--;
2741         } else {
2742             left =  operandFromAst(tree->left);
2743         }
2744         if (tree->opval.op == INC_OP || 
2745             tree->opval.op == DEC_OP) {
2746             lvaluereq++;
2747             right= operandFromAst(tree->right);
2748             lvaluereq--;
2749         } else {
2750             right= operandFromAst(tree->right);
2751         }
2752     }
2753     
2754     /* now depending on the type of operand */
2755     /* this will be a biggy                 */
2756     switch (tree->opval.op) {
2757         
2758     case '[' :    /* array operation */
2759         left= geniCodeRValue (left,TRUE);
2760         right=geniCodeRValue (right,TRUE);                 
2761         
2762         return geniCodeArray (left,right);
2763         
2764     case '.' :   /* structure dereference */
2765         if (IS_PTR(operandType(left)))
2766             left = geniCodeRValue(left,TRUE);
2767         else
2768             left = geniCodeRValue(left,FALSE);            
2769         
2770         return geniCodeStruct (left,right,tree->lvalue);
2771         
2772     case PTR_OP: /* structure pointer dereference */
2773         {
2774             link *pType;
2775             pType = operandType(left);
2776             left = geniCodeRValue(left,TRUE);
2777             
2778             setOClass (pType,getSpec(operandType(left)));
2779         }              
2780         
2781         return geniCodeStruct (left, right,tree->lvalue);
2782         
2783     case INC_OP: /* increment operator */
2784         if ( left )
2785             return geniCodePostInc (left);
2786         else
2787             return geniCodePreInc (right);
2788         
2789     case DEC_OP: /* decrement operator */
2790         if ( left )
2791             return geniCodePostDec (left);
2792         else
2793             return geniCodePreDec (right);
2794         
2795     case '&' : /* bitwise and or address of operator */
2796         if ( right ) { /* this is a bitwise operator   */
2797             left= geniCodeRValue(left,FALSE);
2798             right= geniCodeRValue(right,FALSE);     
2799             return geniCodeBitwise (left,right,BITWISEAND,tree->ftype);
2800         } else
2801             return geniCodeAddressOf (left);
2802         
2803     case '|': /* bitwise or & xor */
2804     case '^':
2805         return geniCodeBitwise (geniCodeRValue(left,FALSE),
2806                                 geniCodeRValue(right,FALSE),
2807                                 tree->opval.op,
2808                                 tree->ftype);
2809         
2810     case '/':
2811         return geniCodeDivision (geniCodeRValue(left,FALSE),
2812                                  geniCodeRValue(right,FALSE));
2813         
2814     case '%' :
2815         return geniCodeModulus (geniCodeRValue(left,FALSE),
2816                                 geniCodeRValue(right,FALSE));
2817     case '*':
2818         if ( right ) 
2819             return geniCodeMultiply (geniCodeRValue(left,FALSE),
2820                                      geniCodeRValue(right,FALSE));
2821         else        
2822             return geniCodeDerefPtr (geniCodeRValue(left,FALSE));
2823         
2824     case '-' :
2825         if ( right ) 
2826             return geniCodeSubtract (geniCodeRValue(left,FALSE),
2827                                      geniCodeRValue(right,FALSE));
2828         else
2829             return geniCodeUnaryMinus (geniCodeRValue(left,FALSE));
2830         
2831     case '+' :
2832         if ( right ) 
2833             return geniCodeAdd (geniCodeRValue(left,FALSE),
2834                                 geniCodeRValue(right,FALSE));
2835         else
2836             return geniCodeRValue(left,FALSE) ; /* unary '+' has no meaning */
2837         
2838     case LEFT_OP:
2839         return geniCodeLeftShift (geniCodeRValue(left,FALSE),
2840                                   geniCodeRValue(right,FALSE));
2841         
2842     case RIGHT_OP:
2843         return geniCodeRightShift (geniCodeRValue(left,FALSE),
2844                                    geniCodeRValue(right,FALSE));
2845     case CAST:
2846         return geniCodeCast (operandType(left),
2847                              geniCodeRValue(right,FALSE),FALSE);
2848         
2849     case '~' :
2850     case '!' :
2851     case RRC:
2852     case RLC:   
2853         return geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
2854         
2855     case GETHBIT:
2856         {
2857             operand *op = geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
2858             setOperandType(op, UCHARTYPE);
2859             return op;
2860         }
2861     case '>' :
2862     case '<' :
2863     case LE_OP:
2864     case GE_OP:
2865     case EQ_OP:
2866     case NE_OP:
2867     case AND_OP:
2868     case OR_OP:
2869         return geniCodeLogic (geniCodeRValue(left,FALSE),
2870                               geniCodeRValue(right,FALSE),
2871                               tree->opval.op);
2872     case '?' : 
2873         return geniCodeConditional (tree); 
2874         
2875     case SIZEOF:
2876         return operandFromLit(getSize(tree->right->ftype));
2877         
2878     case '='        :
2879         {
2880             link *rtype = operandType(right);
2881             link *ltype = operandType(left);
2882             if (IS_PTR(rtype) && IS_ITEMP(right) 
2883                 && right->isaddr && checkType(rtype->next,ltype)==1)
2884                 right =  geniCodeRValue(right,TRUE);
2885             else
2886                 right = geniCodeRValue(right,FALSE);
2887
2888             geniCodeAssign (left,right,0);
2889             return right ;
2890         }              
2891     case MUL_ASSIGN:
2892         return 
2893             geniCodeAssign(left,
2894                            geniCodeMultiply(geniCodeRValue (operandFromOperand(left),
2895                                                             FALSE),
2896                                             geniCodeRValue(right,FALSE)),0);
2897                                                 
2898     case DIV_ASSIGN:
2899         return 
2900             geniCodeAssign(left,
2901                            geniCodeDivision(geniCodeRValue(operandFromOperand(left),
2902                                                            FALSE),
2903                                             geniCodeRValue(right,FALSE)),0);
2904     case MOD_ASSIGN:
2905         return 
2906             geniCodeAssign(left,
2907                            geniCodeModulus(geniCodeRValue(operandFromOperand(left),
2908                                                           FALSE),
2909                                            geniCodeRValue(right,FALSE)),0);
2910     case ADD_ASSIGN: 
2911         {
2912             link *rtype = operandType(right);
2913             link *ltype = operandType(left);
2914             if (IS_PTR(rtype) && IS_ITEMP(right) 
2915                 && right->isaddr && checkType(rtype->next,ltype)==1)
2916                 right =  geniCodeRValue(right,TRUE);
2917             else
2918                 right = geniCodeRValue(right,FALSE);
2919
2920            
2921             return geniCodeAssign(left,
2922                                   geniCodeAdd (geniCodeRValue(operandFromOperand(left),
2923                                                               FALSE),
2924                                                right),0);
2925         }
2926     case SUB_ASSIGN:
2927         {
2928             link *rtype = operandType(right);
2929             link *ltype = operandType(left);
2930             if (IS_PTR(rtype) && IS_ITEMP(right) 
2931                 && right->isaddr && checkType(rtype->next,ltype)==1) {
2932                 right =  geniCodeRValue(right,TRUE);
2933             }
2934             else {
2935                 right = geniCodeRValue(right,FALSE);
2936             }
2937             return 
2938                 geniCodeAssign (left,
2939                                 geniCodeSubtract(geniCodeRValue(operandFromOperand(left),
2940                                                                 FALSE),
2941                                                  right),0);
2942         }
2943     case LEFT_ASSIGN:
2944         return 
2945             geniCodeAssign (left,
2946                             geniCodeLeftShift(geniCodeRValue(operandFromOperand(left)
2947                                                              ,FALSE),
2948                                               geniCodeRValue(right,FALSE)),0);
2949     case RIGHT_ASSIGN:
2950         return 
2951             geniCodeAssign(left,
2952                            geniCodeRightShift(geniCodeRValue(operandFromOperand(left)
2953                                                              ,FALSE),
2954                                               geniCodeRValue(right,FALSE)),0);
2955     case AND_ASSIGN:
2956         return 
2957             geniCodeAssign (left,
2958                             geniCodeBitwise(geniCodeRValue(operandFromOperand(left),
2959                                                            FALSE),
2960                                             geniCodeRValue(right,FALSE),
2961                                             BITWISEAND,
2962                                             operandType(left)),0);
2963     case XOR_ASSIGN:
2964         return 
2965             geniCodeAssign (left,
2966                             geniCodeBitwise (geniCodeRValue(operandFromOperand(left),
2967                                                             FALSE),
2968                                              geniCodeRValue(right,FALSE),
2969                                              '^',
2970                                              operandType(left)),0);
2971     case OR_ASSIGN:
2972         return 
2973             geniCodeAssign (left,
2974                             geniCodeBitwise (geniCodeRValue(operandFromOperand(left)
2975                                                             ,FALSE),
2976                                              geniCodeRValue(right,FALSE),
2977                                              '|',
2978                                              operandType(left)),0);
2979     case ',' :
2980         return geniCodeRValue(right,FALSE);
2981         
2982     case CALL:
2983         return geniCodeCall (ast2iCode(tree->left),
2984                              tree->right);
2985     case LABEL:
2986         geniCodeLabel(ast2iCode(tree->left)->operand.symOperand);
2987         return ast2iCode (tree->right);
2988         
2989     case GOTO:
2990         geniCodeGoto (ast2iCode(tree->left)->operand.symOperand);
2991         return ast2iCode (tree->right);
2992         
2993     case FUNCTION:
2994         geniCodeFunctionBody ( tree );
2995         return NULL ;
2996         
2997     case RETURN:
2998         geniCodeReturn (right);
2999         return NULL ;
3000         
3001     case IFX:
3002         geniCodeIfx (tree);
3003         return NULL ;
3004         
3005     case SWITCH:
3006         geniCodeSwitch (tree);
3007         return NULL;
3008
3009     case INLINEASM:
3010         geniCodeInline (tree);
3011         return NULL ;
3012     }
3013     
3014     return NULL;
3015 }
3016
3017 /*-----------------------------------------------------------------*/
3018 /* reverseICChain - gets from the list and creates a linkedlist    */
3019 /*-----------------------------------------------------------------*/
3020 iCode *reverseiCChain ()
3021 {
3022     iCode *loop = NULL ;
3023     iCode *prev = NULL ;
3024     
3025     while ((loop = getSet(&iCodeChain))) {
3026         loop->next = prev ;
3027         if ( prev )
3028             prev->prev = loop; 
3029         prev = loop ;
3030     }
3031     
3032     return prev;
3033 }
3034
3035
3036 /*-----------------------------------------------------------------*/
3037 /* iCodeFromAst - given an ast will convert it to iCode            */
3038 /*-----------------------------------------------------------------*/
3039 iCode *iCodeFromAst ( ast *tree )
3040 {
3041     returnLabel = newiTempLabel("_return");
3042     entryLabel  = newiTempLabel("_entry") ;
3043     ast2iCode (tree);
3044     return reverseiCChain ();
3045 }
3046