benode.h 15.4 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
Christian Würdig's avatar
Christian Würdig committed
4
5
 */

Sebastian Hack's avatar
Sebastian Hack committed
6
/**
Christian Würdig's avatar
Christian Würdig committed
7
8
9
10
 * @file
 * @brief       Backend node support for generic backend nodes.
 * @author      Sebastian Hack
 * @date        17.05.2005
Sebastian Hack's avatar
Sebastian Hack committed
11
 *
Christian Würdig's avatar
Christian Würdig committed
12
13
 * Backend node support for generic backend nodes.
 * This file provides Perm, Copy, Spill and Reload nodes.
Sebastian Hack's avatar
Sebastian Hack committed
14
 */
Christian Würdig's avatar
Christian Würdig committed
15
16
#ifndef FIRM_BE_BENODE_T_H
#define FIRM_BE_BENODE_T_H
17

18
19
#include <limits.h>

20
#include "firm_types.h"
21
#include "irnode_t.h"
Christian Würdig's avatar
Christian Würdig committed
22
#include "bearch.h"
Sebastian Hack's avatar
Sebastian Hack committed
23

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
typedef enum be_opcode {
	beo_Spill,
	beo_Reload,
	beo_Perm,
	beo_MemPerm,
	beo_Copy,
	beo_Keep,
	beo_CopyKeep,
	beo_Call,
	beo_Return,
	beo_IncSP,
	beo_AddSP,
	beo_SubSP,
	beo_Start,
	beo_FrameAddr,

	beo_first = beo_Spill,
	beo_last  = beo_FrameAddr
} be_opcode;

44
45
46
47
48
49
/**
 * The benode op's.  Must be available to register emitter function.
 */
extern ir_op *op_be_Spill;
extern ir_op *op_be_Reload;
extern ir_op *op_be_Perm;
Matthias Braun's avatar
Matthias Braun committed
50
extern ir_op *op_be_MemPerm;
51
52
extern ir_op *op_be_Copy;
extern ir_op *op_be_Keep;
Michael Beck's avatar
Michael Beck committed
53
extern ir_op *op_be_CopyKeep;
54
55
56
extern ir_op *op_be_Call;
extern ir_op *op_be_Return;
extern ir_op *op_be_IncSP;
Sebastian Hack's avatar
Sebastian Hack committed
57
extern ir_op *op_be_AddSP;
Michael Beck's avatar
Michael Beck committed
58
extern ir_op *op_be_SubSP;
59
extern ir_op *op_be_Start;
60
61
extern ir_op *op_be_FrameAddr;

62
63
64
/**
 * Determines if irn is a be_node.
 */
65
66
67
bool is_be_node(const ir_node *irn);

be_opcode get_be_irn_opcode(const ir_node *node);
68

69
70
71
/**
 * Create all BE specific opcodes.
 */
72
void be_init_op(void);
73

Matthias Braun's avatar
Matthias Braun committed
74
75
void be_finish_op(void);

76
77
78
/**
 * Position numbers for the be_Spill inputs.
 */
79
enum {
80
81
	n_be_Spill_frame = 0,
	n_be_Spill_val   = 1
82
};
83
84
85
86

/**
 * Make a new Spill node.
 */
87
88
89
ir_node *be_new_Spill(const arch_register_class_t *cls,
                      const arch_register_class_t *cls_frame, ir_node *block,
                      ir_node *frame, ir_node *to_spill);
90

91
92
93
/**
 * Position numbers for the be_Reload inputs.
 */
94
enum {
95
96
	n_be_Reload_frame = 0,
	n_be_Reload_mem   = 1
97
};
98
99
100
101

/**
 * Make a new Reload node.
 */
102
103
104
ir_node *be_new_Reload(const arch_register_class_t *cls,
                       const arch_register_class_t *cls_frame, ir_node *block,
                       ir_node *frame, ir_node *mem, ir_mode *mode);
105

