Initial revision
[fw/sdcc] / src / SDCCicode.h
1 /*-------------------------------------------------------------------------
2
3   SDCCicode.h - 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 #include "SDCCbitv.h"
25 #include "SDCCset.h"
26
27 #ifndef SDCCICODE_H
28 #define SDCCICODE_H 1
29
30 extern symbol *returnLabel ;
31 extern symbol *entryLabel  ;
32 extern int iCodeKey ;
33 extern int operandKey ;
34
35 enum {
36         CONDITIONAL = 0 ,
37         EXPRESSION      ,
38         STATEMENT       ,
39         LEAF            };
40 enum optype {
41   SYMBOL    =1,
42   VALUE       ,
43   TYPE      };
44
45 #define IS_SYMOP(op) (op && op->type == SYMBOL)
46 #define ADDTOCHAIN(x) addSetHead(&iCodeChain,x)
47
48 #define LRFTYPE       link *ltype = operandType(left), \
49                            *rtype = operandType(right) ;
50 #define LRETYPE       link *letype= getSpec(ltype)   , \
51                            *retype= getSpec(rtype);
52 #define LRTYPE        LRFTYPE LRETYPE
53 #define IS_ITEMP(op)       (IS_SYMOP(op) && op->operand.symOperand->isitmp == 1)
54 #define IS_PARM(op)        (IS_SYMOP(op) && op->operand.symOperand->_isparm)
55 #define IS_ITEMPLBL(op)    (IS_ITEMP(op) && op->operand.symOperand->isilbl == 1);
56 #define IS_OP_VOLATILE(op) (IS_SYMOP(op) && op->isvolatile)
57 #define IS_OP_LITERAL(op)  (op && op->isLiteral)
58 #define IS_OP_GLOBAL(op)   (IS_SYMOP(op) && op->isGlobal)
59 #define IS_OP_POINTER(op)  (IS_SYMOP(op) && op->isPtr)
60 #define IS_OP_PARM(op)     (IS_SYMOP(op) && op->isParm)
61 #define OP_SYMBOL(op)      op->operand.symOperand
62 #define OP_SYM_TYPE(op)    op->operand.symOperand->type
63 #define OP_SYM_ETYPE(op)   op->operand.symOperand->etype
64 #define SPIL_LOC(op)       op->operand.symOperand->usl.spillLoc
65 #define OP_LIVEFROM(op)    op->operand.symOperand->liveFrom
66 #define OP_LIVETO(op)      op->operand.symOperand->liveTo
67 #define OP_REQV(op)        op->operand.symOperand->reqv
68
69 /* typedef for operand */
70 typedef struct operand {
71     unsigned int  type: 6 ;      /* type of operand */
72     unsigned int  isaddr : 1;    /* is an address   */
73     unsigned int  isvolatile: 1; /* is a volatile operand */
74     unsigned int  isGlobal :1 ;  /* is a global operand */
75     unsigned int  isPtr    :1 ;  /* is assigned a pointer */
76     unsigned int  isGptr   :1 ;  /* is a generic pointer  */
77     unsigned int  isParm   :1 ;  /* is a parameter        */
78     unsigned int  isLiteral:1 ;  /* operand is literal    */
79     unsigned int  noSpilLoc:1 ;  /* cannot be assigned a spil location */
80     
81     unsigned key ;
82     int      parmBytes;
83     union {
84         struct symbol *symOperand ; /* operand is of type symbol */
85         struct value  *valOperand ; /* operand is of type value  */
86         struct link   *typeOperand; /* operand is of type typechain */
87     } operand ;
88     
89     bitVect *usesDefs;             /* which definitions are used by this */
90     struct  asmop *aop      ;      /* asm op for this operand */
91 } operand ;
92
93 /* definition for intermediate code */ 
94 #define IC_RESULT(x) x->ulrrcnd.lrr.result
95 #define IC_LEFT(x)   x->ulrrcnd.lrr.left
96 #define IC_RIGHT(x)  x->ulrrcnd.lrr.right
97 #define IC_COND(x)   x->ulrrcnd.cnd.condition
98 #define IC_TRUE(x)   x->ulrrcnd.cnd.trueLabel
99 #define IC_FALSE(x)  x->ulrrcnd.cnd.falseLabel
100 #define IC_LABEL(x)  x->argLabel.label
101 #define IC_ARGS(x)   x->argLabel.args
102 #define IC_JTCOND(x) x->ulrrcnd.jmpTab.condition
103 #define IC_JTLABELS(x) x->ulrrcnd.jmpTab.labels
104 #define IC_INLINE(x) x->inlineAsm
105
106 typedef struct iCode 
107 {
108     unsigned int op ;              /* operation defined */
109     int key ;                      /* running key for this iCode */
110     int seq ;                      /* sequence number within routine */
111     short depth ;                  /* loop depth of this iCode */
112     short level ;                  /* scope level */
113     short block ;                  /* sequential block number */
114     unsigned nosupdate:1;          /* don't update spillocation with this */
115     unsigned generated:1;          /* code generated for this one */   
116     unsigned parmPush :1;          /* parameter push Vs spill push */
117     unsigned supportRtn:1;         /* will cause a call to a support routine */
118     unsigned regsSaved:1 ;         /* registers have been saved */
119     unsigned bankSaved:1 ;         /* register bank has been saved */
120     
121     struct iCode *next ;           /* next in chain */
122     struct iCode *prev ;           /* previous in chain */
123     set          *movedFrom;       /* if this iCode gets moved to another block */
124     bitVect *rlive ;               /* ranges that are live at this point */
125     int    defKey  ;               /* key for the operand being defined  */
126     bitVect *uses  ;               /* vector of key of used symbols      */
127     bitVect *rUsed ;               /* registers used by this instruction */
128     bitVect *rMask ;               /* registers in use during this instruction */
129     union {
130         struct {
131             operand *left      ;           /* left if any   */
132             operand *right     ;           /* right if any  */
133             operand *result    ;           /* result of this op */
134         } lrr ;
135
136         struct {
137             operand *condition ;           /* if this is a conditional */
138             symbol  *trueLabel ;           /* true for conditional     */
139             symbol  *falseLabel;           /* false for conditional    */
140         } cnd;
141
142         struct {
143             operand *condition ;           /* condition for the jump */
144             set     *labels    ;           /* ordered set of labels  */
145         } jmpTab ;
146
147     } ulrrcnd;
148
149     union {
150         symbol  *label ;           /* for a goto statement     */
151         value   *args  ;
152     } argLabel ;
153     
154     char        *inlineAsm ;           /* pointer to inline assembler code */
155
156     int     lineno      ;           /* file & lineno for debug information */
157     char   *filename    ;         
158 } iCode ;
159
160 /* various functions associated to iCode */
161 typedef struct icodeFuncTable 
162 {
163     int icode ;
164     char *printName ;
165     void (*iCodePrint)(FILE *,iCode *,char *) ;
166     void (*iCodeGen)() ;
167 } iCodeTable ;
168
169 /* useful macros */
170 #define SKIP_IC2(x)  (x->op == GOTO     ||     \
171                       x->op == LABEL    ||     \
172                       x->op == FUNCTION ||     \
173                       x->op == INLINEASM ||    \
174                       x->op == ENDFUNCTION   )
175
176 #define SKIP_IC1(x)  (x->op == CALL     ||     \
177                       SKIP_IC2(x) )
178
179 #define SKIP_IC(x)   (x->op == PCALL    ||     \
180                       x->op == IPUSH    ||     \
181                       x->op == IPOP     ||     \
182                       x->op == JUMPTABLE ||    \
183                       x->op == RECEIVE  ||     \
184                       SKIP_IC1(x)||  \
185                       x->op == SEND         ) 
186
187 #define IS_CONDITIONAL(x) (x->op == EQ_OP || \
188                            x->op == '<'   || \
189                            x->op == '>'   || \
190                            x->op == LE_OP || \
191                            x->op == GE_OP || \
192                            x->op == NE_OP )
193
194 #define IS_TRUE_SYMOP(op) (op && IS_SYMOP(op) && !IS_ITEMP(op))
195
196 #define POINTER_SET(ic) ( ic && ic->op == '='           \
197                              && IS_ITEMP(IC_RESULT(ic)) \
198                              && IC_RESULT(ic)->isaddr )
199
200 #define POINTER_GET(ic) ( ic && ic->op == GET_VALUE_AT_ADDRESS  \
201                              &&  (IS_ITEMP(IC_LEFT(ic)) || IS_OP_LITERAL(IC_LEFT(ic)))\
202                              &&  IC_LEFT(ic)->isaddr )
203
204 #define IS_ARITHMETIC_OP(x) (x && (x->op == '+' || \
205                                    x->op == '-' || \
206                                    x->op == '/' || \
207                                    x->op == '*' || \
208                                    x->op == '%'))
209 #define IS_BITWISE_OP(x) (x && (x->op == BITWISEAND || \
210                                 x->op == '|'        || \
211                                 x->op == '^'))
212
213 #define ASSIGNMENT(ic) ( ic && ic->op == '=')
214
215 #define ASSIGN_SYM_TO_ITEMP(ic) (ic && ic->op == '=' && \
216                              IS_TRUE_SYMOP(IC_RIGHT(ic)) && \
217                              IS_ITEMP(IC_RESULT(ic)))
218
219 #define ASSIGN_ITEMP_TO_SYM(ic) (ic && ic->op == '=' && \
220                              IS_TRUE_SYMOP(IC_RESULT(ic)) && \
221                              IS_ITEMP(IC_RIGHT(ic)))
222
223 #define ASSIGN_ITEMP_TO_ITEMP(ic) (ic && ic->op == '=' &&\
224                                    !POINTER_SET(ic)    &&\
225                                    IS_ITEMP(IC_RIGHT(ic)) &&\
226                                    IS_ITEMP(IC_RESULT(ic)))
227
228 #define ADD_SUBTRACT_ITEMP(ic) (ic && (ic->op == '+' || ic->op == '-') && \
229                                 IS_ITEMP(IC_RESULT(ic)) && \
230                                 ( ( IS_ITEMP(IC_LEFT(ic)) ) ||  ( IS_SYMOP(IC_LEFT(ic)) ) ) && \
231                                   IS_OP_LITERAL(IC_RIGHT(ic)))
232
233 #define ASSIGNMENT_TO_SELF(ic) (!POINTER_SET(ic) && !POINTER_GET(ic) && \
234                                 ic->op == '=' && IC_RESULT(ic)->key == IC_RIGHT(ic)->key )
235
236 #define SET_ISADDR(op,v) {op = operandFromOperand(op); op->isaddr = v;}
237 #define SET_RESULT_RIGHT(ic) {SET_ISADDR(IC_RIGHT(ic),0); SET_ISADDR(IC_RESULT(ic),0);}
238
239 #define OP_DEFS(op) op->operand.symOperand->defs
240 #define OP_USES(op) op->operand.symOperand->uses
241 /*-----------------------------------------------------------------*/
242 /* forward references for functions                                */
243 /*-----------------------------------------------------------------*/
244 iCode   *reverseiCChain     (      );
245 int      isOperandVolatile  (operand *,bool);
246 int      isOperandGlobal    (operand *);
247 void     printiCChain    ( iCode * , FILE *);
248 operand *ast2iCode          ( ast *);
249 operand *geniCodeCast       ( link *, operand *,bool);
250 operand *geniCodePtrPtrSubtract (operand *, operand *);
251 void     initiCode          ();
252 iCode   *iCodeFromAst   ( ast * );
253 int      isiCodeEqual   ( iCode *,iCode *) ;
254 int      isOperandEqual ( operand *, operand *);
255 iCodeTable *getTableEntry (int  );
256 int      isOperandLiteral (operand *);
257 operand *operandOperation (operand *,operand *,int,link *);
258 double   operandLitValue ( operand * );
259 operand *operandFromLit (float);
260 operand *operandFromOperand(operand *);
261 int      isParameterToCall (value *,operand *);
262 iCode   *newiCodeLabelGoto (int , symbol *);
263 symbol  *newiTemp(char *);
264 symbol  *newiTempLabel (char *);
265 symbol  *newiTempPreheaderLabel ();
266 iCode   *newiCode (int, operand *, operand *);
267 link    *operandType(operand *);
268 operand *operandFromValue (value *);
269 operand *operandFromSymbol(symbol *);
270 link    *aggrToPtr ( link *, bool);
271 int      piCode (void *, FILE * );
272 int      printOperand (operand *,FILE *);
273 void     setOperandType (operand *, link *);
274 bool     isOperandInFarSpace (operand *);
275 operand *opFromOpWithDU (operand *,bitVect *,bitVect *);
276
277 #endif