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