bearch.c 8.6 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.
 */

20
/**
Christian Würdig's avatar
Christian Würdig committed
21
22
23
24
 * @file
 * @brief       Processor architecture specification.
 * @author      Sebastian Hack
 * @version     $Id$
25
 */
26
#include "config.h"
Michael Beck's avatar
Michael Beck committed
27

28
29
#include <string.h>

30
#include "bearch.h"
31
#include "benode.h"
32
#include "beinfo.h"
Sebastian Hack's avatar
Sebastian Hack committed
33
#include "ircons_t.h"
Daniel Grund's avatar
Daniel Grund committed
34
#include "irnode_t.h"
35
#include "irop_t.h"
36

Sebastian Hack's avatar
Sebastian Hack committed
37
#include "bitset.h"
Sebastian Hack's avatar
Sebastian Hack committed
38
#include "pset.h"
Matthias Braun's avatar
Matthias Braun committed
39
#include "raw_bitset.h"
40

Sebastian Hack's avatar
Sebastian Hack committed
41
42
#include "irprintf.h"

43
/* Initialize the architecture environment struct. */
44
arch_env_t *arch_env_init(const arch_isa_if_t *isa_if, FILE *file_handle, be_main_env_t *main_env)
45
{
46
47
48
	arch_env_t *arch_env = isa_if->init(file_handle);
	arch_env->main_env   = main_env;
	return arch_env;
Sebastian Hack's avatar
Sebastian Hack committed
49
50
51
}

/**
Sebastian Hack's avatar
Sebastian Hack committed
52
53
54
 * Get the isa responsible for a node.
 * @param irn The node to get the responsible isa for.
 * @return The irn operations given by the responsible isa.
Sebastian Hack's avatar
Sebastian Hack committed
55
 */
56
static inline const arch_irn_ops_t *get_irn_ops(const ir_node *irn)
57
{
Matthias Braun's avatar
Matthias Braun committed
58
59
60
61
62
63
64
	const ir_op          *ops;
	const arch_irn_ops_t *be_ops;

	if (is_Proj(irn)) {
		irn = get_Proj_pred(irn);
		assert(!is_Proj(irn));
	}
65

Matthias Braun's avatar
Matthias Braun committed
66
67
	ops    = get_irn_op(irn);
	be_ops = get_op_ops(ops)->be_ops;
Sebastian Hack's avatar
Sebastian Hack committed
68

Matthias Braun's avatar
Matthias Braun committed
69
	return be_ops;
70
71
}

72
const arch_register_req_t *arch_get_register_req(const ir_node *irn, int pos)
Sebastian Hack's avatar
Sebastian Hack committed
73
{
74
	if (is_Proj(irn)) {
75
76
		ir_node *pred = get_Proj_pred(irn);
		long     pn   = get_Proj_proj(irn);
77
		assert(pos == -1);
78
		return arch_get_out_register_req(pred, pn);
79
	}
80

81
	if (pos < 0) {
82
		return arch_get_out_register_req(irn, -pos-1);
83
	} else {
84
		return arch_get_in_register_req(irn, pos);
85
86
87
	}
}

88
void arch_set_frame_offset(ir_node *irn, int offset)
Sebastian Hack's avatar
Sebastian Hack committed
89
{
90
	const arch_irn_ops_t *ops = get_irn_ops(irn);
91
	ops->set_frame_offset(irn, offset);
Sebastian Hack's avatar
Sebastian Hack committed
92
93
}

94
ir_entity *arch_get_frame_entity(const ir_node *irn)
95
{
96
	const arch_irn_ops_t *ops = get_irn_ops(irn);
97
	return ops->get_frame_entity(irn);
98
99
}

100
int arch_get_sp_bias(ir_node *irn)
101
{
102
	const arch_irn_ops_t *ops = get_irn_ops(irn);
103
	return ops->get_sp_bias(irn);
104
105
}

106
arch_inverse_t *arch_get_inverse(const ir_node *irn, int i, arch_inverse_t *inverse, struct obstack *obstack)
107
{
108
	const arch_irn_ops_t *ops = get_irn_ops(irn);
Matthias Braun's avatar
Matthias Braun committed
109

110
	if (ops->get_inverse) {
111
		return ops->get_inverse(irn, i, inverse, obstack);
Matthias Braun's avatar
Matthias Braun committed
112
113
114
	} else {
		return NULL;
	}
115
116
}

117
118
int arch_possible_memory_operand(const ir_node *irn, unsigned int i)
{
119
	const arch_irn_ops_t *ops = get_irn_ops(irn);
Matthias Braun's avatar
Matthias Braun committed
120

121
	if (ops->possible_memory_operand) {
122
		return ops->possible_memory_operand(irn, i);
123
124
125
126
127
	} else {
		return 0;
	}
}

