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