bearch.c 8.79 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
79
80
	const arch_irn_ops_t *ops;

	if (is_Proj(irn)) {
		assert(pos == -1);
		pos = -1-get_Proj_proj(irn);
		irn = get_Proj_pred(irn);
	}
81
	ops = get_irn_ops_simple(irn);
82
83
84
85
86
87
88
	if (pos < 0) {
		return ops->get_irn_reg_req_out(irn, -pos-1);
	} else {
		return ops->get_irn_reg_req_in(irn, pos);
	}
}

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

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

101
void arch_set_frame_entity(ir_node *irn, ir_entity *ent)
102
{
103
	const arch_irn_ops_t *ops = get_irn_ops(irn);
104
	ops->set_frame_entity(irn, ent);
105
106
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

209
210

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

218
219

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

225
const arch_register_t *arch_irn_get_register(const ir_node *node, int pos)
Sebastian Hack's avatar
Sebastian Hack committed
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
264
	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
265
}
Sebastian Hack's avatar
Sebastian Hack committed
266

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

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

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

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

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

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

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

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