106
107
108
/**
 * Position numbers for the be_Copy inputs.
 */
109
enum {
110
	n_be_Copy_op = 0
111
};
112
113
114
115

/**
 * Make a new Copy node.
 */
116
ir_node *be_new_Copy(ir_node *block, ir_node *in);
117
/** Returns the Copy Argument. */
118
119
ir_node *be_get_Copy_op(const ir_node *cpy);

120
121
122
/**
 * Make a new Perm node.
 */
123
ir_node *be_new_Perm(arch_register_class_t const *cls, ir_node *block, int n, ir_node *const *in);
124
125
126
127
128
129
130

/**
 * Reduce a Perm.
 * Basically, we provide a map to remap the Perm's arguments. If an entry in the
 * map is -1, the argument gets deleted.
 * This function takes care, that the register data and the input array reflects
 * the changes described by the map.
131
132
 * This is needed by the Perm optimization/movement in belower.c, see
 * push_through_perm().
133
 * @param perm     The perm node.
134
135
136
137
 * @param new_size The new number of arguments (must be smaller or equal to the
 *                 current one).
 * @param map      A map assigning each operand a new index (or -1 to indicate
 *                 deletion).
138
139
140
 */
void be_Perm_reduce(ir_node *perm, int new_size, int *map);

141
142
/**
 * Create a new MemPerm node.
143
144
145
 * A MemPerm node exchanges the values of memory locations. (Typically entities
 * used as spillslots). MemPerm nodes perform this operation without modifying
 * any register values.
146
 */
147
148
149
ir_node *be_new_MemPerm(ir_node *block, int n, ir_node *const *in);

ir_node *be_new_Keep(ir_node *block, int arity, ir_node *const *in);
Sebastian Hack's avatar
Sebastian Hack committed
150

151
152
void be_Keep_add_node(ir_node *keep, const arch_register_class_t *cls,
                      ir_node *node);
153

154
155
156
157
/**
 * Position numbers for the be_FrameAddr inputs
 */
enum {
158
	n_be_FrameAddr_ptr = 0
159
160
};

Michael Beck's avatar
Michael Beck committed
161
/** Create a new FrameAddr node. */
162
163
ir_node *be_new_FrameAddr(const arch_register_class_t *cls_frame,
                          ir_node *block, ir_node *frame, ir_entity *ent);
164

Michael Beck's avatar
Michael Beck committed
165
/** Return the frame input of a FrameAddr node. */
Matthias Braun's avatar
Matthias Braun committed
166
167
168
ir_node *be_get_FrameAddr_frame(const ir_node *node);

ir_entity *be_get_FrameAddr_entity(const ir_node *node);
Michael Beck's avatar
Michael Beck committed
169

170
171
172
/**
 * Position numbers for the be_AddSP inputs
 */
Sebastian Hack's avatar
Sebastian Hack committed
173
enum {
174
175
176
	n_be_AddSP_old_sp = 0,
	n_be_AddSP_size   = 1,
	n_be_AddSP_last   = 2
Sebastian Hack's avatar
Sebastian Hack committed
177
178
};

Sebastian Hack's avatar
Sebastian Hack committed
179
enum {
180
181
182
183
	pn_be_AddSP_sp   = 0,
	pn_be_AddSP_res  = 1,
	pn_be_AddSP_M    = 2,
	pn_be_AddSP_last = 3
Sebastian Hack's avatar
Sebastian Hack committed
184
185
};

Sebastian Hack's avatar
Sebastian Hack committed
186
187
/**
 * Make a new AddSP node.
188
189
190
 * An AddSP node expresses an increase of the stack pointer in the direction
 * the stack grows. In contrast to IncSP, the amount of bytes the stack pointer
 * is grown, is not given by a constant but an ordinary Firm node.
Sebastian Hack's avatar
Sebastian Hack committed
191
 * @param sp     The stack pointer register.
192
 * @param block  The block.
Sebastian Hack's avatar
Sebastian Hack committed
193
 * @param old_sp The node representing the old stack pointer value.
194
195
 * @param size   The node expressing the size by which the stack pointer shall
 *               be grown.
Sebastian Hack's avatar
Sebastian Hack committed
196
197
 * @return       A new AddSP node.
 */
