941cbb78b833907bbb76b49a5d64a8b233ad2aa1
[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         if (getSize(ltype) > 1) 
1611                 right = geniCodeCast(INTTYPE,right,TRUE);
1612         resType = copyLinkChain(ltype);
1613     }
1614     else { /* make them the same size */
1615         resType = computeType (ltype,rtype) ;
1616         left = geniCodeCast(resType,left,TRUE);
1617         right= geniCodeCast(resType,right,TRUE);
1618     }
1619     
1620     /* if they are both literals then we know */
1621     if (IS_LITERAL(letype) && IS_LITERAL(retype)
1622         && left->isLiteral && right->isLiteral)
1623         return operandFromValue (valPlus(valFromType(letype),
1624                                          valFromType(retype)));
1625     
1626     ic = newiCode('+',left,right);
1627     
1628     IC_RESULT(ic) = newiTempOperand(resType,1);
1629     IC_RESULT(ic)->isaddr = ( isarray ? 1 : 0);
1630
1631     /* if left or right is a float then support
1632        routine */
1633     if (IS_FLOAT(ltype) || IS_FLOAT(rtype))
1634         ic->supportRtn = 1;
1635
1636     ADDTOCHAIN(ic);
1637     
1638     return IC_RESULT(ic) ;
1639     
1640 }
1641
1642 /*-----------------------------------------------------------------*/
1643 /* aggrToPtr - changes an aggregate to pointer to an aggregate     */
1644 /*-----------------------------------------------------------------*/
1645 link *aggrToPtr ( link *type, bool force)
1646 {
1647     link *etype ;
1648     link *ptype ;
1649
1650     
1651     if (IS_PTR(type) && !force)
1652         return type;
1653
1654     etype = getSpec(type);
1655     ptype = newLink();
1656
1657     ptype->next = type;
1658     /* if the output class is generic */
1659     if ((DCL_TYPE(ptype) = PTR_TYPE(SPEC_OCLS(etype))) == CPOINTER)
1660         DCL_PTR_CONST(ptype) = port->mem.code_ro;
1661
1662     /* if the variable was declared a constant */
1663     /* then the pointer points to a constant */
1664     if (IS_CONSTANT(etype) )
1665         DCL_PTR_CONST(ptype) = 1;
1666
1667     /* the variable was volatile then pointer to volatile */
1668     if (IS_VOLATILE(etype))
1669         DCL_PTR_VOLATILE(ptype) = 1;
1670     return ptype; 
1671 }
1672
1673 /*-----------------------------------------------------------------*/
1674 /* geniCodeArray2Ptr - array to pointer                            */
1675 /*-----------------------------------------------------------------*/
1676 operand *geniCodeArray2Ptr (operand *op)
1677 {
1678     link *optype = operandType(op);
1679     link *opetype = getSpec(optype);
1680
1681     /* set the pointer depending on the storage class */    
1682     if ((DCL_TYPE(optype) = PTR_TYPE(SPEC_OCLS(opetype))) == CPOINTER)
1683         DCL_PTR_CONST(optype) = port->mem.code_ro;
1684
1685     
1686     /* if the variable was declared a constant */
1687     /* then the pointer points to a constant */
1688     if (IS_CONSTANT(opetype) )
1689         DCL_PTR_CONST(optype) = 1;
1690
1691     /* the variable was volatile then pointer to volatile */
1692     if (IS_VOLATILE(opetype))
1693         DCL_PTR_VOLATILE(optype) = 1;
1694     op->isaddr = 0;
1695     return op;
1696 }
1697
1698 /*-----------------------------------------------------------------*/
1699 /* geniCodeArray - array access                                    */
1700 /*-----------------------------------------------------------------*/
1701 operand *geniCodeArray (operand *left,operand *right)
1702 {
1703     iCode *ic;
1704     link *ltype = operandType(left);
1705     
1706     if (IS_PTR(ltype)) {
1707         if (IS_PTR(ltype->next) && left->isaddr)
1708             left = geniCodeRValue(left,FALSE);
1709         return geniCodeDerefPtr(geniCodeAdd(left,right));
1710     }
1711
1712     /* array access */
1713     right = geniCodeMultiply(right,
1714                              operandFromLit(getSize(ltype->next)));
1715
1716     /* we can check for limits here */
1717     if (isOperandLiteral(right) &&
1718         IS_ARRAY(ltype)         &&
1719         DCL_ELEM(ltype)         &&
1720         (operandLitValue(right)/getSize(ltype->next)) >= DCL_ELEM(ltype)) {
1721         werror(E_ARRAY_BOUND);
1722         right = operandFromLit(0);
1723     }
1724
1725     ic = newiCode('+',left,right);    
1726
1727     IC_RESULT(ic) = newiTempOperand(((IS_PTR(ltype) && 
1728                                       !IS_AGGREGATE(ltype->next) &&
1729                                       !IS_PTR(ltype->next))
1730                                      ? ltype : ltype->next),0);
1731
1732     IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(ltype->next));
1733     ADDTOCHAIN(ic);
1734     return IC_RESULT(ic) ;
1735 }
1736
1737 /*-----------------------------------------------------------------*/
1738 /* geniCodeStruct - generates intermediate code for structres      */
1739 /*-----------------------------------------------------------------*/
1740 operand *geniCodeStruct (operand *left, operand *right, bool islval)
1741 {
1742     iCode *ic ;
1743     link *type = operandType(left);
1744     link *etype = getSpec(type);
1745     link *retype ;
1746     symbol *element = getStructElement(SPEC_STRUCT(etype), 
1747                                        right->operand.symOperand);
1748     
1749     /* add the offset */
1750     ic = newiCode('+',left,operandFromLit(element->offset));
1751     
1752     IC_RESULT(ic) = newiTempOperand(element->type,0);
1753
1754     /* preserve the storage & output class of the struct */
1755     /* as well as the volatile attribute */
1756     retype = getSpec(operandType(IC_RESULT(ic)));
1757     SPEC_SCLS(retype) = SPEC_SCLS(etype);
1758     SPEC_OCLS(retype) = SPEC_OCLS(etype);
1759     SPEC_VOLATILE(retype) |= SPEC_VOLATILE(etype);    
1760
1761     if (IS_PTR(element->type)) 
1762         setOperandType(IC_RESULT(ic),aggrToPtr(operandType(IC_RESULT(ic)),TRUE));
1763     
1764     IC_RESULT(ic)->isaddr = (!IS_AGGREGATE(element->type));
1765
1766     
1767     ADDTOCHAIN(ic);
1768     return (islval ? IC_RESULT(ic) : geniCodeRValue(IC_RESULT(ic),TRUE));
1769 }
1770
1771 /*-----------------------------------------------------------------*/
1772 /* geniCodePostInc - generate int code for Post increment          */
1773 /*-----------------------------------------------------------------*/
1774 operand *geniCodePostInc (operand *op)
1775 {
1776     iCode *ic ;
1777     operand *rOp ;
1778     link *optype = operandType(op);
1779     operand *result ;
1780     operand *rv = (IS_ITEMP(op) ? 
1781                    geniCodeRValue(op,(IS_PTR(optype) ? TRUE : FALSE)) :
1782                    op);            
1783     link *rvtype = operandType(rv);    
1784     int size = 0;
1785     
1786     /* if this is not an address we have trouble */
1787     if ( ! op->isaddr ) {
1788         werror (E_LVALUE_REQUIRED,"++");
1789         return op ;
1790     }
1791     
1792     rOp = newiTempOperand(rvtype,0);
1793     rOp->noSpilLoc = 1;
1794
1795     if (IS_ITEMP(rv))
1796         rv->noSpilLoc = 1;
1797
1798     geniCodeAssign(rOp,rv,0);
1799    
1800     size = (IS_PTR(rvtype) ? getSize(rvtype->next) : 1);
1801     ic = newiCode('+',rv,operandFromLit(size));          
1802     IC_RESULT(ic) = result =newiTempOperand(rvtype,0);
1803     ADDTOCHAIN(ic);
1804
1805     geniCodeAssign(op,result,0);
1806     
1807     return rOp;
1808     
1809 }
1810
1811 /*-----------------------------------------------------------------*/
1812 /* geniCodePreInc - generate code for preIncrement                 */
1813 /*-----------------------------------------------------------------*/
1814 operand *geniCodePreInc (operand *op)
1815 {
1816     iCode *ic ;
1817     link *optype = operandType(op);    
1818     operand *rop = (IS_ITEMP(op) ? 
1819                     geniCodeRValue (op,(IS_PTR(optype) ? TRUE : FALSE)) :
1820                     op);
1821     link *roptype = operandType(rop);
1822     operand *result;
1823     int size = 0;
1824     
1825     if ( ! op->isaddr ) {
1826         werror(E_LVALUE_REQUIRED,"++");
1827         return op ;
1828     }
1829
1830
1831     size = (IS_PTR(roptype) ? getSize(roptype->next) : 1);
1832     ic = newiCode('+',rop,operandFromLit(size));
1833     IC_RESULT(ic) = result = newiTempOperand(roptype,0) ;
1834     ADDTOCHAIN(ic);
1835
1836     
1837     return geniCodeAssign(op,result,0) ;
1838 }
1839
1840 /*-----------------------------------------------------------------*/
1841 /* geniCodePostDec - generates code for Post decrement             */
1842 /*-----------------------------------------------------------------*/
1843 operand *geniCodePostDec (operand *op)
1844 {
1845     iCode *ic ;
1846     operand *rOp ;
1847     link *optype = operandType(op);
1848     operand *result ;
1849     operand *rv = (IS_ITEMP(op) ? 
1850                    geniCodeRValue(op,(IS_PTR(optype) ? TRUE : FALSE)) :
1851                    op);            
1852     link *rvtype = operandType(rv);    
1853     int size = 0;
1854     
1855     /* if this is not an address we have trouble */
1856     if ( ! op->isaddr ) {
1857         werror (E_LVALUE_REQUIRED,"++");
1858         return op ;
1859     }
1860     
1861     rOp = newiTempOperand(rvtype,0);
1862     rOp->noSpilLoc = 1;
1863
1864     if (IS_ITEMP(rv))
1865         rv->noSpilLoc = 1;
1866
1867     geniCodeAssign(rOp,rv,0);
1868    
1869     size = (IS_PTR(rvtype) ? getSize(rvtype->next) : 1);
1870     ic = newiCode('-',rv,operandFromLit(size));          
1871     IC_RESULT(ic) = result =newiTempOperand(rvtype,0);
1872     ADDTOCHAIN(ic);
1873
1874     geniCodeAssign(op,result,0);
1875     
1876     return rOp;
1877     
1878 }
1879
1880 /*-----------------------------------------------------------------*/
1881 /* geniCodePreDec - generate code for pre  decrement               */
1882 /*-----------------------------------------------------------------*/
1883 operand *geniCodePreDec (operand *op)
1884 {  
1885     iCode *ic ;
1886     link *optype = operandType(op);    
1887     operand *rop = (IS_ITEMP(op) ? 
1888                     geniCodeRValue (op,(IS_PTR(optype) ? TRUE : FALSE)) :
1889                     op);
1890     link *roptype = operandType(rop);
1891     operand *result;
1892     int size = 0;
1893     
1894     if ( ! op->isaddr ) {
1895         werror(E_LVALUE_REQUIRED,"++");
1896         return op ;
1897     }
1898
1899
1900     size = (IS_PTR(roptype) ? getSize(roptype->next) : 1);
1901     ic = newiCode('-',rop,operandFromLit(size));
1902     IC_RESULT(ic) = result = newiTempOperand(roptype,0) ;
1903     ADDTOCHAIN(ic);
1904
1905     
1906     return geniCodeAssign(op,result,0) ;
1907 }
1908
1909
1910 /*-----------------------------------------------------------------*/
1911 /* geniCodeBitwise - gen int code for bitWise  operators           */
1912 /*-----------------------------------------------------------------*/
1913 operand *geniCodeBitwise (operand *left, operand *right, 
1914                           int oper, link *resType)
1915 {
1916     iCode *ic;   
1917     
1918     left = geniCodeCast(resType,left,TRUE);
1919     right= geniCodeCast(resType,right,TRUE);
1920     
1921     ic = newiCode(oper,left,right);
1922     IC_RESULT(ic) = newiTempOperand(resType,0);
1923     
1924     ADDTOCHAIN(ic);
1925     return IC_RESULT(ic) ;
1926 }
1927
1928 /*-----------------------------------------------------------------*/
1929 /* geniCodeAddressOf - gens icode for '&' address of operator      */
1930 /*-----------------------------------------------------------------*/
1931 operand *geniCodeAddressOf (operand *op) 
1932 {
1933     iCode *ic;
1934     link *p ;
1935     link *optype = operandType(op);
1936     link *opetype= getSpec(optype);
1937     
1938     /* lvalue check already done in decorateType */
1939     /* this must be a lvalue */
1940 /*     if (!op->isaddr && !IS_AGGREGATE(optype)) { */
1941 /*      werror (E_LVALUE_REQUIRED,"&"); */
1942 /*      return op; */
1943 /*     } */
1944     
1945     p = newLink();
1946     p->class = DECLARATOR ;
1947     
1948     /* set the pointer depending on the storage class */
1949     if ((DCL_TYPE(p) = PTR_TYPE(SPEC_OCLS(opetype))) == CPOINTER)
1950         DCL_PTR_CONST(p) = port->mem.code_ro;
1951
1952     /* make sure we preserve the const & volatile */
1953     if (IS_CONSTANT(opetype)) 
1954         DCL_PTR_CONST(p) = 1;
1955
1956     if (IS_VOLATILE(opetype))
1957         DCL_PTR_VOLATILE(p) = 1;
1958     
1959     p->next = copyLinkChain(optype);
1960     
1961     /* if already a temp */
1962     if (IS_ITEMP(op)) {
1963         setOperandType (op,p);     
1964         op->isaddr= 0;
1965         return op;
1966     }
1967     
1968     /* other wise make this of the type coming in */
1969     ic = newiCode(ADDRESS_OF,op,NULL);
1970     IC_RESULT(ic) = newiTempOperand(p,1);
1971     IC_RESULT(ic)->isaddr = 0;
1972     ADDTOCHAIN(ic);
1973     return IC_RESULT(ic);
1974 }
1975 /*-----------------------------------------------------------------*/
1976 /* setOClass - sets the output class depending on the pointer type */
1977 /*-----------------------------------------------------------------*/
1978 void setOClass (link *ptr, link *spec)
1979 {
1980     switch (DCL_TYPE(ptr)) {
1981     case POINTER:
1982         SPEC_OCLS(spec) = data ;
1983         break ;
1984         
1985     case GPOINTER:
1986         SPEC_OCLS(spec) = generic;
1987         break;
1988         
1989     case FPOINTER:
1990         SPEC_OCLS(spec) = xdata ;
1991         break ;
1992         
1993     case CPOINTER:
1994         SPEC_OCLS(spec) = code ;
1995         break ;  
1996         
1997     case IPOINTER:
1998         SPEC_OCLS(spec) = idata;
1999         break;
2000
2001     case PPOINTER:
2002         SPEC_OCLS(spec) = xstack;
2003         break;
2004
2005     case EEPPOINTER:
2006         SPEC_OCLS(spec) = eeprom;
2007         break;
2008
2009     default:
2010         break;
2011
2012     }
2013 }
2014
2015 /*-----------------------------------------------------------------*/
2016 /* geniCodeDerefPtr - dereference pointer with '*'                 */
2017 /*-----------------------------------------------------------------*/
2018 operand *geniCodeDerefPtr (operand *op)
2019 {    
2020     link *rtype , *retype ;
2021     link *optype = operandType(op);  
2022
2023     /* if this is a pointer then generate the rvalue */
2024     if (IS_PTR(optype)) {
2025         if (IS_TRUE_SYMOP(op)) {
2026             op->isaddr = 1;
2027             op = geniCodeRValue(op,TRUE);
2028         }
2029         else    
2030             op = geniCodeRValue(op,TRUE);       
2031     }
2032     
2033     /* now get rid of the pointer part */
2034     if (lvaluereq && IS_ITEMP(op) )
2035     {
2036         retype = getSpec(rtype = copyLinkChain(optype)) ;
2037     }
2038     else
2039     {
2040         retype = getSpec(rtype = copyLinkChain(optype->next)) ;
2041     }
2042     
2043     /* if this is a pointer then outputclass needs 2b updated */
2044     if (IS_PTR(optype)) 
2045         setOClass(optype,retype);    
2046         
2047     op->isGptr = IS_GENPTR(optype);
2048
2049     /* if the pointer was declared as a constant */
2050     /* then we cannot allow assignment to the derefed */
2051     if (IS_PTR_CONST(optype))
2052         SPEC_CONST(retype) = 1;
2053     
2054     op->isaddr = (IS_PTR(rtype)    ||
2055                   IS_STRUCT(rtype) || 
2056                   IS_INT(rtype)    ||
2057                   IS_CHAR(rtype)   ||
2058                   IS_FLOAT(rtype) );
2059
2060     if (!lvaluereq)
2061         op = geniCodeRValue(op,TRUE);
2062
2063     setOperandType(op,rtype);
2064     
2065     return op;    
2066 }
2067
2068 /*-----------------------------------------------------------------*/
2069 /* geniCodeUnaryMinus - does a unary minus of the operand          */
2070 /*-----------------------------------------------------------------*/
2071 operand *geniCodeUnaryMinus (operand *op)
2072 {
2073     iCode *ic ;
2074     link *optype = operandType(op);
2075     
2076     if (IS_LITERAL(optype))
2077         return operandFromLit(- floatFromVal(op->operand.valOperand));
2078     
2079     ic = newiCode(UNARYMINUS,op,NULL);
2080     IC_RESULT(ic) = newiTempOperand(optype,0);
2081     ADDTOCHAIN(ic);
2082     return IC_RESULT(ic);
2083 }
2084
2085 /*-----------------------------------------------------------------*/
2086 /* geniCodeLeftShift - gen i code for left shift                   */
2087 /*-----------------------------------------------------------------*/
2088 operand *geniCodeLeftShift (operand *left, operand *right)
2089
2090     iCode *ic;
2091     link *ltype = operandType(left);
2092     
2093     ic = newiCode(LEFT_OP,left,right);
2094     IC_RESULT(ic) = newiTempOperand(ltype,0);
2095     ADDTOCHAIN(ic);
2096     return IC_RESULT(ic) ;  
2097 }
2098
2099 /*-----------------------------------------------------------------*/
2100 /* geniCodeRightShift - gen i code for right shift                 */
2101 /*-----------------------------------------------------------------*/
2102 operand *geniCodeRightShift (operand *left, operand *right)
2103
2104     iCode *ic;
2105     link *ltype = operandType(left);
2106     
2107     ic = newiCode(RIGHT_OP,left,right);
2108     IC_RESULT(ic) = newiTempOperand(ltype,0);
2109     ADDTOCHAIN(ic);
2110     return IC_RESULT(ic) ;  
2111 }
2112
2113 #ifdef __BORLANDC__
2114 #define LONG_LONG __int64
2115 #else
2116 #define LONG_LONG long long
2117 #endif
2118
2119 /*-----------------------------------------------------------------*/
2120 /* geniCodeLogic- logic code                                       */
2121 /*-----------------------------------------------------------------*/
2122 operand *geniCodeLogic (operand *left, operand *right, int op )
2123 {
2124     iCode *ic ;
2125     link *ctype; 
2126     link *rtype = operandType(right);
2127     link *ltype = operandType(left);
2128     
2129     /* left is integral type and right is literal then
2130        check if the literal value is within bounds */
2131     if (IS_INTEGRAL(ltype) && IS_LITERAL(rtype)) {
2132         int nbits = bitsForType(ltype);
2133         long v = operandLitValue(right);
2134
2135         if (v > ((LONG_LONG) 1 << nbits) && v > 0)
2136             werror(W_CONST_RANGE," compare operation ");
2137     }
2138
2139     ctype = computeType(ltype,rtype);                         
2140     left = geniCodeCast(ctype,left,TRUE);
2141     right= geniCodeCast(ctype,right,TRUE);
2142
2143     ic = newiCode(op,left,right);
2144     IC_RESULT(ic) = newiTempOperand (newCharLink(),1);
2145
2146     /* if comparing anything greater than one byte
2147        and not a '==' || '!=' || '&&' || '||' (these
2148        will be inlined */
2149     if (getSize(ctype) > 1 && 
2150         op != EQ_OP        && 
2151         op != NE_OP        &&
2152         op != AND_OP       &&
2153         op != OR_OP        )
2154         ic->supportRtn = 1;
2155
2156     ADDTOCHAIN(ic);
2157     return IC_RESULT(ic);
2158 }
2159
2160 /*-----------------------------------------------------------------*/
2161 /* geniCodeUnary - for a a generic unary operation                 */
2162 /*-----------------------------------------------------------------*/
2163 operand *geniCodeUnary (operand *op, int oper )
2164 {
2165     iCode *ic = newiCode (oper,op,NULL);
2166     
2167     IC_RESULT(ic)= newiTempOperand(operandType(op),0);
2168     ADDTOCHAIN(ic);
2169     return IC_RESULT(ic) ;
2170 }
2171
2172 /*-----------------------------------------------------------------*/
2173 /* geniCodeConditional - geniCode for '?' ':' operation            */
2174 /*-----------------------------------------------------------------*/
2175 operand *geniCodeConditional (ast *tree)
2176 {
2177     iCode *ic ;
2178     symbol *falseLabel = newiTempLabel(NULL);
2179     symbol *exitLabel  = newiTempLabel(NULL);
2180     operand *cond = ast2iCode(tree->left);
2181     operand *true, *false , *result;
2182     
2183     ic = newiCodeCondition(geniCodeRValue(cond,FALSE),
2184                            NULL,falseLabel);
2185     ADDTOCHAIN(ic);
2186     
2187     true = ast2iCode(tree->right->left);
2188     
2189     /* move the value to a new Operand */
2190     result = newiTempOperand(operandType(true),0);
2191     geniCodeAssign(result,geniCodeRValue(true,FALSE),0);
2192     
2193     /* generate an unconditional goto */
2194     geniCodeGoto(exitLabel);
2195     
2196     /* now for the right side */
2197     geniCodeLabel(falseLabel);
2198     
2199     false = ast2iCode(tree->right->right);
2200     geniCodeAssign(result,geniCodeRValue(false,FALSE),0);
2201     
2202     /* create the exit label */
2203     geniCodeLabel(exitLabel);
2204     
2205     return result ;
2206 }
2207
2208 /*-----------------------------------------------------------------*/
2209 /* geniCodeAssign - generate code for assignment                   */
2210 /*-----------------------------------------------------------------*/
2211 operand *geniCodeAssign (operand *left, operand *right, int nosupdate)
2212 {
2213     iCode *ic ;
2214     link *ltype = operandType(left);
2215     link *rtype = operandType(right);
2216     
2217     if (!left->isaddr && !IS_ITEMP(left)) {
2218         werror(E_LVALUE_REQUIRED,"assignment");
2219         return left;
2220     }
2221         
2222     /* left is integral type and right is literal then
2223        check if the literal value is within bounds */
2224     if (IS_INTEGRAL(ltype) && right->type == VALUE && IS_LITERAL(rtype)) {
2225         int nbits = bitsForType(ltype);
2226         long v = operandLitValue(right);
2227
2228         if (v > ((LONG_LONG)1 << nbits) && v > 0)
2229             werror(W_CONST_RANGE," = operation");
2230     }
2231
2232     /* if the left & right type don't exactly match */
2233     /* if pointer set then make sure the check is
2234        done with the type & not the pointer */
2235     /* then cast rights type to left */   
2236
2237     /* first check the type for pointer assignement */
2238     if (left->isaddr && IS_PTR(ltype) && IS_ITEMP(left) &&
2239         checkType(ltype,rtype)<0) {
2240         if (checkType(ltype->next,rtype) < 0)
2241             right = geniCodeCast(ltype->next,right,TRUE);
2242     } else
2243         if (checkType(ltype,rtype) < 0 )
2244             right = geniCodeCast(ltype,right,TRUE);
2245
2246     /* if left is a true symbol & ! volatile 
2247        create an assignment to temporary for
2248        the right & then assign this temporary
2249        to the symbol this is SSA . isn't it simple
2250        and folks have published mountains of paper on it */
2251     if (IS_TRUE_SYMOP(left) && 
2252         !isOperandVolatile(left,FALSE) &&
2253         isOperandGlobal(left)) {
2254         symbol *sym = NULL;
2255
2256         if (IS_TRUE_SYMOP(right))
2257             sym = OP_SYMBOL(right);
2258         ic = newiCode('=',NULL,right);
2259         IC_RESULT(ic) = right = newiTempOperand(ltype,0);       
2260         SPIL_LOC(right)  = sym ;
2261         ADDTOCHAIN(ic);
2262     }
2263     
2264     ic = newiCode('=',NULL,right);
2265     IC_RESULT(ic) = left;
2266     ADDTOCHAIN(ic);    
2267
2268     /* if left isgptr flag is set then support
2269        routine will be required */
2270     if (left->isGptr)
2271         ic->supportRtn = 1;
2272
2273     ic->nosupdate = nosupdate;
2274     return left;
2275 }
2276
2277 /*-----------------------------------------------------------------*/
2278 /* geniCodeSEParms - generate code for side effecting fcalls       */
2279 /*-----------------------------------------------------------------*/
2280 static void geniCodeSEParms (ast *parms)
2281 {
2282     if (!parms)
2283         return ;
2284
2285     if (parms->type == EX_OP && parms->opval.op == PARAM) {
2286         geniCodeSEParms (parms->left) ;
2287         geniCodeSEParms (parms->right);
2288         return ;
2289     }
2290
2291     /* hack don't like this but too lazy to think of
2292        something better */
2293     if (IS_ADDRESS_OF_OP(parms))
2294         parms->left->lvalue = 1;
2295     
2296     if (IS_CAST_OP(parms) && 
2297         IS_PTR(parms->ftype) && 
2298         IS_ADDRESS_OF_OP(parms->right))
2299         parms->right->left->lvalue = 1;
2300
2301     parms->opval.oprnd = 
2302         geniCodeRValue(ast2iCode (parms),FALSE);
2303    
2304     parms->type = EX_OPERAND ;
2305 }
2306
2307 /*-----------------------------------------------------------------*/
2308 /* geniCodeParms - generates parameters                            */
2309 /*-----------------------------------------------------------------*/
2310 static void geniCodeParms ( ast *parms , int *stack, link *fetype)
2311 {
2312     iCode *ic ;
2313     operand *pval ; 
2314     
2315     if ( ! parms )
2316         return ;
2317     
2318     /* if this is a param node then do the left & right */
2319     if (parms->type == EX_OP && parms->opval.op == PARAM) {
2320         geniCodeParms (parms->left, stack,fetype) ;
2321         geniCodeParms (parms->right, stack,fetype);
2322         return ;
2323     }
2324     
2325     /* get the parameter value */
2326     if (parms->type == EX_OPERAND)
2327         pval = parms->opval.oprnd ;
2328     else {
2329         /* maybe this else should go away ?? */
2330         /* hack don't like this but too lazy to think of
2331            something better */
2332         if (IS_ADDRESS_OF_OP(parms))
2333             parms->left->lvalue = 1;
2334     
2335         if (IS_CAST_OP(parms) && 
2336             IS_PTR(parms->ftype) && 
2337             IS_ADDRESS_OF_OP(parms->right))
2338             parms->right->left->lvalue = 1;
2339
2340         pval = geniCodeRValue(ast2iCode (parms),FALSE); 
2341     }
2342
2343     /* if register parm then make it a send */
2344     if (((parms->argSym && IS_REGPARM(parms->argSym->etype)) ||
2345         IS_REGPARM(parms->etype)) && 
2346         !IS_RENT(fetype)) {
2347         ic = newiCode(SEND,pval,NULL);
2348         ADDTOCHAIN(ic);
2349     } else {
2350         /* now decide whether to push or assign */
2351         if (!(options.stackAuto || IS_RENT(fetype))) { 
2352             
2353             /* assign */
2354             operand *top = operandFromSymbol(parms->argSym);
2355             geniCodeAssign(top,pval,1);
2356         }
2357         else { 
2358             link *p = operandType(pval);
2359             /* push */
2360             ic = newiCode(IPUSH,pval,NULL);
2361             ic->parmPush = 1;
2362             /* update the stack adjustment */
2363             *stack += getSize(IS_AGGREGATE(p)? aggrToPtr(p,FALSE):p);
2364             ADDTOCHAIN(ic);
2365         }
2366     }
2367     
2368 }
2369
2370 /*-----------------------------------------------------------------*/
2371 /* geniCodeCall - generates temp code for calling                  */
2372 /*-----------------------------------------------------------------*/
2373 operand *geniCodeCall (operand *left, ast *parms)
2374
2375     iCode *ic ;
2376     operand *result ;
2377     link *type, *etype;
2378     int stack = 0 ;
2379     
2380     /* take care of parameters with side-effecting
2381        function calls in them, this is required to take care 
2382        of overlaying function parameters */
2383     geniCodeSEParms ( parms );
2384
2385     /* first the parameters */
2386     geniCodeParms ( parms , &stack , getSpec(operandType(left)));
2387     
2388     /* now call : if symbol then pcall */
2389     if (IS_ITEMP(left)) 
2390         ic = newiCode(PCALL,left,NULL);
2391     else
2392         ic = newiCode(CALL,left,NULL);
2393     
2394     IC_ARGS(ic) = left->operand.symOperand->args ;
2395     type = copyLinkChain(operandType(left)->next);
2396     etype = getSpec(type);
2397     SPEC_EXTR(etype) = 0;
2398     IC_RESULT(ic) = result = newiTempOperand(type,1);
2399     
2400     ADDTOCHAIN(ic);
2401     
2402     /* stack adjustment after call */
2403     left->parmBytes = stack;
2404
2405     return result;
2406 }
2407
2408 /*-----------------------------------------------------------------*/
2409 /* geniCodeReceive - generate intermediate code for "receive"      */
2410 /*-----------------------------------------------------------------*/
2411 static void geniCodeReceive (value *args)
2412 {   
2413     /* for all arguments that are passed in registers */
2414     while (args) {
2415
2416         if (IS_REGPARM(args->etype)) {
2417             operand *opr = operandFromValue(args);
2418             operand *opl ;
2419             symbol *sym  = OP_SYMBOL(opr);
2420             iCode *ic ;
2421
2422             /* we will use it after all optimizations
2423                and before liveRange calculation */          
2424             if (!sym->addrtaken && !IS_VOLATILE(sym->etype)) {
2425
2426                 if (IN_FARSPACE(SPEC_OCLS(sym->etype)) &&
2427                    options.stackAuto == 0 &&
2428                    !IS_DS390_PORT) {
2429                 } else {
2430                     opl = newiTempOperand(args->type,0);
2431                     sym->reqv = opl ;       
2432                     sym->reqv->key = sym->key ;
2433                     OP_SYMBOL(sym->reqv)->key = sym->key;
2434                     OP_SYMBOL(sym->reqv)->isreqv = 1;
2435                     OP_SYMBOL(sym->reqv)->islocal= 0;
2436                     SPIL_LOC(sym->reqv) =  sym;
2437                 }
2438             }
2439
2440             ic = newiCode(RECEIVE,NULL,NULL);
2441             currFunc->recvSize = getSize(sym->etype);
2442             IC_RESULT(ic) = opr;
2443             ADDTOCHAIN(ic);
2444         }
2445         
2446         args = args->next;
2447     }
2448 }
2449
2450 /*-----------------------------------------------------------------*/
2451 /* geniCodeFunctionBody - create the function body                 */
2452 /*-----------------------------------------------------------------*/
2453 void geniCodeFunctionBody (ast *tree)
2454 {
2455     iCode *ic ;
2456     operand *func ;
2457     link *fetype  ;
2458     int savelineno ;
2459     
2460     /* reset the auto generation */
2461     /* numbers */
2462     iTempNum = 0 ;
2463     iTempLblNum = 0;   
2464     operandKey = 0 ;
2465     iCodeKey = 0 ;
2466     func  = ast2iCode(tree->left);
2467     fetype = getSpec(operandType(func));
2468     
2469     savelineno = lineno;
2470     lineno = OP_SYMBOL(func)->lineDef;
2471     /* create an entry label */
2472     geniCodeLabel(entryLabel);    
2473     lineno = savelineno;
2474
2475     /* create a proc icode */
2476     ic = newiCode(FUNCTION,func,NULL);
2477     /* if the function has parmas   then */
2478     /* save the parameters information    */
2479     ic->argLabel.args = tree->values.args ;
2480     ic->lineno = OP_SYMBOL(func)->lineDef;
2481
2482     ADDTOCHAIN(ic);   
2483     
2484     /* for all parameters that are passed
2485        on registers add a "receive" */
2486     geniCodeReceive( tree->values.args );
2487
2488     /* generate code for the body */
2489     ast2iCode(tree->right);
2490     
2491     /* create a label for return */
2492     geniCodeLabel(returnLabel);
2493     
2494     /* now generate the end proc */
2495     ic = newiCode(ENDFUNCTION,func,NULL);
2496     ADDTOCHAIN(ic);
2497     return ;
2498 }
2499
2500 /*-----------------------------------------------------------------*/
2501 /* geniCodeReturn - gen icode for 'return' statement               */
2502 /*-----------------------------------------------------------------*/
2503 void geniCodeReturn (operand *op)
2504 {
2505     iCode *ic;
2506     
2507     /* if the operand is present force an rvalue */
2508     if (op) 
2509         op = geniCodeRValue(op,FALSE);    
2510     
2511     ic = newiCode(RETURN,op,NULL);
2512     ADDTOCHAIN(ic);
2513 }
2514
2515 /*-----------------------------------------------------------------*/
2516 /* geniCodeIfx - generates code for extended if statement          */
2517 /*-----------------------------------------------------------------*/
2518 void geniCodeIfx (ast *tree)
2519 {
2520     iCode *ic;
2521     operand *condition = ast2iCode(tree->left);
2522     link *cetype; 
2523     
2524     /* if condition is null then exit */
2525     if (!condition)
2526         goto exit ;
2527     else
2528         condition = geniCodeRValue(condition,FALSE);
2529     
2530     cetype = getSpec(operandType(condition));
2531     /* if the condition is a literal */
2532     if (IS_LITERAL(cetype)) {
2533         if (floatFromVal(condition->operand.valOperand)) {
2534             if (tree->trueLabel)
2535                 geniCodeGoto(tree->trueLabel);
2536             else
2537                 assert(1);
2538         }
2539         else {
2540             if (tree->falseLabel)
2541                 geniCodeGoto (tree->falseLabel);
2542             else
2543                 assert(1);
2544         }
2545         goto exit;
2546     }
2547     
2548     if ( tree->trueLabel ) {
2549         ic = newiCodeCondition(condition,
2550                                tree->trueLabel,
2551                                NULL );
2552         ADDTOCHAIN(ic);
2553         
2554         if ( tree->falseLabel) 
2555             geniCodeGoto(tree->falseLabel);     
2556     }
2557     else {
2558         ic = newiCodeCondition (condition,
2559                                 NULL,
2560                                 tree->falseLabel);
2561         ADDTOCHAIN(ic);
2562     }
2563     
2564  exit:
2565     ast2iCode(tree->right);
2566 }
2567
2568 /*-----------------------------------------------------------------*/
2569 /* geniCodeJumpTable - tries to create a jump table for switch     */
2570 /*-----------------------------------------------------------------*/
2571 int geniCodeJumpTable (operand *cond, value *caseVals, ast *tree)
2572 {
2573     int min = 0 ,max = 0, t, cnt = 0;
2574     value *vch;
2575     iCode *ic;
2576     operand *boundary;
2577     symbol *falseLabel;
2578     set *labels = NULL ;
2579
2580     if (!tree || !caseVals)
2581         return 0;
2582
2583     /* the criteria for creating a jump table is */
2584     /* all integer numbers between the maximum & minimum must */
2585     /* be present , the maximum value should not exceed 255 */
2586     min = max = (int)floatFromVal(vch = caseVals);
2587     sprintf(buffer,"_case_%d_%d",
2588             tree->values.switchVals.swNum,
2589             min);
2590     addSet(&labels,newiTempLabel(buffer));
2591
2592     /* if there is only one case value then no need */
2593     if (!(vch = vch->next ))
2594         return 0;
2595
2596     while (vch) {
2597         if (((t = (int)floatFromVal(vch)) - max) != 1)
2598             return 0;
2599         sprintf(buffer,"_case_%d_%d",
2600                 tree->values.switchVals.swNum,
2601                 t);
2602         addSet(&labels,newiTempLabel(buffer));
2603         max = t;
2604         cnt++ ;
2605         vch = vch->next ;
2606     }
2607     
2608     /* if the number of case statements <= 2 then */
2609     /* it is not economical to create the jump table */
2610     /* since two compares are needed for boundary conditions */
2611     if ((! optimize.noJTabBoundary  && cnt <= 2) || max > (255/3))
2612         return 0;
2613     
2614     if ( tree->values.switchVals.swDefault )
2615         sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2616     else
2617         sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum  );
2618     
2619     falseLabel = newiTempLabel (buffer);
2620
2621     /* so we can create a jumptable */
2622     /* first we rule out the boundary conditions */
2623     /* if only optimization says so */
2624     if ( ! optimize.noJTabBoundary ) {
2625         link *cetype = getSpec(operandType(cond));
2626         /* no need to check the lower bound if
2627            the condition is unsigned & minimum value is zero */
2628         if (!( min == 0  && SPEC_USIGN(cetype))) {
2629             boundary = geniCodeLogic (cond,operandFromLit(min),'<');
2630             ic = newiCodeCondition (boundary,falseLabel,NULL);
2631             ADDTOCHAIN(ic);
2632         }
2633
2634         /* now for upper bounds */
2635         boundary = geniCodeLogic(cond,operandFromLit(max),'>');
2636         ic = newiCodeCondition (boundary,falseLabel,NULL);
2637         ADDTOCHAIN(ic);
2638     }
2639
2640     /* if the min is not zero then we no make it zero */
2641     if (min) {
2642         cond = geniCodeSubtract(cond,operandFromLit(min));
2643         setOperandType(cond, UCHARTYPE);
2644     }
2645
2646     /* now create the jumptable */
2647     ic = newiCode(JUMPTABLE,NULL,NULL);
2648     IC_JTCOND(ic) = cond;
2649     IC_JTLABELS(ic) = labels;
2650     ADDTOCHAIN(ic);
2651     return 1;       
2652 }
2653
2654 /*-----------------------------------------------------------------*/
2655 /* geniCodeSwitch - changes a switch to a if statement             */
2656 /*-----------------------------------------------------------------*/
2657 void geniCodeSwitch (ast *tree)
2658 {
2659     iCode *ic ;
2660     operand *cond = geniCodeRValue(ast2iCode (tree->left),FALSE);
2661     value *caseVals = tree->values.switchVals.swVals ;
2662     symbol *trueLabel , *falseLabel;
2663     
2664     /* if we can make this a jump table */
2665     if ( geniCodeJumpTable (cond,caseVals,tree) )
2666         goto jumpTable ; /* no need for the comparison */
2667
2668     /* for the cases defined do */
2669     while (caseVals) {
2670         
2671         operand *compare = geniCodeLogic (cond,
2672                                           operandFromValue(caseVals),
2673                                           EQ_OP);
2674         
2675         sprintf(buffer,"_case_%d_%d",
2676                 tree->values.switchVals.swNum,
2677                 (int) floatFromVal(caseVals));
2678         trueLabel = newiTempLabel(buffer);
2679         
2680         ic = newiCodeCondition(compare,trueLabel,NULL);
2681         ADDTOCHAIN(ic);
2682         caseVals = caseVals->next;
2683     }
2684
2685
2686     
2687     /* if default is present then goto break else break */
2688     if ( tree->values.switchVals.swDefault )
2689         sprintf (buffer,"_default_%d",tree->values.switchVals.swNum);
2690     else
2691         sprintf (buffer,"_swBrk_%d",tree->values.switchVals.swNum  );
2692     
2693     falseLabel = newiTempLabel (buffer);
2694     geniCodeGoto(falseLabel);
2695  
2696  jumpTable:   
2697     ast2iCode(tree->right);
2698
2699
2700 /*-----------------------------------------------------------------*/
2701 /* geniCodeInline - intermediate code for inline assembler         */
2702 /*-----------------------------------------------------------------*/
2703 static void geniCodeInline (ast *tree)
2704 {
2705     iCode *ic;
2706
2707     ic = newiCode(INLINEASM,NULL,NULL);
2708     IC_INLINE(ic) = tree->values.inlineasm;
2709     ADDTOCHAIN(ic);
2710 }
2711
2712 /*-----------------------------------------------------------------*/
2713 /* ast2iCode - creates an icodeList from an ast                    */
2714 /*-----------------------------------------------------------------*/
2715 operand *ast2iCode (ast *tree)
2716 {
2717     operand *left = NULL;
2718     operand *right= NULL;
2719     
2720     if (!tree)
2721         return NULL ;
2722     
2723     /* set the global variables for filename & line number */
2724     if ( tree->filename )
2725         filename =  tree->filename ;
2726     if ( tree->lineno)
2727         lineno   = tree->lineno ;
2728     if (tree->block)
2729         block = tree->block ;
2730     if (tree->level)
2731         scopeLevel = tree->level;
2732     
2733     if (tree->type == EX_VALUE )
2734         return operandFromValue(tree->opval.val);
2735     
2736     if (tree->type == EX_LINK )
2737         return operandFromLink (tree->opval.lnk);
2738     
2739     /* if we find a nullop */
2740     if (tree->type == EX_OP && 
2741         ( tree->opval.op == NULLOP || 
2742           tree->opval.op == BLOCK )) {
2743         ast2iCode (tree->left);
2744         ast2iCode (tree->right);
2745         return NULL ;
2746     }
2747     
2748     /* special cases for not evaluating */
2749     if ( tree->opval.op != ':'   && 
2750          tree->opval.op != '?'   &&
2751          tree->opval.op != CALL  && 
2752          tree->opval.op != IFX   &&
2753          tree->opval.op != LABEL &&
2754          tree->opval.op != GOTO  &&     
2755          tree->opval.op != SWITCH &&
2756          tree->opval.op != FUNCTION &&
2757          tree->opval.op != INLINEASM ) {
2758
2759         if (IS_ASSIGN_OP(tree->opval.op) || 
2760             IS_DEREF_OP(tree)            || 
2761             (tree->opval.op == '&' && !tree->right) ||
2762             tree->opval.op == PTR_OP) {
2763             lvaluereq++;
2764             if ((IS_ARRAY_OP(tree->left) && IS_ARRAY_OP(tree->left->left)) ||
2765                 (IS_DEREF_OP(tree) && IS_ARRAY_OP(tree->left)))
2766             {
2767                 int olvr = lvaluereq ;
2768                 lvaluereq = 0;
2769                 left = operandFromAst(tree->left);
2770                 lvaluereq = olvr - 1;
2771             } else {
2772                 left = operandFromAst(tree->left);
2773                 lvaluereq--;
2774             }
2775             if (IS_DEREF_OP(tree) && IS_DEREF_OP(tree->left))
2776                     left = geniCodeRValue(left,TRUE);
2777         } else {
2778             left =  operandFromAst(tree->left);
2779         }
2780         if (tree->opval.op == INC_OP || 
2781             tree->opval.op == DEC_OP) {
2782             lvaluereq++;
2783             right= operandFromAst(tree->right);
2784             lvaluereq--;
2785         } else {
2786             right= operandFromAst(tree->right);
2787         }
2788     }
2789     
2790     /* now depending on the type of operand */
2791     /* this will be a biggy                 */
2792     switch (tree->opval.op) {
2793         
2794     case '[' :    /* array operation */
2795         {
2796             link *ltype = operandType(left);
2797             left= geniCodeRValue (left,IS_PTR(ltype->next) ? TRUE : FALSE);
2798             right=geniCodeRValue (right,TRUE);             
2799         }
2800         
2801         return geniCodeArray (left,right);
2802         
2803     case '.' :   /* structure dereference */
2804         if (IS_PTR(operandType(left)))
2805             left = geniCodeRValue(left,TRUE);
2806         else
2807             left = geniCodeRValue(left,FALSE);            
2808         
2809         return geniCodeStruct (left,right,tree->lvalue);
2810         
2811     case PTR_OP: /* structure pointer dereference */
2812         {
2813             link *pType;
2814             pType = operandType(left);
2815             left = geniCodeRValue(left,TRUE);
2816             
2817             setOClass (pType,getSpec(operandType(left)));
2818         }              
2819         
2820         return geniCodeStruct (left, right,tree->lvalue);
2821         
2822     case INC_OP: /* increment operator */
2823         if ( left )
2824             return geniCodePostInc (left);
2825         else
2826             return geniCodePreInc (right);
2827         
2828     case DEC_OP: /* decrement operator */
2829         if ( left )
2830             return geniCodePostDec (left);
2831         else
2832             return geniCodePreDec (right);
2833         
2834     case '&' : /* bitwise and or address of operator */
2835         if ( right ) { /* this is a bitwise operator   */
2836             left= geniCodeRValue(left,FALSE);
2837             right= geniCodeRValue(right,FALSE);     
2838             return geniCodeBitwise (left,right,BITWISEAND,tree->ftype);
2839         } else
2840             return geniCodeAddressOf (left);
2841         
2842     case '|': /* bitwise or & xor */
2843     case '^':
2844         return geniCodeBitwise (geniCodeRValue(left,FALSE),
2845                                 geniCodeRValue(right,FALSE),
2846                                 tree->opval.op,
2847                                 tree->ftype);
2848         
2849     case '/':
2850         return geniCodeDivision (geniCodeRValue(left,FALSE),
2851                                  geniCodeRValue(right,FALSE));
2852         
2853     case '%' :
2854         return geniCodeModulus (geniCodeRValue(left,FALSE),
2855                                 geniCodeRValue(right,FALSE));
2856     case '*':
2857         if ( right ) 
2858             return geniCodeMultiply (geniCodeRValue(left,FALSE),
2859                                      geniCodeRValue(right,FALSE));
2860         else        
2861             return geniCodeDerefPtr (geniCodeRValue(left,FALSE));
2862         
2863     case '-' :
2864         if ( right ) 
2865             return geniCodeSubtract (geniCodeRValue(left,FALSE),
2866                                      geniCodeRValue(right,FALSE));
2867         else
2868             return geniCodeUnaryMinus (geniCodeRValue(left,FALSE));
2869         
2870     case '+' :
2871         if ( right ) 
2872             return geniCodeAdd (geniCodeRValue(left,FALSE),
2873                                 geniCodeRValue(right,FALSE));
2874         else
2875             return geniCodeRValue(left,FALSE) ; /* unary '+' has no meaning */
2876         
2877     case LEFT_OP:
2878         return geniCodeLeftShift (geniCodeRValue(left,FALSE),
2879                                   geniCodeRValue(right,FALSE));
2880         
2881     case RIGHT_OP:
2882         return geniCodeRightShift (geniCodeRValue(left,FALSE),
2883                                    geniCodeRValue(right,FALSE));
2884     case CAST:
2885         return geniCodeCast (operandType(left),
2886                              geniCodeRValue(right,FALSE),FALSE);
2887         
2888     case '~' :
2889     case '!' :
2890     case RRC:
2891     case RLC:   
2892         return geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
2893         
2894     case GETHBIT:
2895         {
2896             operand *op = geniCodeUnary (geniCodeRValue(left,FALSE),tree->opval.op);
2897             setOperandType(op, UCHARTYPE);
2898             return op;
2899         }
2900     case '>' :
2901     case '<' :
2902     case LE_OP:
2903     case GE_OP:
2904     case EQ_OP:
2905     case NE_OP:
2906     case AND_OP:
2907     case OR_OP:
2908         return geniCodeLogic (geniCodeRValue(left,FALSE),
2909                               geniCodeRValue(right,FALSE),
2910                               tree->opval.op);
2911     case '?' : 
2912         return geniCodeConditional (tree); 
2913         
2914     case SIZEOF:
2915         return operandFromLit(getSize(tree->right->ftype));
2916         
2917     case '='        :
2918         {
2919             link *rtype = operandType(right);
2920             link *ltype = operandType(left);
2921             if (IS_PTR(rtype) && IS_ITEMP(right) 
2922                 && right->isaddr && checkType(rtype->next,ltype)==1)
2923                 right =  geniCodeRValue(right,TRUE);
2924             else
2925                 right = geniCodeRValue(right,FALSE);
2926
2927             geniCodeAssign (left,right,0);
2928             return right ;
2929         }              
2930     case MUL_ASSIGN:
2931         return 
2932             geniCodeAssign(left,
2933                            geniCodeMultiply(geniCodeRValue (operandFromOperand(left),
2934                                                             FALSE),
2935                                             geniCodeRValue(right,FALSE)),0);
2936                                                 
2937     case DIV_ASSIGN:
2938         return 
2939             geniCodeAssign(left,
2940                            geniCodeDivision(geniCodeRValue(operandFromOperand(left),
2941                                                            FALSE),
2942                                             geniCodeRValue(right,FALSE)),0);
2943     case MOD_ASSIGN:
2944         return 
2945             geniCodeAssign(left,
2946                            geniCodeModulus(geniCodeRValue(operandFromOperand(left),
2947                                                           FALSE),
2948                                            geniCodeRValue(right,FALSE)),0);
2949     case ADD_ASSIGN: 
2950         {
2951             link *rtype = operandType(right);
2952             link *ltype = operandType(left);
2953             if (IS_PTR(rtype) && IS_ITEMP(right) 
2954                 && right->isaddr && checkType(rtype->next,ltype)==1)
2955                 right =  geniCodeRValue(right,TRUE);
2956             else
2957                 right = geniCodeRValue(right,FALSE);
2958
2959            
2960             return geniCodeAssign(left,
2961                                   geniCodeAdd (geniCodeRValue(operandFromOperand(left),
2962                                                               FALSE),
2963                                                right),0);
2964         }
2965     case SUB_ASSIGN:
2966         {
2967             link *rtype = operandType(right);
2968             link *ltype = operandType(left);
2969             if (IS_PTR(rtype) && IS_ITEMP(right) 
2970                 && right->isaddr && checkType(rtype->next,ltype)==1) {
2971                 right =  geniCodeRValue(right,TRUE);
2972             }
2973             else {
2974                 right = geniCodeRValue(right,FALSE);
2975             }
2976             return 
2977                 geniCodeAssign (left,
2978                                 geniCodeSubtract(geniCodeRValue(operandFromOperand(left),
2979                                                                 FALSE),
2980                                                  right),0);
2981         }
2982     case LEFT_ASSIGN:
2983         return 
2984             geniCodeAssign (left,
2985                             geniCodeLeftShift(geniCodeRValue(operandFromOperand(left)
2986                                                              ,FALSE),
2987                                               geniCodeRValue(right,FALSE)),0);
2988     case RIGHT_ASSIGN:
2989         return 
2990             geniCodeAssign(left,
2991                            geniCodeRightShift(geniCodeRValue(operandFromOperand(left)
2992                                                              ,FALSE),
2993                                               geniCodeRValue(right,FALSE)),0);
2994     case AND_ASSIGN:
2995         return 
2996             geniCodeAssign (left,
2997                             geniCodeBitwise(geniCodeRValue(operandFromOperand(left),
2998                                                            FALSE),
2999                                             geniCodeRValue(right,FALSE),
3000                                             BITWISEAND,
3001                                             operandType(left)),0);
3002     case XOR_ASSIGN:
3003         return 
3004             geniCodeAssign (left,
3005                             geniCodeBitwise (geniCodeRValue(operandFromOperand(left),
3006                                                             FALSE),
3007                                              geniCodeRValue(right,FALSE),
3008                                              '^',
3009                                              operandType(left)),0);
3010     case OR_ASSIGN:
3011         return 
3012             geniCodeAssign (left,
3013                             geniCodeBitwise (geniCodeRValue(operandFromOperand(left)
3014                                                             ,FALSE),
3015                                              geniCodeRValue(right,FALSE),
3016                                              '|',
3017                                              operandType(left)),0);
3018     case ',' :
3019         return geniCodeRValue(right,FALSE);
3020         
3021     case CALL:
3022         return geniCodeCall (ast2iCode(tree->left),
3023                              tree->right);
3024     case LABEL:
3025         geniCodeLabel(ast2iCode(tree->left)->operand.symOperand);
3026         return ast2iCode (tree->right);
3027         
3028     case GOTO:
3029         geniCodeGoto (ast2iCode(tree->left)->operand.symOperand);
3030         return ast2iCode (tree->right);
3031         
3032     case FUNCTION:
3033         geniCodeFunctionBody ( tree );
3034         return NULL ;
3035         
3036     case RETURN:
3037         geniCodeReturn (right);
3038         return NULL ;
3039         
3040     case IFX:
3041         geniCodeIfx (tree);
3042         return NULL ;
3043         
3044     case SWITCH:
3045         geniCodeSwitch (tree);
3046         return NULL;
3047
3048     case INLINEASM:
3049         geniCodeInline (tree);
3050         return NULL ;
3051     }
3052     
3053     return NULL;
3054 }
3055
3056 /*-----------------------------------------------------------------*/
3057 /* reverseICChain - gets from the list and creates a linkedlist    */
3058 /*-----------------------------------------------------------------*/
3059 iCode *reverseiCChain ()
3060 {
3061     iCode *loop = NULL ;
3062     iCode *prev = NULL ;
3063     
3064     while ((loop = getSet(&iCodeChain))) {
3065         loop->next = prev ;
3066         if ( prev )
3067             prev->prev = loop; 
3068         prev = loop ;
3069     }
3070     
3071     return prev;
3072 }
3073
3074
3075 /*-----------------------------------------------------------------*/
3076 /* iCodeFromAst - given an ast will convert it to iCode            */
3077 /*-----------------------------------------------------------------*/
3078 iCode *iCodeFromAst ( ast *tree )
3079 {
3080     returnLabel = newiTempLabel("_return");
3081     entryLabel  = newiTempLabel("_entry") ;
3082     ast2iCode (tree);
3083     return reverseiCChain ();
3084 }
3085