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 // jwk #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 // jwk 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 IS_CAST_ICODE(ic) (ic && ic->op == CAST)
266 #define SET_ISADDR(op,v) {op = operandFromOperand(op); op->isaddr = v;}
267 #define SET_RESULT_RIGHT(ic) {SET_ISADDR(IC_RIGHT(ic),0); SET_ISADDR(IC_RESULT(ic),0);}
269 #define OP_DEFS(op) op->operand.symOperand->defs
270 #define OP_USES(op) op->operand.symOperand->uses
271 /*-----------------------------------------------------------------*/
272 /* forward references for functions */
273 /*-----------------------------------------------------------------*/
274 iCode *reverseiCChain ();
275 bool isOperandOnStack (operand *);
276 int isOperandVolatile (operand *, bool);
277 int isOperandGlobal (operand *);
278 void printiCChain (iCode *, FILE *);
279 operand *ast2iCode (ast *,int);
280 operand *geniCodeCast (sym_link *, operand *, bool);
281 operand *geniCodePtrPtrSubtract (operand *, operand *);
283 iCode *iCodeFromAst (ast *);
284 int isiCodeEqual (iCode *, iCode *);
285 int isOperandEqual (operand *, operand *);
286 iCodeTable *getTableEntry (int);
287 int isOperandLiteral (operand *);
288 operand *operandOperation (operand *, operand *, int, sym_link *);
289 double operandLitValue (operand *);
290 operand *operandFromLit (double);
291 operand *operandFromOperand (operand *);
292 int isParameterToCall (value *, operand *);
293 iCode *newiCodeLabelGoto (int, symbol *);
294 symbol *newiTemp (char *);
295 symbol *newiTempLabel (char *);
296 symbol *newiTempPreheaderLabel ();
297 iCode *newiCode (int, operand *, operand *);
298 sym_link *operandType (operand *);
299 operand *operandFromValue (value *);
300 operand *operandFromSymbol (symbol *);
301 sym_link *aggrToPtr (sym_link *, bool);
302 int piCode (void *, FILE *);
303 int printOperand (operand *, FILE *);
304 void setOperandType (operand *, sym_link *);
305 bool isOperandInFarSpace (operand *);
306 operand *opFromOpWithDU (operand *, bitVect *, bitVect *);
307 iCode *copyiCode (iCode *);
308 operand *newiTempFromOp (operand *);
309 /*-----------------------------------------------------------------*/
310 /* declaration of exported variables */
311 /*-----------------------------------------------------------------*/
312 extern char *filename;