1 /*-------------------------------------------------------------------------
3 SDCCicode.h - intermediate code generation etc.
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
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
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.
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.
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 -------------------------------------------------------------------------*/
30 extern symbol *returnLabel;
31 extern symbol *entryLabel;
33 extern int operandKey;
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)
55 #define ADDTOCHAIN(x) addSetHead(&iCodeChain,x)
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
73 /* typedef for operand */
74 typedef struct operand
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 */
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 */
94 bitVect *usesDefs; /* which definitions are used by this */
95 struct asmop *aop; /* asm op for this operand */
99 extern operand *validateOpType(operand *op,
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
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
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 */
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 */
156 operand *left; /* left if any */
157 operand *right; /* right if any */
158 operand *result; /* result of this op */
164 operand *condition; /* if this is a conditional */
165 symbol *trueLabel; /* true for conditional */
166 symbol *falseLabel; /* false for conditional */
172 operand *condition; /* condition for the jump */
173 set *labels; /* ordered set of labels */
180 symbol *label; /* for a goto statement */
182 char *inlineAsm; /* pointer to inline assembler code */
183 literalList *arrayInitList; /* point to array initializer list. */
185 int lineno; /* file & lineno for debug information */
188 int parmBytes; /* if call/pcall, count of parameter bytes
190 int argreg; /* argument regno for SEND/RECEIVE */
191 int eBBlockNum; /* belongs to which eBBlock */
192 char riu; /* after ralloc, the registers in use */
196 /* various functions associated to iCode */
197 typedef struct icodeFuncTable
201 void (*iCodePrint) (FILE *, iCode *, char *);
202 iCode *(*iCodeCopy) (iCode *);
207 #define SKIP_IC2(x) (x->op == GOTO || \
209 x->op == FUNCTION || \
210 x->op == INLINEASM || \
211 x->op == ENDFUNCTION )
213 #define SKIP_IC1(x) (x->op == CALL || \
216 #define SKIP_IC(x) (x->op == PCALL || \
219 x->op == JUMPTABLE || \
220 x->op == RECEIVE || \
221 x->op == ARRAYINIT || \
225 #define SKIP_IC3(x) (SKIP_IC2(x) || \
228 #define IS_CONDITIONAL(x) (x->op == EQ_OP || \
235 #define IS_TRUE_SYMOP(op) (op && IS_SYMOP(op) && !IS_ITEMP(op))
237 #define POINTER_SET(ic) ( ic && ic->op == '=' \
238 && IS_ITEMP(IC_RESULT(ic)) \
239 && IC_RESULT(ic)->isaddr )
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 )
245 #define IS_ARITHMETIC_OP(x) (x && (x->op == '+' || \
250 #define IS_BITWISE_OP(x) (x && (x->op == BITWISEAND || \
254 #define ASSIGNMENT(ic) ( ic && ic->op == '=')
256 #define ASSIGN_SYM_TO_ITEMP(ic) (ic && ic->op == '=' && \
257 IS_TRUE_SYMOP(IC_RIGHT(ic)) && \
258 IS_ITEMP(IC_RESULT(ic)))
260 #define ASSIGN_ITEMP_TO_SYM(ic) (ic && ic->op == '=' && \
261 IS_TRUE_SYMOP(IC_RESULT(ic)) && \
262 IS_ITEMP(IC_RIGHT(ic)))
264 #define ASSIGN_ITEMP_TO_ITEMP(ic) (ic && ic->op == '=' &&\
266 IS_ITEMP(IC_RIGHT(ic)) &&\
267 IS_ITEMP(IC_RESULT(ic)))
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)))
274 #define ASSIGNMENT_TO_SELF(ic) (!POINTER_SET(ic) && !POINTER_GET(ic) && \
275 ic->op == '=' && IC_RESULT(ic)->key == IC_RIGHT(ic)->key )
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))
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 *);
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 sym_link *aggrToPtr (sym_link *, bool);
315 int piCode (void *, FILE *);
316 int printOperand (operand *, FILE *);
317 void setOperandType (operand *, sym_link *);
318 bool isOperandInFarSpace (operand *);
319 bool isOperandInDirSpace (operand *);
320 bool isOperandInCodeSpace (operand *);
321 operand *opFromOpWithDU (operand *, bitVect *, bitVect *);
322 iCode *copyiCode (iCode *);
323 operand *newiTempFromOp (operand *);
324 iCode *getBuiltinParms (iCode *,int *, operand **);
325 /*-----------------------------------------------------------------*/
326 /* declaration of exported variables */
327 /*-----------------------------------------------------------------*/
328 extern char *filename;