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