irop.c 8.18 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
Christian Würdig's avatar
Christian Würdig committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * This file is part of libFirm.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

Matthias Braun's avatar
Matthias Braun committed
20
21
22
23
/**
 * @file
 * @brief   Representation of opcode of intermediate operation.
 * @author  Christian Schaefer, Goetz Lindenmaier, Michael Beck
Götz Lindenmaier's avatar
Götz Lindenmaier committed
24
 */
Matthias Braun's avatar
Matthias Braun committed
25
#include "config.h"
Boris Boesler's avatar
added    
Boris Boesler committed
26

27
#include <string.h>
28

Michael Beck's avatar
Michael Beck committed
29
30
31
#include "irop_t.h"
#include "irnode_t.h"
#include "irhooks.h"
32
#include "irbackedge_t.h"
33

34
#include "iropt_t.h"
35
#include "irverify_t.h"
Michael Beck's avatar
Michael Beck committed
36
#include "reassoc_t.h"
Florian Liekweg's avatar
Florian Liekweg committed
37

Michael Beck's avatar
Michael Beck committed
38
#include "xmalloc.h"
Christian Schäfer's avatar
Christian Schäfer committed
39

40
41
void be_init_op(void);

Michael Beck's avatar
Michael Beck committed
42
43
44
/** the available next opcode */
static unsigned next_iro = iro_MaxOpcode;

45
46
47
48
/*
 * Copies all attributes stored in the old node to the new node.
 * Assumes both have the same opcode and sufficient size.
 */
49
50
void default_copy_attr(ir_graph *irg, const ir_node *old_node,
                       ir_node *new_node)
51
{
52
	unsigned size = firm_add_node_size;
53
	(void) irg;
54

55
56
	assert(get_irn_op(old_node) == get_irn_op(new_node));
	memcpy(&new_node->attr, &old_node->attr, get_op_attr_size(get_irn_op(old_node)));
57

58
59
60
61
	if (size > 0) {
		/* copy additional node data */
		memcpy(get_irn_data(new_node, void, size), get_irn_data(old_node, void, size), size);
	}
62
}
63
64

/**
Michael Beck's avatar
Michael Beck committed
65
 * Copies all Call attributes stored in the old node to the new node.
66
 */
67
68
static void call_copy_attr(ir_graph *irg, const ir_node *old_node,
                           ir_node *new_node)
69
{
70
	default_copy_attr(irg, old_node, new_node);
71
	remove_Call_callee_arr(new_node);
72
}
73

Michael Beck's avatar
Michael Beck committed
74
75
76
/**
 * Copies all Block attributes stored in the old node to the new node.
 */
77
78
static void block_copy_attr(ir_graph *irg, const ir_node *old_node,
                            ir_node *new_node)
79
{
80
81
82
83
84
85
86
87
	default_copy_attr(irg, old_node, new_node);
	new_node->attr.block.irg.irg       = irg;
	new_node->attr.block.phis          = NULL;
	new_node->attr.block.cg_backedge   = NULL;
	new_node->attr.block.backedge      = new_backedge_arr(irg->obst, get_irn_arity(new_node));
	new_node->attr.block.block_visited = 0;
	memset(&new_node->attr.block.dom, 0, sizeof(new_node->attr.block.dom));
	memset(&new_node->attr.block.pdom, 0, sizeof(new_node->attr.block.pdom));
Michael Beck's avatar
Michael Beck committed
88
89
90
91
92
	/* It should be safe to copy the entity here, as it has no back-link to the old block.
	 * It serves just as a label number, so copying a labeled block results in an exact copy.
	 * This is at least what we need for DCE to work. */
	new_node->attr.block.entity         = old_node->attr.block.entity;
	new_node->attr.block.phis           = NULL;
93
	INIT_LIST_HEAD(&new_node->attr.block.succ_head);
94
}
95

96
97
98
/**
 * Copies all phi attributes stored in old node to the new node
 */
99
100
static void phi_copy_attr(ir_graph *irg, const ir_node *old_node,
                          ir_node *new_node)