198
199
ir_node *be_new_AddSP(const arch_register_t *sp, ir_node *block,
                      ir_node *old_sp, ir_node *size);
Sebastian Hack's avatar
Sebastian Hack committed
200

Michael Beck's avatar
Michael Beck committed
201
202
203
204
/**
 * Position numbers for the be_SubSP inputs
 */
enum {
205
206
207
	n_be_SubSP_old_sp = 0,
	n_be_SubSP_size   = 1,
	n_be_SubSP_last   = 2
Michael Beck's avatar
Michael Beck committed
208
209
210
};

enum {
211
	pn_be_SubSP_sp   = 0,
Michael Beck's avatar
Michael Beck committed
212
213
214
215
216
217
	pn_be_SubSP_M    = 1,
	pn_be_SubSP_last = 2
};

/**
 * Make a new SubSP node.
218
219
220
 * A SubSP node expresses a decrease of the stack pointer in the direction the
 * stack grows. In contrast to IncSP, the amount of bytes the stack pointer is
 * grown, is not given by a constant but an ordinary Firm node.
Michael Beck's avatar
Michael Beck committed
221
 * @param sp     The stack pointer register.
222
 * @param block  The block.
Michael Beck's avatar
Michael Beck committed
223
 * @param old_sp The node representing the old stack pointer value.
224
225
 * @param size   The node expressing the size by which the stack pointer shall
 *               be grown.
Michael Beck's avatar
Michael Beck committed
226
227
 * @return       A new DecSP node.
 */
228
229
ir_node *be_new_SubSP(const arch_register_t *sp, ir_node *block,
                      ir_node *old_sp, ir_node *size);
Michael Beck's avatar
Michael Beck committed
230

Sebastian Hack's avatar
Sebastian Hack committed
231
232
/**
 * Make a stack pointer increase/decrease node.
233
234
 * @param sp     The stack pointer register.
 * @param block  The block to insert the node into.
Sebastian Hack's avatar
Sebastian Hack committed
235
 * @param old_sp The node defining the former stack pointer.
236
237
238
239
 * @param offset amount the stack should expand (positive offset) or shrink
 *               (negative offset). Note that the offset is independent of the
 *               natural stack direction of the architecture but just specifies
 *               abstract expanding/shrinking of the stack area.
yb9976's avatar
yb9976 committed
240
 * @param align  force stack alignment to this power of 2. (i.e. specifying 3
241
 *               results in a 2^3 = 8byte stack alignment)
Sebastian Hack's avatar
Sebastian Hack committed
242
 * @return       A new stack pointer increment/decrement node.
243
244
 * @note         This node sets a register constraint to the @p sp register on
 *               its output.
Sebastian Hack's avatar
Sebastian Hack committed
245
 */
246
ir_node *be_new_IncSP(const arch_register_t *sp, ir_node *block,
247
                      ir_node *old_sp, int offset, int align);
Sebastian Hack's avatar
Sebastian Hack committed
248

Michael Beck's avatar
BugFix:    
Michael Beck committed
249
250
/** Returns the previous node that computes the stack pointer. */
ir_node *be_get_IncSP_pred(ir_node *incsp);
Sebastian Hack's avatar
Sebastian Hack committed
251

252
/** Sets the previous node that computes the stack pointer. */
253
void     be_set_IncSP_pred(ir_node *incsp, ir_node *pred);
254

255
256
257
258
259
260
261
/**
 * Sets a new offset to a IncSP node.
 * A positive offset means expanding the stack, a negative offset shrinking
 * an offset is == BE_STACK_FRAME_SIZE will be replaced by the real size of the
 * stackframe in the fix_stack_offsets phase.
 */
