irop.c 7.37 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
24
/**
 * @file
 * @brief   Representation of opcode of intermediate operation.
 * @author  Christian Schaefer, Goetz Lindenmaier, Michael Beck
 * @version $Id$
Götz Lindenmaier's avatar
Götz Lindenmaier committed
25
 */
Matthias Braun's avatar
Matthias Braun committed
26
#include "config.h"
Boris Boesler's avatar
added    
Boris Boesler committed
27

28
#include <string.h>
29

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

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

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

41
42
void be_init_op(void);

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

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

56
57
	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)));
58

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

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

Michael Beck's avatar
Michael Beck committed
75
76
77
/**
 * Copies all Block attributes stored in the old node to the new node.
 */
78
79
static void block_copy_attr(ir_graph *irg, const ir_node *old_node,
                            ir_node *new_node)
80
{
81
82
83
84
85
86
87
88
89
90
91
92
	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));
	/* TODO: we should probably create a new entity. But we somehow have to
	 * patch the stuff at the same time */
	new_node->attr.block.entity            = NULL;
	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
}

119
/**
Michael Beck's avatar
Michael Beck committed
120
121
122
123
124
125
126
 * 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.
127
 */
128
static ir_op_ops *firm_set_default_copy_attr(unsigned code, ir_op_ops *ops)
129
{
130
	switch (code) {
Matthias Braun's avatar
Matthias Braun committed
131
	case iro_Call:
132
		ops->copy_attr = call_copy_attr;
Matthias Braun's avatar
Matthias Braun committed
133
134
		break;
	case iro_Block:
135
		ops->copy_attr = block_copy_attr;
Matthias Braun's avatar
Matthias Braun committed
136
137
		break;
	case iro_Phi:
138
		ops->copy_attr = phi_copy_attr;
Matthias Braun's avatar
Matthias Braun committed
139
140
		break;
	case iro_ASM:
Michael Beck's avatar
Michael Beck committed
141
		ops->copy_attr = ASM_copy_attr;
Matthias Braun's avatar
Matthias Braun committed
142
143
		break;
	default:
144
145
146
147
148
		/* not allowed to be NULL */
		if (! ops->copy_attr)
			ops->copy_attr = default_copy_attr;
	}
	return ops;
Michael Beck's avatar
Michael Beck committed
149
}  /* firm_set_default_copy_attr */
150

Michael Beck's avatar
Michael Beck committed
151
/* Creates a new ir operation. */
152
153
154
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
155
{
156
	ir_op *res = XMALLOCZ(ir_op);
157
158
159

	res->code      = code;
	res->name      = new_id_from_chars(name, strlen(name));
160
	res->pin_state = p;
161
162
163
164
	res->attr_size = attr_size;
	res->flags     = flags;
	res->opar      = opar;
	res->op_index  = op_index;
Matthias Braun's avatar
Matthias Braun committed
165
	res->tag       = 0;
166
167
168
169
170
171
172
173

	if (ops)
		memcpy(&res->ops, ops, sizeof(res->ops));
	else /* no given ops, set all operations to NULL */
		memset(&res->ops, 0, sizeof(res->ops));

	firm_set_default_operations(code, &res->ops);
	firm_set_default_copy_attr(code, &res->ops);
Matthias Braun's avatar
Matthias Braun committed
174
	firm_set_default_verifier(code, &res->ops);
175
176
177
178
179
180
	firm_set_default_reassoc(code, &res->ops);

	add_irp_opcode(res);

	hook_new_ir_op(res);
	return res;
Michael Beck's avatar
Michael Beck committed
181
}  /* new_ir_op */
Christian Schäfer's avatar
Christian Schäfer committed
182

183
184
void free_ir_op(ir_op *code)
{
185
	hook_free_ir_op(code);
186

187
188
	remove_irp_opcode(code);
	free(code);
Michael Beck's avatar
Michael Beck committed
189
}  /* free_ir_op */
Christian Schäfer's avatar
Christian Schäfer committed
190

Götz Lindenmaier's avatar
Götz Lindenmaier committed
191
/* Returns the string for the opcode. */
192
193
const char *get_op_name (const ir_op *op)
{
194
	return get_id_str(op->name);
Michael Beck's avatar
Michael Beck committed
195
}  /* get_op_name */
Christian Schäfer's avatar
Christian Schäfer committed
196

197
198
unsigned (get_op_code)(const ir_op *op)
{
199
  return _get_op_code(op);
Michael Beck's avatar
Michael Beck committed
200
}  /* get_op_code */
Christian Schäfer's avatar
Christian Schäfer committed
201

202
203
ident *(get_op_ident)(const ir_op *op)
{
204
  return _get_op_ident(op);
Michael Beck's avatar
Michael Beck committed
205
}  /* get_op_ident */
Christian Schäfer's avatar
Christian Schäfer committed
206

207
208
const char *get_op_pin_state_name(op_pin_state s)
{
209
	switch (s) {
Sebastian Hack's avatar
Sebastian Hack committed
210
#define XXX(s) case s: return #s
211
212
213
214
	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
215
#undef XXX
216
217
	}
	return "<none>";
Michael Beck's avatar
Michael Beck committed
218
}  /* get_op_pin_state_name */
Götz Lindenmaier's avatar
Götz Lindenmaier committed
219

220
221
op_pin_state (get_op_pinned)(const ir_op *op)
{
222
	return _get_op_pinned(op);
Michael Beck's avatar
Michael Beck committed
223
}  /* get_op_pinned */
224

225
/* Sets op_pin_state_pinned in the opcode.  Setting it to floating has no effect
226
   for Phi, Block and control flow nodes. */
227
228
void set_op_pinned(ir_op *op, op_pin_state pinned)
{
229
	if (op == op_Block || op == op_Phi || is_op_cfopcode(op)) return;
230
	op->pin_state = pinned;
Michael Beck's avatar
Michael Beck committed
231
}  /* set_op_pinned */
Michael Beck's avatar
Michael Beck committed
232

233
/* retrieve the next free opcode */
234
235
unsigned get_next_ir_opcode(void)
{
236
	return next_iro++;
Michael Beck's avatar
Michael Beck committed
237
}  /* get_next_ir_opcode */
238

239
/* Returns the next free n IR opcode number, allows to register a bunch of user ops */
240
241
unsigned get_next_ir_opcodes(unsigned num)
{
242
243
244
	unsigned base = next_iro;
	next_iro += num;
	return base;
Michael Beck's avatar
Michael Beck committed
245
}  /* get_next_ir_opcodes */
246

247
/* Returns the generic function pointer from an ir operation. */
248
249
op_func (get_generic_function_ptr)(const ir_op *op)
{
250
	return _get_generic_function_ptr(op);
Michael Beck's avatar
Michael Beck committed
251
}  /* get_generic_function_ptr */
252
253

/* Store a generic function pointer into an ir operation. */
254
255
void (set_generic_function_ptr)(ir_op *op, op_func func)
{
256
	_set_generic_function_ptr(op, func);
Michael Beck's avatar
Michael Beck committed
257
}  /* set_generic_function_ptr */
Michael Beck's avatar
Michael Beck committed
258
259

/* Returns the ir_op_ops of an ir_op. */
260
261
const ir_op_ops *(get_op_ops)(const ir_op *op)
{
262
	return _get_op_ops(op);
Michael Beck's avatar
Michael Beck committed
263
}  /* get_op_ops */
264

265
266
irop_flags get_op_flags(const ir_op *op)
{
267
	return (irop_flags)op->flags;
268
}
269
270

#include "gen_irop.c.inl"