101
{
102
	default_copy_attr(irg, old_node, new_node);
103
104
	new_node->attr.phi.next       = NULL;
	new_node->attr.phi.u.backedge = new_backedge_arr(irg->obst, get_irn_arity(new_node));
105
106
}

Michael Beck's avatar
Michael Beck committed
107
108
109
/**
 * Copies all ASM attributes stored in old node to the new node
 */
110
111
static void ASM_copy_attr(ir_graph *irg, const ir_node *old_node,
                          ir_node *new_node)
112
{
113
	default_copy_attr(irg, old_node, new_node);
114
115
	new_node->attr.assem.input_constraints  = DUP_ARR_D(ir_asm_constraint, irg->obst, old_node->attr.assem.input_constraints);
	new_node->attr.assem.output_constraints = DUP_ARR_D(ir_asm_constraint, irg->obst, old_node->attr.assem.output_constraints);
Matthias Braun's avatar
Matthias Braun committed
116
	new_node->attr.assem.clobbers = DUP_ARR_D(ident*, irg->obst, old_node->attr.assem.clobbers);
Michael Beck's avatar
Michael Beck committed
117
118
}

Matthias Braun's avatar
Matthias Braun committed
119
120
121
122
123
124
125
126
static void switch_copy_attr(ir_graph *irg, const ir_node *old_node,
                             ir_node *new_node)
{
	const ir_switch_table *table = get_Switch_table(old_node);
	new_node->attr.switcha.table = ir_switch_table_duplicate(irg, table);
	new_node->attr.switcha.n_outs = old_node->attr.switcha.n_outs;
}

127
/**
Michael Beck's avatar
Michael Beck committed
128
129
130
131
132
133
134
 * Sets the default copy_attr operation for an ir_ops
 *
 * @param code   the opcode for the default operation
 * @param ops    the operations initialized
 *
 * @return
 *    The operations.
135
 */
136
static void firm_set_default_copy_attr(unsigned code, ir_op_ops *ops)
137
{
138
	switch (code) {
Matthias Braun's avatar
Matthias Braun committed
139
140
141
142
143
	case iro_Call:   ops->copy_attr = call_copy_attr;   break;
	case iro_Block:  ops->copy_attr = block_copy_attr;  break;
	case iro_Phi:    ops->copy_attr = phi_copy_attr;    break;
	case iro_ASM:    ops->copy_attr = ASM_copy_attr;    break;
	case iro_Switch: ops->copy_attr = switch_copy_attr; break;
Matthias Braun's avatar
Matthias Braun committed
144
	default:
Matthias Braun's avatar
Matthias Braun committed
145
		if (ops->copy_attr == NULL)
146
147
			ops->copy_attr = default_copy_attr;
	}
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
}

/*
 * Sets the default operation for an ir_ops.
 */
static void set_default_operations(unsigned code, ir_op_ops *ops)
{
	firm_set_default_hash(code, ops);
	firm_set_default_computed_value(code, ops);
	firm_set_default_equivalent_node(code, ops);
	firm_set_default_transform_node(code, ops);
	firm_set_default_node_cmp_attr(code, ops);
	firm_set_default_get_type_attr(code, ops);
	firm_set_default_get_entity_attr(code, ops);
	firm_set_default_copy_attr(code, ops);
	firm_set_default_verifier(code, ops);
	firm_set_default_reassoc(code, ops);
165
}
166

Michael Beck's avatar
Michael Beck committed
167
/* Creates a new ir operation. */
168
169
170
ir_op *new_ir_op(unsigned code, const char *name, op_pin_state p,
                 unsigned flags, op_arity opar, int op_index, size_t attr_size,
                 const ir_op_ops *ops)
Christian Schäfer's avatar
Christian Schäfer committed
171
{
172
	ir_op *res = XMALLOCZ(ir_op);
173
174
175

	res->code      = code;
	res->name      = new_id_from_chars(name, strlen(name));
176
	res->pin_state = p;
177
178
179
180
	res->attr_size = attr_size;
	res->flags     = flags;
	res->opar      = opar;
	res->op_index  = op_index;
Matthias Braun's avatar
Matthias Braun committed
181
	res->tag       = 0;
182
183

	if (ops)
184
		res->ops = *ops;
185
186
187
	else /* no given ops, set all operations to NULL */
		memset(&res->ops, 0, sizeof(res->ops));

188
	set_default_operations(code, &res->ops);
189
190
191
192
193

	add_irp_opcode(res);

	hook_new_ir_op(res);
	return res;
194
}
Christian Schäfer's avatar
Christian Schäfer committed
195