void     be_set_IncSP_offset(ir_node *irn, int offset);
Michael Beck's avatar
BugFix:    
Michael Beck committed
262
263

/** Gets the offset from a IncSP node. */
264
int be_get_IncSP_offset(const ir_node *irn);
265
int be_get_IncSP_align(const ir_node *irn);
Sebastian Hack's avatar
Sebastian Hack committed
266

267
/** Gets the call entity or NULL if this is no static call. */
268
ir_entity  *be_Call_get_entity(const ir_node *call);
269
/** Sets the call entity. */
270
void     be_Call_set_entity(ir_node *call, ir_entity *ent);
271
272
273
274
/** Gets the call type. */
ir_type *be_Call_get_type(ir_node *call);
/** Sets the call type. */
void     be_Call_set_type(ir_node *call, ir_type *call_tp);
275

Matthias Braun's avatar
Matthias Braun committed
276
277
278
279
void     be_Call_set_pop(ir_node *call, unsigned pop);

unsigned be_Call_get_pop(const ir_node *call);

280
281
282
/**
 * Position numbers for the be_Call inputs.
 */
283
enum {
284
285
286
287
	n_be_Call_mem       = 0,  /**< memory input of a be_Call node */
	n_be_Call_sp        = 1,  /**< stack pointer input of a be_Call node */
	n_be_Call_ptr       = 2,  /**< call pointer input of a be_Call node */
	n_be_Call_first_arg = 3   /**< first argument input of a be_Call node */
288
289
};

290
291
292
293
/**
 * Projection numbers for result of be_Call node: use for Proj nodes!
 */
typedef enum {
294
295
296
	pn_be_Call_M         = pn_Call_M, /**< The memory result of a be_Call. */
	pn_be_Call_X_regular = pn_Call_X_regular,
	pn_be_Call_X_except  = pn_Call_X_except,
297
	pn_be_Call_sp        = pn_Call_max+1,
298
	pn_be_Call_first_res     /**< The first result proj number of a be_Call. */
299
300
301
} pn_be_Call;

/**
Michael Beck's avatar
Michael Beck committed
302
303
304
 * Construct a new be_Call.
 *
 * @param dbg      debug info
305
 * @param block    the block where the call is placed
Michael Beck's avatar
Michael Beck committed
306
307
 * @param mem      the memory input of the call
 * @param sp       the stack pointer input of the call
308
309
 * @param ptr      the address of the called function, if immediate call set
 *                 to sp
Michael Beck's avatar
Michael Beck committed
310
311
312
313
 * @param n_outs   the number of outcoming values from this call
 * @param n        the number of (register) inputs of this call
 * @param in       the (register) inputs of this call
 * @param call_tp  the call type of this call
314
 */
315
ir_node *be_new_Call(dbg_info *dbg, ir_node *block, ir_node *mem, arch_register_req_t const *sp_req, ir_node *sp, arch_register_req_t const *ptr_req, ir_node *ptr, int n_outs, int n, ir_node *const *in, ir_type *call_tp);
316
317

/**
318
319
320
 * Position numbers for the be_Return inputs.
 */
enum {
321
322
323
	n_be_Return_mem  = 0,     /**< memory input of a be_Return node */
	n_be_Return_sp   = 1,     /**< stack pointer input of a be_Return node */
	n_be_Return_val  = 2,     /**< first "real" return value if any */
324
325
326
327
};

/**
 * Construct a new be_Return.
Michael Beck's avatar
Michael Beck committed
328
329
 *
 * @param dbg    debug info
330
 * @param block  the block where the new node will be placed
331
 * @param n_res  number of "real" results
332
 * @param pop    pop number of bytes on return
333
 * @param n      number of inputs
334
335
 * @param in     input array
 */
336
ir_node *be_new_Return(dbg_info *dbg, ir_node *block, int n_res, unsigned pop, int n, ir_node *const *in);
337
338

