irtools.c 6.17 KB
Newer Older
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 *
 * 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.
 */

/**
 * @file
 * @brief     Some often needed tool-functions
 * @author    Michael Beck
 * @version   $Id$
25
 */
Matthias Braun's avatar
Matthias Braun committed
26
#include "config.h"
27

28
29
#include "pset.h"

30
31
#include <stdlib.h>
#include "irnode_t.h"
Michael Beck's avatar
Michael Beck committed
32
#include "irbackedge_t.h"
33
#include "irtools.h"
34
#include "irprintf.h"
35
#include "irpass_t.h"
36
37
38

/* the famous clear_link implementation. */
void firm_clear_link(ir_node *n, void *env) {
Michael Beck's avatar
Michael Beck committed
39
40
	(void) env;
	set_irn_link(n, NULL);
41
}
Michael Beck's avatar
Michael Beck committed
42

43
44
45
46
47
48
49
50
51
52
/* the famous clear_node_and_phi_links() implementation. */
void firm_clear_node_and_phi_links(ir_node *n, void *env) {
	(void) env;
	set_irn_link(n, NULL);
	if (is_Block(n))
		set_Block_phis(n, NULL);
	else if (is_Phi(n))
		set_Phi_next(n, NULL);
}

Michael Beck's avatar
Michael Beck committed
53
/*
Michael Beck's avatar
Michael Beck committed
54
55
56
57
58
59
60
61
 * Copies a node to a new irg. The Ins of the new node point to
 * the predecessors on the old irg.  n->link points to the new node.
 *
 * Does NOT copy standard nodes like Start, End etc that are fixed
 * in an irg. Instead, the corresponding nodes of the new irg are returned.
 * Note further, that the new nodes have no block.
 */
void
Michael Beck's avatar
Michael Beck committed
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
copy_irn_to_irg(ir_node *n, ir_graph *irg) {
	ir_op *op = get_irn_op(n);
	ir_graph *old_irg;
	ir_node *nn = NULL;

	/* do not copy standard nodes */
	if (op == op_Bad)
		nn = get_irg_bad(irg);
	else if (op == op_NoMem)
		n = get_irg_no_mem(irg);
	else if (op == op_Block) {
		old_irg = get_irn_irg(n);

		if (n == get_irg_start_block(old_irg))
			nn = get_irg_start_block(irg);
		else if (n == get_irg_end_block(old_irg))
			nn = get_irg_end_block(irg);
	}
	else if (op == op_Start)
		nn = get_irg_start(irg);
	else if (op == op_End)
		nn = get_irg_end(irg);
	else if (op == op_Proj) {
		old_irg = get_irn_irg(n);

87
88
89
		if (n == get_irg_initial_exec(old_irg))
			nn = get_irg_initial_exec(irg);
		else if (n == get_irg_frame(old_irg))
Michael Beck's avatar
Michael Beck committed
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
			nn = get_irg_frame(irg);
		else if (n == get_irg_initial_mem(old_irg))
			nn = get_irg_initial_mem(irg);
		else if (n == get_irg_args(old_irg))
			nn = get_irg_args(irg);
	}

	if (nn) {
		set_irn_link(n, nn);
		return;
	}

	nn = new_ir_node(get_irn_dbg_info(n),
	                 irg,
	                 NULL,            /* no block yet, will be set later */
	                 op,
	                 get_irn_mode(n),
	                 get_irn_arity(n),
	                 get_irn_in(n) + 1);


	/* Copy the attributes.  These might point to additional data.  If this
	   was allocated on the old obstack the pointers now are dangling.  This
	   frees e.g. the memory of the graph_arr allocated in new_immBlock. */
	copy_node_attr(n, nn);
	new_backedge_info(nn);
	set_irn_link(n, nn);

	/* fix the irg for blocks */
Michael Beck's avatar
Michael Beck committed
119
	if (is_Block(nn)) {
120
		nn->attr.block.irg.irg = irg;
Michael Beck's avatar
Michael Beck committed
121
122
123
124

		/* we cannot allow blocks WITHOUT macroblock input */
		set_Block_MacroBlock(nn, get_Block_MacroBlock(n));
	}
Michael Beck's avatar
Michael Beck committed
125
}
Michael Beck's avatar
Michael Beck committed
126
127
128

/*
 * Creates an exact copy of a node.
Christoph Mallon's avatar
Christoph Mallon committed
129
 * The copy resides in the same graph in the same block.
Michael Beck's avatar
Michael Beck committed
130
 */