128
129
void arch_perform_memory_operand(ir_node *irn, ir_node *spill, unsigned int i)
{
130
	const arch_irn_ops_t *ops = get_irn_ops(irn);
Matthias Braun's avatar
Matthias Braun committed
131

132
	if (ops->perform_memory_operand) {
133
		ops->perform_memory_operand(irn, spill, i);
134
135
136
137
138
	} else {
		return;
	}
}

139
int arch_get_op_estimated_cost(const ir_node *irn)
140
{
141
	const arch_irn_ops_t *ops = get_irn_ops(irn);
Matthias Braun's avatar
Matthias Braun committed
142

143
	if (ops->get_op_estimated_cost) {
144
		return ops->get_op_estimated_cost(irn);
Matthias Braun's avatar
Matthias Braun committed
145
146
147
	} else {
		return 1;
	}
148
149
}

150
151
int arch_reg_is_allocatable(const ir_node *irn, int pos,
                            const arch_register_t *reg)
Sebastian Hack's avatar
Sebastian Hack committed
152
{
153
	const arch_register_req_t *req = arch_get_register_req(irn, pos);
Sebastian Hack's avatar
Sebastian Hack committed
154

155
	if (req->type == arch_register_req_type_none)
Sebastian Hack's avatar
Sebastian Hack committed
156
157
		return 0;

158
	if (arch_register_req_is(req, limited)) {
159
160
		if (arch_register_get_class(reg) != req->cls)
			return 0;
Matthias Braun's avatar
Matthias Braun committed
161
		return rbitset_is_set(req->limited, arch_register_get_index(reg));
162
163
	}

Matthias Braun's avatar
Matthias Braun committed
164
	return req->cls == reg->reg_class;
Sebastian Hack's avatar
Sebastian Hack committed
165
166
}

167
const arch_register_class_t *arch_get_irn_reg_class(const ir_node *irn, int pos)
Sebastian Hack's avatar
Sebastian Hack committed
168
{
169
	const arch_register_req_t *req = arch_get_register_req(irn, pos);
Matthias Braun's avatar
Matthias Braun committed
170
171
172
173

	assert(req->type != arch_register_req_type_none || req->cls == NULL);

	return req->cls;
Sebastian Hack's avatar
Sebastian Hack committed
174
175
}

176
static inline reg_out_info_t *get_out_info(const ir_node *node)
177
{
178
179
180
181
182
183
184
185
186
187
188
189
	int                   pos  = 0;
	const backend_info_t *info;

	assert(get_irn_mode(node) != mode_T);
	if (is_Proj(node)) {
		pos  = get_Proj_proj(node);
		node = get_Proj_pred(node);
	}

	info = be_get_info(node);
	assert(pos >= 0 && pos < ARR_LEN(info->out_infos));
	return &info->out_infos[pos];
190
}
191

192
193

static inline reg_out_info_t *get_out_info_n(const ir_node *node, int pos)
194
{
195
196
197
198
	const backend_info_t *info = be_get_info(node);
	assert(!is_Proj(node));
	assert(pos >= 0 && pos < ARR_LEN(info->out_infos));
	return &info->out_infos[pos];
199
}
200

201
202

const arch_register_t *arch_get_irn_register(const ir_node *node)
203
{
204
205
	const reg_out_info_t *out = get_out_info(node);
	return out->reg;
206
}
Sebastian Hack's avatar
Sebastian Hack committed
207

208
const arch_register_t *arch_irn_get_register(const ir_node *node, int pos)
Sebastian Hack's avatar
Sebastian Hack committed
209
{
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
	const reg_out_info_t *out = get_out_info_n(node, pos);
	return out->reg;
}

void arch_irn_set_register(ir_node *node, int pos, const arch_register_t *reg)
{
	reg_out_info_t *out = get_out_info_n(node, pos);
	out->reg            = reg;
}

void arch_set_irn_register(ir_node *node, const arch_register_t *reg)
{
	reg_out_info_t *out = get_out_info(node);
	out->reg = reg;
}

arch_irn_class_t arch_irn_classify(const ir_node *node)
{
	const arch_irn_ops_t *ops = get_irn_ops(node);
	return ops->classify(node);
}

arch_irn_flags_t arch_irn_get_flags(const ir_node *node)
{
	backend_info_t *info = be_get_info(node);
	return info->flags;
}

void arch_irn_set_flags(ir_node *node, arch_irn_flags_t flags)
{
	backend_info_t *info = be_get_info(node);
	info->flags = flags;
}

void arch_irn_add_flags(ir_node *node, arch_irn_flags_t flags)
{
	backend_info_t *info = be_get_info(node);
	info->flags |= flags;
Sebastian Hack's avatar
Sebastian Hack committed
248
}
Sebastian Hack's avatar
Sebastian Hack committed
249

