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