196
197
void free_ir_op(ir_op *code)
{
198
	hook_free_ir_op(code);
199

200
201
	remove_irp_opcode(code);
	free(code);
202
}
Christian Schäfer's avatar
Christian Schäfer committed
203

204
void ir_op_set_memory_index(ir_op *op, int memory_index)
Matthias Braun's avatar
Matthias Braun committed
205
{
206
207
208
209
210
211
212
	assert(op->flags & irop_flag_uses_memory);
	op->memory_index = memory_index;
}

void ir_op_set_fragile_indices(ir_op *op, int pn_x_regular, int pn_x_except)
{
	assert(op->flags & irop_flag_fragile);
Matthias Braun's avatar
Matthias Braun committed
213
214
215
216
	op->pn_x_regular = pn_x_regular;
	op->pn_x_except = pn_x_except;
}

Götz Lindenmaier's avatar
Götz Lindenmaier committed
217
/* Returns the string for the opcode. */
218
219
const char *get_op_name (const ir_op *op)
{
220
	return get_id_str(op->name);
221
}
Christian Schäfer's avatar
Christian Schäfer committed
222

223
224
unsigned (get_op_code)(const ir_op *op)
{
225
  return get_op_code_(op);
226
}
Christian Schäfer's avatar
Christian Schäfer committed
227

228
229
ident *(get_op_ident)(const ir_op *op)
{
230
  return get_op_ident_(op);
231
}
Christian Schäfer's avatar
Christian Schäfer committed
232

233
234
const char *get_op_pin_state_name(op_pin_state s)
{
235
	switch (s) {
Sebastian Hack's avatar
Sebastian Hack committed
236
#define XXX(s) case s: return #s
237
238
239
240
	XXX(op_pin_state_floats);
	XXX(op_pin_state_pinned);
	XXX(op_pin_state_exc_pinned);
	XXX(op_pin_state_mem_pinned);
Sebastian Hack's avatar
Sebastian Hack committed
241
#undef XXX
242
243
	}
	return "<none>";
244
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
245

246
247
op_pin_state (get_op_pinned)(const ir_op *op)
{
248
	return get_op_pinned_(op);
249
}
250

251
/* Sets op_pin_state_pinned in the opcode.  Setting it to floating has no effect
252
   for Phi, Block and control flow nodes. */
253
254
void set_op_pinned(ir_op *op, op_pin_state pinned)
{
255
	if (op == op_Block || op == op_Phi || is_op_cfopcode(op)) return;
256
	op->pin_state = pinned;
257
}
Michael Beck's avatar
Michael Beck committed
258

259
/* retrieve the next free opcode */
260
261
unsigned get_next_ir_opcode(void)
{
262
	return next_iro++;
263
}
264

265
/* Returns the next free n IR opcode number, allows to register a bunch of user ops */
266
267
unsigned get_next_ir_opcodes(unsigned num)
{
268
269
270
	unsigned base = next_iro;
	next_iro += num;
	return base;
271
}
272

273
/* Returns the generic function pointer from an ir operation. */
274
275
op_func (get_generic_function_ptr)(const ir_op *op)
{
276
	return get_generic_function_ptr_(op);
277
}
278
279

/* Store a generic function pointer into an ir operation. */
280
281
void (set_generic_function_ptr)(ir_op *op, op_func func)
{
282
	set_generic_function_ptr_(op, func);
283
}
Michael Beck's avatar
Michael Beck committed
284
285

/* Returns the ir_op_ops of an ir_op. */
286
287
const ir_op_ops *(get_op_ops)(const ir_op *op)
{
288
	return get_op_ops_(op);
289
}
290

291
292
irop_flags get_op_flags(const ir_op *op)
{
293
	return (irop_flags)op->flags;
294
}
295
296

#include "gen_irop.c.inl"