/** Returns the number of real returns values */
339
340
int be_Return_get_n_rets(const ir_node *ret);

Michael Beck's avatar
Michael Beck committed
341
/**
342
343
 * Return the number of bytes that should be popped from stack when executing
 * the Return.
Michael Beck's avatar
Michael Beck committed
344
345
346
 *
 * @param ret  the be_Return node
 */
347
unsigned be_Return_get_pop(const ir_node *ret);
348

349
350
351
352
353
354
355
356
357
358
359
360
361
/**
 * Return non-zero, if number of popped bytes must be always emitted.
 *
 * @param ret  the be_Return node
 */
int be_Return_get_emit_pop(const ir_node *ret);

/**
 * Set the emit_pop flag.
 *
 * @param ret  the be_Return node
 */
void be_Return_set_emit_pop(ir_node *ret, int emit_pop);
362

363
364
void be_return_set_destroy_stackframe(ir_node *node, bool value);

365
ir_node *be_new_Start(dbg_info *dbgi, ir_node *block, int n_out);
Sebastian Hack's avatar
Sebastian Hack committed
366

367
368
void be_start_set_setup_stackframe(ir_node *node, bool value);

Sebastian Hack's avatar
Sebastian Hack committed
369
enum {
370
	n_be_CopyKeep_op = 0
Sebastian Hack's avatar
Sebastian Hack committed
371
};
372
373
ir_node *be_new_CopyKeep(ir_node *block, ir_node *src,
                         int n, ir_node *in_keep[]);
374

375
ir_node *be_new_CopyKeep_single(ir_node *block, ir_node *src, ir_node *keep);
376

377
ir_node *be_get_CopyKeep_op(const ir_node *cpy);
Sebastian Hack's avatar
Sebastian Hack committed
378

379
void be_set_CopyKeep_op(ir_node *cpy, ir_node *op);
Sebastian Hack's avatar
Sebastian Hack committed
380

381
/**
Michael Beck's avatar
Michael Beck committed
382
 * Returns the frame entity of a be node.
383
 * Try to avoid this function and better call arch_get_frame_entity!
384
 *
Michael Beck's avatar
Michael Beck committed
385
 * @return the frame entity used by the be node
386
 */
387
388
ir_entity *be_get_frame_entity(const ir_node *irn);

389
390
void be_node_set_frame_entity(ir_node *node, ir_entity *entity);

391
392
393
394
/**
 * Returns the frame offset of this node.
 */
int be_get_frame_offset(const ir_node *irn);
395
396

ir_node* be_get_Reload_mem(const ir_node *irn);
397
ir_node *be_get_Reload_frame(const ir_node *irn);
398
ir_node* be_get_Spill_val(const ir_node *irn);
399
ir_node *be_get_Spill_frame(const ir_node *irn);
400

401
402
void be_set_MemPerm_in_entity(const ir_node *irn, int n, ir_entity* ent);
ir_entity *be_get_MemPerm_in_entity(const ir_node *irn, int n);
Matthias Braun's avatar
Matthias Braun committed
403

404
405
void be_set_MemPerm_out_entity(const ir_node *irn, int n, ir_entity* ent);
ir_entity *be_get_MemPerm_out_entity(const ir_node *irn, int n);
406

407
408
int be_get_MemPerm_entity_arity(const ir_node *irn);

Sebastian Hack's avatar
Sebastian Hack committed
409
410
411
/**
 * Impose a register constraint on a backend node.
 * @param irn The node.
412
 * @param pos The position of the argument.
413
414
 * @param reg The register which is admissible for that node, argument/result
 *            and position.
Sebastian Hack's avatar
Sebastian Hack committed
415
 */
416
417
418
419
void be_set_constr_single_reg_in(ir_node *irn, int pos,
		const arch_register_t *reg, arch_register_req_type_t additional_flags);
void be_set_constr_single_reg_out(ir_node *irn, int pos,
		const arch_register_t *reg, arch_register_req_type_t additional_flags);
