bearch.c 8.78 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
75
76
77
78
	if (is_Proj(irn)) {
		assert(pos == -1);
		pos = -1-get_Proj_proj(irn);
		irn = get_Proj_pred(irn);
	}
79

80
	if (pos < 0) {
81
		return arch_get_out_register_req(irn, -pos-1);
82
	} else {
83
		const arch_irn_ops_t *ops = get_irn_ops_simple(irn);
84
85
86
87
		return ops->get_irn_reg_req_in(irn, pos);
	}
}

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
void arch_set_frame_entity(ir_node *irn, ir_entity *ent)
101
{
102
	const arch_irn_ops_t *ops = get_irn_ops(irn);
103
	ops->set_frame_entity(irn, ent);
104
105
}

106
int arch_get_sp_bias(ir_node *irn)
107
{
108
	const arch_irn_ops_t *ops = get_irn_ops(irn);
109
	return ops->get_sp_bias(irn);
110
111
}

112
arch_inverse_t *arch_get_inverse(const ir_node *irn, int i, arch_inverse_t *inverse, struct obstack *obstack)
113
{
114
	const arch_irn_ops_t *ops = get_irn_ops(irn);
Matthias Braun's avatar
Matthias Braun committed
115

Matthias Braun's avatar
Matthias Braun committed
116
	if(ops->get_inverse) {
117
		return ops->get_inverse(irn, i, inverse, obstack);
Matthias Braun's avatar
Matthias Braun committed
118
119
120
	} else {
		return NULL;
	}
121
122
}

123
124
int arch_possible_memory_operand(const ir_node *irn, unsigned int i)
{
125
	const arch_irn_ops_t *ops = get_irn_ops(irn);
Matthias Braun's avatar
Matthias Braun committed
126

Matthias Braun's avatar
Matthias Braun committed
127
	if(ops->possible_memory_operand) {
128
		return ops->possible_memory_operand(irn, i);
129
130
131
132
133
	} else {
		return 0;
	}
}

134
135
void arch_perform_memory_operand(ir_node *irn, ir_node *spill, unsigned int i)
{
136
	const arch_irn_ops_t *ops = get_irn_ops(irn);
Matthias Braun's avatar
Matthias Braun committed
137

Matthias Braun's avatar
Matthias Braun committed
138
	if(ops->perform_memory_operand) {
139
		ops->perform_memory_operand(irn, spill, i);
140
141
142
143
144
	} else {
		return;
	}
}

145
int arch_get_op_estimated_cost(const ir_node *irn)
146
{
147
	const arch_irn_ops_t *ops = get_irn_ops(irn);
Matthias Braun's avatar
Matthias Braun committed
148

Matthias Braun's avatar
Matthias Braun committed
149
	if(ops->get_op_estimated_cost) {
150
		return ops->get_op_estimated_cost(irn);
Matthias Braun's avatar
Matthias Braun committed
151
152
153
	} else {
		return 1;
	}
154
155
}

156
void arch_put_non_ignore_regs(const arch_register_class_t *cls, bitset_t *bs)
Sebastian Hack's avatar
Sebastian Hack committed
157
{
158
	unsigned i;
Sebastian Hack's avatar
Sebastian Hack committed
159
160
161
162
163
164
165

	for(i = 0; i < cls->n_regs; ++i) {
		if(!arch_register_type_is(&cls->regs[i], ignore))
			bitset_set(bs, i);
	}
}

166
167
int arch_reg_is_allocatable(const ir_node *irn, int pos,
                            const arch_register_t *reg)
Sebastian Hack's avatar
Sebastian Hack committed
168
{
169
	const arch_register_req_t *req = arch_get_register_req(irn, pos);
Sebastian Hack's avatar
Sebastian Hack committed
170

Matthias Braun's avatar
Matthias Braun committed
171
	if(req->type == arch_register_req_type_none)
Sebastian Hack's avatar
Sebastian Hack committed
172
173
		return 0;

Matthias Braun's avatar
Matthias Braun committed
174
	if(arch_register_req_is(req, limited)) {
175
176
		if (arch_register_get_class(reg) != req->cls)
			return 0;
Matthias Braun's avatar
Matthias Braun committed
177
		return rbitset_is_set(req->limited, arch_register_get_index(reg));
178
179
	}

Matthias Braun's avatar
Matthias Braun committed
180
	return req->cls == reg->reg_class;
Sebastian Hack's avatar
Sebastian Hack committed
181
182
}