Christoph Mallon's avatar
Christoph Mallon committed
131
ir_node *exact_copy(const ir_node *n) {
132
133
134
135
	ir_graph *irg = get_irn_irg(n);
	ir_node *res, *block = NULL;

	if (is_no_Block(n))
Michael Beck's avatar
Michael Beck committed
136
		block = get_nodes_block(n);
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

	res = new_ir_node(get_irn_dbg_info(n),
		irg,
		block,
		get_irn_op(n),
		get_irn_mode(n),
		get_irn_arity(n),
		get_irn_in(n) + 1);


	/* Copy the attributes.  These might point to additional data.  If this
	   was allocated on the old obstack the pointers now are dangling.  This
	   frees e.g. the memory of the graph_arr allocated in new_immBlock. */
	copy_node_attr(n, res);
	new_backedge_info(res);
Michael Beck's avatar
Michael Beck committed
152
153
154
155

	if (is_Block(n)) {
		set_Block_MacroBlock(res, get_Block_MacroBlock(n));
	}
156
	return res;
Michael Beck's avatar
Michael Beck committed
157
}
158

Michael Beck's avatar
Michael Beck committed
159
160
161
/*
 * Dump a pset containing Firm objects.
 */
Michael Beck's avatar
Michael Beck committed
162
void firm_pset_dump(pset *set) {
163
164
165
166
167
168
	void *obj;

	foreach_pset(set, obj) {
		ir_fprintf(stderr, "%+F\n", obj);
	}
}
169
170
171
172

/**
 * Wrapper for running void function(ir_graph *irg) as an ir_graph pass.
 */
173
static int void_graph_wrapper(ir_graph *irg, void *context) {
174
175
176
	void (*function)(ir_graph *irg) = context;
	function(irg);
	return 0;
177
}  /* void_graph_wrapper */
178
179
180

/* Creates an ir_graph pass for running void function(ir_graph *irg). */
ir_graph_pass_t *def_graph_pass(
181
	const char *name, void (*function)(ir_graph *irg))
182
183
184
{
	struct ir_graph_pass_t *pass = XMALLOCZ(ir_graph_pass_t);

185
186
	pass->kind       = k_ir_graph_pass;
	pass->run_on_irg = void_graph_wrapper;
187
188
189
190
191
192
193
194
195
196
197
	pass->context    = function;
	pass->name       = name;

	INIT_LIST_HEAD(&pass->list);

	return pass;
}  /* def_graph_pass */

/**
 * Wrapper for running void function(ir_graph *irg) as an ir_graph pass.
 */
198
static int int_graph_wrapper(ir_graph *irg, void *context) {
199
200
	int (*function)(ir_graph *irg) = context;
	return function(irg);
201
}  /* int_graph_wrapper */
202
203
204

/* Creates an ir_graph pass for running void function(ir_graph *irg). */
ir_graph_pass_t *def_graph_pass_ret(
205
		const char *name, int (*function)(ir_graph *irg))
206
207
208
{
	struct ir_graph_pass_t *pass = XMALLOCZ(ir_graph_pass_t);

209
210
	pass->kind       = k_ir_graph_pass;
	pass->run_on_irg = int_graph_wrapper;
211
212
213
214
215
216
217
	pass->context    = function;
	pass->name       = name;

	INIT_LIST_HEAD(&pass->list);

	return pass;
}  /* def_graph_pass_ret */
218
219
220
221
222
223
224
225
226
227
228
229
230
231

/**
 * Wrapper for running void function(void) as an ir_prog pass.
 */
static int void_prog_wrapper(ir_prog *irp, void *context) {
	void (*function)(void) = context;

	(void)irp;
	function();
	return 0;
}  /* void_graph_wrapper */

/* Creates an ir_prog pass for running void function(void). */
ir_prog_pass_t *def_prog_pass(
232
	const char *name,
233
234
235
236
237
238
239
240
241
242
243
244
245
	void (*function)(void))
{
	struct ir_prog_pass_t *pass = XMALLOCZ(ir_prog_pass_t);

	pass->kind          = k_ir_prog_pass;
	pass->run_on_irprog = void_prog_wrapper;
	pass->context       = function;
	pass->name          = name;

	INIT_LIST_HEAD(&pass->list);

	return pass;
}  /* def_prog_pass */