420

421
422
423
const arch_register_req_t *be_create_reg_req(struct obstack *obst,
		const arch_register_t *reg, arch_register_req_type_t additional_types);

424
/**
425
 * Impose register constraints on a backend node.
426
427
428
 * The register subsets given by the limited function in @p req are copied to
 * the backend node. This requires that the constraint type of the @p req is
 * arch_register_req_type_limited.
429
430
431
 * @param irn The backend node.
 * @param pos The position (@see be_set_constr_single_reg()).
 * @param req The register requirements which shall be transferred.
432
 */
433
434
void be_set_constr_in(ir_node *irn, int pos, const arch_register_req_t *req);
void be_set_constr_out(ir_node *irn, int pos, const arch_register_req_t *req);
435

Sebastian Hack's avatar
Sebastian Hack committed
436
437
438
/**
 * Set the register class of a node.
 * @param irn The node itself.
439
 * @param pos The position (0..n) for arguments
Sebastian Hack's avatar
Sebastian Hack committed
440
441
 * @param flags The register class to set for that node and position.
 */
442
443
444
445
void be_node_set_reg_class_in(ir_node *irn, int pos,
                              const arch_register_class_t *cls);
void be_node_set_reg_class_out(ir_node *irn, int pos,
                               const arch_register_class_t *cls);
Sebastian Hack's avatar
Sebastian Hack committed
446

447
448
449
/**
 * Set the register requirements for a phi node.
 */
450
451
void be_set_phi_reg_req(ir_node *phi, const arch_register_req_t *req);

452
void be_dump_phi_reg_reqs(FILE *out, const ir_node *node, dump_reason_t reason);
453

454
455
456
457
/**
 * Creates a new phi with associated backend informations
 */
ir_node *be_new_Phi(ir_node *block, int n_ins, ir_node **ins, ir_mode *mode,
458
                    const arch_register_req_t *req);
459

460
461
462
463
464
/**
 * Search for output of start node with a specific register
 */
ir_node *be_get_initial_reg_value(ir_graph *irg, const arch_register_t *reg);

465
466
467
468
469
470
471
472
473
474
475
476
477
478
static inline bool be_is_Spill    (const ir_node *irn) { return get_irn_op(irn) == op_be_Spill    ; }
static inline bool be_is_Reload   (const ir_node *irn) { return get_irn_op(irn) == op_be_Reload   ; }
static inline bool be_is_Copy     (const ir_node *irn) { return get_irn_op(irn) == op_be_Copy     ; }
static inline bool be_is_CopyKeep (const ir_node *irn) { return get_irn_op(irn) == op_be_CopyKeep ; }
static inline bool be_is_Perm     (const ir_node *irn) { return get_irn_op(irn) == op_be_Perm     ; }
static inline bool be_is_MemPerm  (const ir_node *irn) { return get_irn_op(irn) == op_be_MemPerm  ; }
static inline bool be_is_Keep     (const ir_node *irn) { return get_irn_op(irn) == op_be_Keep     ; }
static inline bool be_is_Call     (const ir_node *irn) { return get_irn_op(irn) == op_be_Call     ; }
static inline bool be_is_Return   (const ir_node *irn) { return get_irn_op(irn) == op_be_Return   ; }
static inline bool be_is_IncSP    (const ir_node *irn) { return get_irn_op(irn) == op_be_IncSP    ; }
static inline bool be_is_AddSP    (const ir_node *irn) { return get_irn_op(irn) == op_be_AddSP    ; }
static inline bool be_is_SubSP    (const ir_node *irn) { return get_irn_op(irn) == op_be_SubSP    ; }
static inline bool be_is_Start    (const ir_node *irn) { return get_irn_op(irn) == op_be_Start    ; }
static inline bool be_is_FrameAddr(const ir_node *irn) { return get_irn_op(irn) == op_be_FrameAddr; }
479

480
#endif