250
251
void arch_dump_register_req(FILE *F, const arch_register_req_t *req,
                            const ir_node *node)
Sebastian Hack's avatar
Sebastian Hack committed
252
{
253
254
255
256
257
258
	if (req == NULL || req->type == arch_register_req_type_none) {
		fprintf(F, "n/a");
		return;
	}

	fprintf(F, "%s", req->cls->name);
Sebastian Hack's avatar
Sebastian Hack committed
259

260
	if (arch_register_req_is(req, limited)) {
Matthias Braun's avatar
Matthias Braun committed
261
262
263
		unsigned n_regs = req->cls->n_regs;
		unsigned i;

264
		fprintf(F, " limited to");
265
266
		for (i = 0; i < n_regs; ++i) {
			if (rbitset_is_set(req->limited, i)) {
Matthias Braun's avatar
Matthias Braun committed
267
				const arch_register_t *reg = &req->cls->regs[i];
268
				fprintf(F, " %s", reg->name);
Matthias Braun's avatar
Matthias Braun committed
269
			}
Sebastian Hack's avatar
Sebastian Hack committed
270
271
272
		}
	}

273
	if (arch_register_req_is(req, should_be_same)) {
274
275
276
		const unsigned other = req->other_same;
		int i;

277
		fprintf(F, " same as");
278
279
		for (i = 0; 1U << i <= other; ++i) {
			if (other & (1U << i)) {
280
				ir_fprintf(F, " %+F", get_irn_n(skip_Proj_const(node), i));
281
			}
282
		}
Sebastian Hack's avatar
Sebastian Hack committed
283
284
	}

285
	if (arch_register_req_is(req, must_be_different)) {
286
287
288
		const unsigned other = req->other_different;
		int i;

289
		fprintf(F, " different from");
290
291
		for (i = 0; 1U << i <= other; ++i) {
			if (other & (1U << i)) {
292
				ir_fprintf(F, " %+F", get_irn_n(skip_Proj_const(node), i));
293
294
			}
		}
Sebastian Hack's avatar
Sebastian Hack committed
295
296
	}

297
298
299
300
301
302
	if (req->width != 1) {
		fprintf(F, " width:%u", req->width);
	}
	if (arch_register_req_is(req, aligned)) {
		fprintf(F, " aligned");
	}
303
	if (arch_register_req_is(req, ignore)) {
304
		fprintf(F, " ignore");
305
306
	}
	if (arch_register_req_is(req, produces_sp)) {
307
		fprintf(F, " produces_sp");
308
	}
Sebastian Hack's avatar
Sebastian Hack committed
309
}
Matthias Braun's avatar
Matthias Braun committed
310

311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
void arch_dump_reqs_and_registers(FILE *F, const ir_node *node)
{
	int              n_ins  = get_irn_arity(node);
	int              n_outs = arch_irn_get_n_outs(node);
	arch_irn_flags_t flags  = arch_irn_get_flags(node);
	int              i;

	for (i = 0; i < n_ins; ++i) {
		const arch_register_req_t *req = arch_get_in_register_req(node, i);
		fprintf(F, "inreq #%d = ", i);
		arch_dump_register_req(F, req, node);
		fputs("\n", F);
	}
	for (i = 0; i < n_outs; ++i) {
		const arch_register_req_t *req = arch_get_out_register_req(node, i);
		fprintf(F, "outreq #%d = ", i);
		arch_dump_register_req(F, req, node);
		fputs("\n", F);
	}
	for (i = 0; i < n_outs; ++i) {
		const arch_register_t     *reg = arch_irn_get_register(node, i);
		const arch_register_req_t *req = arch_get_out_register_req(node, i);
		if (req->cls == NULL)
			continue;
		fprintf(F, "reg #%d = %s\n", i, reg != NULL ? reg->name : "n/a");
	}

	fprintf(F, "flags =");
	if (flags == arch_irn_flags_none) {
		fprintf(F, " none");
	} else {
		if (flags & arch_irn_flags_dont_spill) {
			fprintf(F, " unspillable");
		}
		if (flags & arch_irn_flags_rematerializable) {
			fprintf(F, " remat");
		}
		if (flags & arch_irn_flags_modify_flags) {
			fprintf(F, " modify_flags");
		}
	}
	fprintf(F, " (%d)\n", flags);
}

Matthias Braun's avatar
Matthias Braun committed
355
356
357
358
static const arch_register_req_t no_requirement = {
	arch_register_req_type_none,
	NULL,
	NULL,
359
	0,
360
	0,
361
	0
Matthias Braun's avatar
Matthias Braun committed
362
363
};
const arch_register_req_t *arch_no_register_req = &no_requirement;