183
const arch_register_class_t *arch_get_irn_reg_class(const ir_node *irn, int pos)
Sebastian Hack's avatar
Sebastian Hack committed
184
{
185
	const arch_register_req_t *req = arch_get_register_req(irn, pos);
Matthias Braun's avatar
Matthias Braun committed
186
187
188
189

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

	return req->cls;
Sebastian Hack's avatar
Sebastian Hack committed
190
191
}

192
static inline reg_out_info_t *get_out_info(const ir_node *node)
193
{
194
195
196
197
198
199
200
201
202
203
204
205
	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];
206
}
207

208
209

static inline reg_out_info_t *get_out_info_n(const ir_node *node, int pos)
210
{
211
212
213
214
	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];
215
}
216

217
218

const arch_register_t *arch_get_irn_register(const ir_node *node)
219
{
220
221
	const reg_out_info_t *out = get_out_info(node);
	return out->reg;
222
}
Sebastian Hack's avatar
Sebastian Hack committed
223

224
const arch_register_t *arch_irn_get_register(const ir_node *node, int pos)
Sebastian Hack's avatar
Sebastian Hack committed
225
{
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
	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
264
}
Sebastian Hack's avatar
Sebastian Hack committed
265

266
267
void arch_dump_register_req(FILE *F, const arch_register_req_t *req,
                            const ir_node *node)
Sebastian Hack's avatar
Sebastian Hack committed
268
{
269
270
271
272
273
274
	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
275
276

	if(arch_register_req_is(req, limited)) {
Matthias Braun's avatar
Matthias Braun committed
277
278
279
		unsigned n_regs = req->cls->n_regs;
		unsigned i;

280
		fprintf(F, " limited to");
Matthias Braun's avatar
Matthias Braun committed
281
282
283
		for(i = 0; i < n_regs; ++i) {
			if(rbitset_is_set(req->limited, i)) {
				const arch_register_t *reg = &req->cls->regs[i];
284
				fprintf(F, " %s", reg->name);
Matthias Braun's avatar
Matthias Braun committed
285
			}
Sebastian Hack's avatar
Sebastian Hack committed
286
287
288
289
		}
	}

	if(arch_register_req_is(req, should_be_same)) {
290
291
292
		const unsigned other = req->other_same;
		int i;

293
		fprintf(F, " same as");
294
295
		for (i = 0; 1U << i <= other; ++i) {
			if (other & (1U << i)) {
296
				ir_fprintf(F, " %+F", get_irn_n(skip_Proj_const(node), i));
297
			}
298
		}
Sebastian Hack's avatar
Sebastian Hack committed
299
300
	}

301
	if (arch_register_req_is(req, must_be_different)) {
302
303
304
		const unsigned other = req->other_different;
		int i;

305
		fprintf(F, " different from");
306
307
		for (i = 0; 1U << i <= other; ++i) {
			if (other & (1U << i)) {
308
				ir_fprintf(F, " %+F", get_irn_n(skip_Proj_const(node), i));
309
310
			}
		}
Sebastian Hack's avatar
Sebastian Hack committed
311
312
	}

313
	if (arch_register_req_is(req, ignore)) {
314
		fprintf(F, " ignore");
315
316
	}
	if (arch_register_req_is(req, produces_sp)) {
317
		fprintf(F, " produces_sp");
318
	}
Sebastian Hack's avatar
Sebastian Hack committed
319
}
Matthias Braun's avatar
Matthias Braun committed
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
355
356
357
358
359
360
361
362
363
364
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
365
366
367
368
static const arch_register_req_t no_requirement = {
	arch_register_req_type_none,
	NULL,
	NULL,
369
370
	0,
	0
Matthias Braun's avatar
Matthias Braun committed
371
372
};
const arch_register_req_t *arch_no_register_req = &no_requirement;