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