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