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 aggr2ptr:1; /* must change aggregate to pointer to aggregate */
79 unsigned int isvolatile:1; /* is a volatile operand */
80 unsigned int isGlobal:1; /* is a global operand */
81 unsigned int isPtr:1; /* is assigned a pointer */
82 unsigned int isGptr:1; /* is a generic pointer */
83 unsigned int isParm:1; /* is a parameter */
84 unsigned int isLiteral:1; /* operand is literal */
89 struct symbol *symOperand; /* operand is of type symbol */
90 struct value *valOperand; /* operand is of type value */
91 struct sym_link *typeOperand; /* operand is of type typechain */
95 bitVect *usesDefs; /* which definitions are used by this */
96 struct asmop *aop; /* asm op for this operand */
100 extern operand *validateOpType(operand *op,
107 #define OP_SYMBOL(op) validateOpType(op, "OP_SYMBOL", #op, SYMBOL, __FILE__, __LINE__)->operand.symOperand
108 #define OP_VALUE(op) validateOpType(op, "OP_VALUE", #op, VALUE, __FILE__, __LINE__)->operand.valOperand
109 #define OP_SYM_TYPE(op) validateOpType(op, "OP_SYM_TYPE", #op, SYMBOL, __FILE__, __LINE__)->operand.symOperand->type
110 #define OP_SYM_ETYPE(op) validateOpType(op, "OP_SYM_ETYPE", #op, SYMBOL, __FILE__, __LINE__)->operand.symOperand->etype
111 #define SPIL_LOC(op) validateOpType(op, "SPIL_LOC", #op, SYMBOL, __FILE__, __LINE__)->operand.symOperand->usl.spillLoc
112 #define OP_LIVEFROM(op) validateOpType(op, "OP_LIVEFROM", #op, SYMBOL, __FILE__, __LINE__)->operand.symOperand->liveFrom
113 #define OP_LIVETO(op) validateOpType(op, "OP_LIVETO", #op, SYMBOL, __FILE__, __LINE__)->operand.symOperand->liveTo
114 #define OP_REQV(op) validateOpType(op, "OP_REQV", #op, SYMBOL, __FILE__, __LINE__)->operand.symOperand->reqv
116 /* definition for intermediate code */
117 #define IC_RESULT(x) (x)->ulrrcnd.lrr.result
118 #define IC_LEFT(x) (x)->ulrrcnd.lrr.left
119 #define IC_RIGHT(x) (x)->ulrrcnd.lrr.right
120 #define IC_COND(x) (x)->ulrrcnd.cnd.condition
121 #define IC_TRUE(x) (x)->ulrrcnd.cnd.trueLabel
122 #define IC_FALSE(x) (x)->ulrrcnd.cnd.falseLabel
123 #define IC_LABEL(x) (x)->label
124 #define IC_JTCOND(x) (x)->ulrrcnd.jmpTab.condition
125 #define IC_JTLABELS(x) (x)->ulrrcnd.jmpTab.labels
126 #define IC_INLINE(x) (x)->inlineAsm
127 #define IC_ARRAYILIST(x) (x)->arrayInitList
131 unsigned int op; /* operation defined */
132 int key; /* running key for this iCode */
133 int seq; /* sequence number within routine */
134 int seqPoint; /* sequence point */
135 short depth; /* loop depth of this iCode */
136 short level; /* scope level */
137 short block; /* sequential block number */
138 unsigned nosupdate:1; /* don't update spillocation with this */
139 unsigned generated:1; /* code generated for this one */
140 unsigned parmPush:1; /* parameter push Vs spill push */
141 unsigned supportRtn:1; /* will cause a call to a support routine */
142 unsigned regsSaved:1; /* registers have been saved */
143 unsigned bankSaved:1; /* register bank has been saved */
144 unsigned builtinSEND:1; /* SEND for parameter of builtin function */
146 struct iCode *next; /* next in chain */
147 struct iCode *prev; /* previous in chain */
148 set *movedFrom; /* if this iCode gets moved to another block */
149 bitVect *rlive; /* ranges that are live at this point */
150 int defKey; /* key for the operand being defined */
151 bitVect *uses; /* vector of key of used symbols */
152 bitVect *rUsed; /* registers used by this instruction */
153 bitVect *rMask; /* registers in use during this instruction */
158 operand *left; /* left if any */
159 operand *right; /* right if any */
160 operand *result; /* result of this op */
166 operand *condition; /* if this is a conditional */
167 symbol *trueLabel; /* true for conditional */
168 symbol *falseLabel; /* false for conditional */
174 operand *condition; /* condition for the jump */
175 set *labels; /* ordered set of labels */
182 symbol *label; /* for a goto statement */
184 char *inlineAsm; /* pointer to inline assembler code */
185 literalList *arrayInitList; /* point to array initializer list. */
187 int lineno; /* file & lineno for debug information */
190 int parmBytes; /* if call/pcall, count of parameter bytes
192 int argreg; /* argument regno for SEND/RECEIVE */
193 int eBBlockNum; /* belongs to which eBBlock */
194 char riu; /* after ralloc, the registers in use */
195 struct ast * tree; /* ast node for this iCode (if not NULL) */
199 /* various functions associated to iCode */
200 typedef struct icodeFuncTable
204 void (*iCodePrint) (struct dbuf_s *, iCode *, char *);
205 iCode *(*iCodeCopy) (iCode *);
210 #define SKIP_IC2(x) (x->op == GOTO || \
212 x->op == FUNCTION || \
213 x->op == INLINEASM || \
214 x->op == ENDFUNCTION )
216 #define SKIP_IC1(x) (x->op == CALL || \
219 #define SKIP_IC(x) (x->op == PCALL || \
222 x->op == JUMPTABLE || \
223 x->op == RECEIVE || \
224 x->op == ARRAYINIT || \
226 x->op == CRITICAL || \
227 x->op == ENDCRITICAL || \
230 #define SKIP_IC3(x) (SKIP_IC2(x) || \
233 #define IS_CONDITIONAL(x) (x->op == EQ_OP || \
240 #define IS_TRUE_SYMOP(op) (op && IS_SYMOP(op) && !IS_ITEMP(op))
242 #define POINTER_SET(ic) ( ic && ic->op == '=' \
243 && IS_ITEMP(IC_RESULT(ic)) \
244 && IC_RESULT(ic)->isaddr )
246 #define POINTER_GET(ic) ( ic && ic->op == GET_VALUE_AT_ADDRESS \
247 && (IS_ITEMP(IC_LEFT(ic)) || IS_OP_LITERAL(IC_LEFT(ic)))\
248 && IC_LEFT(ic)->isaddr )
250 #define IS_ARITHMETIC_OP(x) (x && (x->op == '+' || \
255 #define IS_BITWISE_OP(x) (x && (x->op == BITWISEAND || \
259 #define IS_ASSOCIATIVE(x) (x && (x->op == EQ_OP || \
263 x->op == BITWISEAND || \
267 #define ASSIGNMENT(ic) ( ic && ic->op == '=')
269 #define ASSIGN_SYM_TO_ITEMP(ic) (ic && ic->op == '=' && \
270 IS_TRUE_SYMOP(IC_RIGHT(ic)) && \
271 IS_ITEMP(IC_RESULT(ic)))
273 #define ASSIGN_ITEMP_TO_SYM(ic) (ic && ic->op == '=' && \
274 IS_TRUE_SYMOP(IC_RESULT(ic)) && \
275 IS_ITEMP(IC_RIGHT(ic)))
277 #define ASSIGN_ITEMP_TO_ITEMP(ic) (ic && ic->op == '=' &&\
279 IS_ITEMP(IC_RIGHT(ic)) &&\
280 IS_ITEMP(IC_RESULT(ic)))
282 #define ADD_SUBTRACT_ITEMP(ic) (ic && (ic->op == '+' || ic->op == '-') && \
283 IS_ITEMP(IC_RESULT(ic)) && \
284 ( ( IS_ITEMP(IC_LEFT(ic)) ) || ( IS_SYMOP(IC_LEFT(ic)) ) ) && \
285 IS_OP_LITERAL(IC_RIGHT(ic)))
287 #define ASSIGNMENT_TO_SELF(ic) (!POINTER_SET(ic) && !POINTER_GET(ic) && \
288 ic->op == '=' && IC_RESULT(ic)->key == IC_RIGHT(ic)->key )
290 #define IS_CAST_ICODE(ic) (ic && ic->op == CAST)
291 #define SET_ISADDR(op,v) {op = operandFromOperand(op); op->isaddr = v;}
292 #define SET_RESULT_RIGHT(ic) {SET_ISADDR(IC_RIGHT(ic),0); SET_ISADDR(IC_RESULT(ic),0);}
293 #define IS_ASSIGN_ICODE(ic) (ASSIGNMENT(ic) && !POINTER_SET(ic))
295 #define OP_DEFS(op) validateOpType(op, "OP_DEFS", #op, SYMBOL, __FILE__, __LINE__)->operand.symOperand->defs
296 #define OP_USES(op) validateOpType(op, "OP_USES", #op, SYMBOL, __FILE__, __LINE__)->operand.symOperand->uses
297 /*-----------------------------------------------------------------*/
298 /* forward references for functions */
299 /*-----------------------------------------------------------------*/
300 iCode *reverseiCChain ();
301 bool isOperandOnStack (operand *);
302 int isOperandVolatile (operand *, bool);
303 int isOperandGlobal (operand *);
304 void printiCChain (iCode *, FILE *);
305 operand *ast2iCode (ast *,int);
306 operand *geniCodePtrPtrSubtract (operand *, operand *);
308 iCode *iCodeFromAst (ast *);
309 int isiCodeEqual (iCode *, iCode *);
310 int isOperandEqual (operand *, operand *);
311 iCodeTable *getTableEntry (int);
312 int isOperandLiteral (operand *);
313 operand *operandOperation (operand *, operand *, int, sym_link *);
314 double operandLitValue (operand *);
315 operand *operandFromLit (double);
316 operand *operandFromOperand (operand *);
317 int isParameterToCall (value *, operand *);
318 iCode *newiCodeLabelGoto (int, symbol *);
319 symbol *newiTemp (char *);
320 symbol *newiTempLabel (char *);
321 #define LOOPEXITLBL "loopExitLbl"
322 symbol *newiTempLoopHeaderLabel (bool);
323 iCode *newiCode (int, operand *, operand *);
324 sym_link *operandType (operand *);
325 operand *operandFromValue (value *);
326 operand *operandFromSymbol (symbol *);
327 operand *operandFromLink (sym_link *);
328 sym_link *aggrToPtr (sym_link *, bool);
329 int aggrToPtrDclType (sym_link *, bool);
330 int piCode (void *, FILE *);
331 int dbuf_printOperand (operand *, struct dbuf_s *);
332 int printOperand (operand *, FILE *);
333 void setOperandType (operand *, sym_link *);
334 bool isOperandInFarSpace (operand *);
335 bool isOperandInPagedSpace (operand *);
336 bool isOperandInDirSpace (operand *);
337 bool isOperandInCodeSpace (operand *);
338 operand *opFromOpWithDU (operand *, bitVect *, bitVect *);
339 iCode *copyiCode (iCode *);
340 operand *newiTempFromOp (operand *);
341 iCode *getBuiltinParms (iCode *,int *, operand **);
342 int isiCodeInFunctionCall (iCode *);
343 /*-----------------------------------------------------------------*/
344 /* declaration of exported variables */
345 /*-----------------------------------------------------------------*/
346 extern char *filename;