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 ADDTOCHAIN(x) addSetHead(&iCodeChain,x)
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 OP_VALUE(op) op->operand.valOperand
72 #define SPIL_LOC(op) op->operand.symOperand->usl.spillLoc
73 #define OP_LIVEFROM(op) op->operand.symOperand->liveFrom
74 #define OP_LIVETO(op) op->operand.symOperand->liveTo
75 #define OP_REQV(op) op->operand.symOperand->reqv
76 #define OP_ISLIVE_FCALL(op) (IS_ITEMP(op) && OP_SYMBOL(op)->isLiveFcall)
78 /* typedef for operand */
79 typedef struct operand
81 OPTYPE type; /* type of operand */
82 unsigned int isaddr:1; /* is an address */
83 unsigned int isvolatile:1; /* is a volatile operand */
84 unsigned int isGlobal:1; /* is a global operand */
85 unsigned int isPtr:1; /* is assigned a pointer */
86 unsigned int isGptr:1; /* is a generic pointer */
87 unsigned int isParm:1; /* is a parameter */
88 unsigned int isLiteral:1; /* operand is literal */
93 struct symbol *symOperand; /* operand is of type symbol */
94 struct value *valOperand; /* operand is of type value */
95 struct sym_link *typeOperand; /* operand is of type typechain */
99 bitVect *usesDefs; /* which definitions are used by this */
100 struct asmop *aop; /* asm op for this operand */
104 /* definition for intermediate code */
105 #define IC_RESULT(x) (x)->ulrrcnd.lrr.result
106 #define IC_LEFT(x) (x)->ulrrcnd.lrr.left
107 #define IC_RIGHT(x) (x)->ulrrcnd.lrr.right
108 #define IC_COND(x) (x)->ulrrcnd.cnd.condition
109 #define IC_TRUE(x) (x)->ulrrcnd.cnd.trueLabel
110 #define IC_FALSE(x) (x)->ulrrcnd.cnd.falseLabel
111 #define IC_LABEL(x) (x)->argLabel.label
112 #define IC_ARGS(x) (x)->argLabel.args
113 #define IC_JTCOND(x) (x)->ulrrcnd.jmpTab.condition
114 #define IC_JTLABELS(x) (x)->ulrrcnd.jmpTab.labels
115 #define IC_INLINE(x) (x)->inlineAsm
116 #define IC_ARRAYILIST(x) (x)->arrayInitList
120 unsigned int op; /* operation defined */
121 int key; /* running key for this iCode */
122 int seq; /* sequence number within routine */
123 short depth; /* loop depth of this iCode */
124 short level; /* scope level */
125 short block; /* sequential block number */
126 unsigned nosupdate:1; /* don't update spillocation with this */
127 unsigned generated:1; /* code generated for this one */
128 unsigned parmPush:1; /* parameter push Vs spill push */
129 unsigned supportRtn:1; /* will cause a call to a support routine */
130 unsigned regsSaved:1; /* registers have been saved */
131 unsigned bankSaved:1; /* register bank has been saved */
133 struct iCode *next; /* next in chain */
134 struct iCode *prev; /* previous in chain */
135 set *movedFrom; /* if this iCode gets moved to another block */
136 bitVect *rlive; /* ranges that are live at this point */
137 int defKey; /* key for the operand being defined */
138 bitVect *uses; /* vector of key of used symbols */
139 bitVect *rUsed; /* registers used by this instruction */
140 bitVect *rMask; /* registers in use during this instruction */
145 operand *left; /* left if any */
146 operand *right; /* right if any */
147 operand *result; /* result of this op */
153 operand *condition; /* if this is a conditional */
154 symbol *trueLabel; /* true for conditional */
155 symbol *falseLabel; /* false for conditional */
161 operand *condition; /* condition for the jump */
162 set *labels; /* ordered set of labels */
171 symbol *label; /* for a goto statement */
172 value *args; /* for a function */
176 char *inlineAsm; /* pointer to inline assembler code */
177 literalList *arrayInitList; /* point to array initializer list. */
179 int lineno; /* file & lineno for debug information */
182 int parmBytes; /* if call/pcall, count of parameter bytes
187 /* various functions associated to iCode */
188 typedef struct icodeFuncTable
192 void (*iCodePrint) (FILE *, iCode *, char *);
193 iCode *(*iCodeCopy) (iCode *);
198 #define SKIP_IC2(x) (x->op == GOTO || \
200 x->op == FUNCTION || \
201 x->op == INLINEASM || \
202 x->op == ENDFUNCTION )
204 #define SKIP_IC1(x) (x->op == CALL || \
207 #define SKIP_IC(x) (x->op == PCALL || \
210 x->op == JUMPTABLE || \
211 x->op == RECEIVE || \
212 x->op == ARRAYINIT || \
216 #define IS_CONDITIONAL(x) (x->op == EQ_OP || \
223 #define IS_TRUE_SYMOP(op) (op && IS_SYMOP(op) && !IS_ITEMP(op))
225 #define POINTER_SET(ic) ( ic && ic->op == '=' \
226 && IS_ITEMP(IC_RESULT(ic)) \
227 && IC_RESULT(ic)->isaddr )
229 #define POINTER_GET(ic) ( ic && ic->op == GET_VALUE_AT_ADDRESS \
230 && (IS_ITEMP(IC_LEFT(ic)) || IS_OP_LITERAL(IC_LEFT(ic)))\
231 && IC_LEFT(ic)->isaddr )
233 #define IS_ARITHMETIC_OP(x) (x && (x->op == '+' || \
238 #define IS_BITWISE_OP(x) (x && (x->op == BITWISEAND || \
242 #define ASSIGNMENT(ic) ( ic && ic->op == '=')
244 #define ASSIGN_SYM_TO_ITEMP(ic) (ic && ic->op == '=' && \
245 IS_TRUE_SYMOP(IC_RIGHT(ic)) && \
246 IS_ITEMP(IC_RESULT(ic)))
248 #define ASSIGN_ITEMP_TO_SYM(ic) (ic && ic->op == '=' && \
249 IS_TRUE_SYMOP(IC_RESULT(ic)) && \
250 IS_ITEMP(IC_RIGHT(ic)))
252 #define ASSIGN_ITEMP_TO_ITEMP(ic) (ic && ic->op == '=' &&\
254 IS_ITEMP(IC_RIGHT(ic)) &&\
255 IS_ITEMP(IC_RESULT(ic)))
257 #define ADD_SUBTRACT_ITEMP(ic) (ic && (ic->op == '+' || ic->op == '-') && \
258 IS_ITEMP(IC_RESULT(ic)) && \
259 ( ( IS_ITEMP(IC_LEFT(ic)) ) || ( IS_SYMOP(IC_LEFT(ic)) ) ) && \
260 IS_OP_LITERAL(IC_RIGHT(ic)))
262 #define ASSIGNMENT_TO_SELF(ic) (!POINTER_SET(ic) && !POINTER_GET(ic) && \
263 ic->op == '=' && IC_RESULT(ic)->key == IC_RIGHT(ic)->key )
265 #define SET_ISADDR(op,v) {op = operandFromOperand(op); op->isaddr = v;}
266 #define SET_RESULT_RIGHT(ic) {SET_ISADDR(IC_RIGHT(ic),0); SET_ISADDR(IC_RESULT(ic),0);}
268 #define OP_DEFS(op) op->operand.symOperand->defs
269 #define OP_USES(op) op->operand.symOperand->uses
270 /*-----------------------------------------------------------------*/
271 /* forward references for functions */
272 /*-----------------------------------------------------------------*/
273 iCode *reverseiCChain ();
274 bool isOperandOnStack (operand *);
275 int isOperandVolatile (operand *, bool);
276 int isOperandGlobal (operand *);
277 void printiCChain (iCode *, FILE *);
278 operand *ast2iCode (ast *,int);
279 operand *geniCodeCast (sym_link *, operand *, bool);
280 operand *geniCodePtrPtrSubtract (operand *, operand *);
282 iCode *iCodeFromAst (ast *);
283 int isiCodeEqual (iCode *, iCode *);
284 int isOperandEqual (operand *, operand *);
285 iCodeTable *getTableEntry (int);
286 int isOperandLiteral (operand *);
287 operand *operandOperation (operand *, operand *, int, sym_link *);
288 double operandLitValue (operand *);
289 operand *operandFromLit (double);
290 operand *operandFromOperand (operand *);
291 int isParameterToCall (value *, operand *);
292 iCode *newiCodeLabelGoto (int, symbol *);
293 symbol *newiTemp (char *);
294 symbol *newiTempLabel (char *);
295 symbol *newiTempPreheaderLabel ();
296 iCode *newiCode (int, operand *, operand *);
297 sym_link *operandType (operand *);
298 operand *operandFromValue (value *);
299 operand *operandFromSymbol (symbol *);
300 sym_link *aggrToPtr (sym_link *, bool);
301 int piCode (void *, FILE *);
302 int printOperand (operand *, FILE *);
303 void setOperandType (operand *, sym_link *);
304 bool isOperandInFarSpace (operand *);
305 operand *opFromOpWithDU (operand *, bitVect *, bitVect *);
306 iCode *copyiCode (iCode *);
307 operand *newiTempFromOp (operand *);
308 /*-----------------------------------------------------------------*/
309 /* declaration of exported variables */
310 /*-----------------------------------------------------------------*/
311 extern char *filename;