bearch.c 6.02 KB
Newer Older
1
2
3
4
5
6
7
/**
 * Processor architecture specification.
 * @author Sebastian Hack
 * @date 11.2.2005
 *
 * $Id$
 */
Sebastian Hack's avatar
Sebastian Hack committed
8

Michael Beck's avatar
Michael Beck committed
9
10
11
12
13
14
15
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
Daniel Grund's avatar
Daniel Grund committed
16

Michael Beck's avatar
Michael Beck committed
17
18
19
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
20

21
22
#include <string.h>

Michael Beck's avatar
Michael Beck committed
23
#include "bearch.h"
Sebastian Hack's avatar
Sebastian Hack committed
24
#include "ircons_t.h"
Daniel Grund's avatar
Daniel Grund committed
25
#include "irnode_t.h"
26

Sebastian Hack's avatar
Sebastian Hack committed
27
#include "bitset.h"
Sebastian Hack's avatar
Sebastian Hack committed
28
#include "pset.h"
29
30
#include "entity.h"

Sebastian Hack's avatar
Sebastian Hack committed
31
32
#include "irprintf.h"

33
34
/* Initialize the architecture environment struct. */
arch_env_t *arch_env_init(arch_env_t *env, const arch_isa_if_t *isa_if, FILE *file_handle)
35
{
Sebastian Hack's avatar
Sebastian Hack committed
36
  memset(env, 0, sizeof(*env));
37
  env->isa = isa_if->init(file_handle);
Sebastian Hack's avatar
Sebastian Hack committed
38
  return env;
Sebastian Hack's avatar
Sebastian Hack committed
39
40
}

41
arch_env_t *arch_env_push_irn_handler(arch_env_t *env,
Sebastian Hack's avatar
Sebastian Hack committed
42
    const arch_irn_handler_t *handler)
Sebastian Hack's avatar
Sebastian Hack committed
43
{
Sebastian Hack's avatar
Sebastian Hack committed
44
45
46
  assert(env->handlers_tos <= ARCH_MAX_HANDLERS);
  env->handlers[env->handlers_tos++] = handler;
  return env;
47
48
}

49
50
51
52
53
54
const arch_irn_handler_t *arch_env_pop_irn_handler(arch_env_t *env)
{
  assert(env->handlers_tos > 0 && env->handlers_tos <= ARCH_MAX_HANDLERS);
  return env->handlers[--env->handlers_tos];
}

Sebastian Hack's avatar
Sebastian Hack committed
55
static const arch_irn_ops_t *fallback_irn_ops = NULL;
Sebastian Hack's avatar
Sebastian Hack committed
56

Sebastian Hack's avatar
Sebastian Hack committed
57
int arch_register_class_put(const arch_register_class_t *cls, bitset_t *bs)
58
{
Sebastian Hack's avatar
Sebastian Hack committed
59
60
61
62
63
  if(bs) {
    int i, n;
    for(i = 0, n = cls->n_regs; i < n; ++i)
      bitset_set(bs, i);
  }
64

Sebastian Hack's avatar
Sebastian Hack committed
65
  return cls->n_regs;
66
67
}

Sebastian Hack's avatar
Sebastian Hack committed
68
/**
Sebastian Hack's avatar
Sebastian Hack committed
69
70
71
72
 * Get the isa responsible for a node.
 * @param env The arch environment with the isa stack.
 * @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
73
 */
Sebastian Hack's avatar
Sebastian Hack committed
74
75
static INLINE const arch_irn_ops_t *
get_irn_ops(const arch_env_t *env, const ir_node *irn)
76
{
Sebastian Hack's avatar
Sebastian Hack committed
77
  int i;
78

Sebastian Hack's avatar
Sebastian Hack committed
79
  for(i = env->handlers_tos - 1; i >= 0; --i) {
Sebastian Hack's avatar
Sebastian Hack committed
80
81
82
    const arch_irn_handler_t *handler = env->handlers[i];
    const arch_irn_ops_t *ops = handler->get_irn_ops(handler, irn);

Sebastian Hack's avatar
Sebastian Hack committed
83
84
85
    if(ops)
      return ops;
  }
Sebastian Hack's avatar
Sebastian Hack committed
86

Sebastian Hack's avatar
Sebastian Hack committed
87
  return fallback_irn_ops;
88
89
}

Sebastian Hack's avatar
Sebastian Hack committed
90
91
92
93
const arch_register_req_t *arch_get_register_req(const arch_env_t *env,
    arch_register_req_t *req, const ir_node *irn, int pos)
{
  const arch_irn_ops_t *ops = get_irn_ops(env, irn);
Sebastian Hack's avatar
Sebastian Hack committed
94
  req->type = arch_register_req_type_none;
95
  return ops->impl->get_irn_reg_req(ops, req, irn, pos);
Sebastian Hack's avatar
Sebastian Hack committed
96
97
}

98
void arch_set_frame_offset(const arch_env_t *env, ir_node *irn, int offset)
Sebastian Hack's avatar
Sebastian Hack committed
99
100
{
  const arch_irn_ops_t *ops = get_irn_ops(env, irn);
101
  ops->impl->set_frame_offset(ops, irn, offset);
Sebastian Hack's avatar
Sebastian Hack committed
102
103
}

104
105
106
107
108
109
entity *arch_get_frame_entity(const arch_env_t *env, ir_node *irn)
{
  const arch_irn_ops_t *ops = get_irn_ops(env, irn);
  return ops->impl->get_frame_entity(ops, irn);
}

Sebastian Hack's avatar
Sebastian Hack committed
110

Sebastian Hack's avatar
Sebastian Hack committed
111
int arch_get_allocatable_regs(const arch_env_t *env, const ir_node *irn, int pos, bitset_t *bs)
Sebastian Hack's avatar
Sebastian Hack committed
112
{
Sebastian Hack's avatar
Sebastian Hack committed
113
  arch_register_req_t local_req;
Sebastian Hack's avatar
Sebastian Hack committed
114
  const arch_irn_ops_t *ops = get_irn_ops(env, irn);
115
  const arch_register_req_t *req = ops->impl->get_irn_reg_req(ops, &local_req, irn, pos);
Sebastian Hack's avatar
Sebastian Hack committed
116

Sebastian Hack's avatar
Sebastian Hack committed
117
  if(req->type == arch_register_req_type_none) {
Sebastian Hack's avatar
Sebastian Hack committed
118
119
	  bitset_clear_all(bs);
	  return 0;
Sebastian Hack's avatar
Sebastian Hack committed
120
  }
Sebastian Hack's avatar
Sebastian Hack committed
121

Sebastian Hack's avatar
Sebastian Hack committed
122
  if(arch_register_req_is(req, limited)) {
Sebastian Hack's avatar
Sebastian Hack committed
123
	  req->limited(req->limited_env, bs);
Sebastian Hack's avatar
Sebastian Hack committed
124
125
	  return bitset_popcnt(bs);
  }
Sebastian Hack's avatar
Sebastian Hack committed
126
127
128

  arch_register_class_put(req->cls, bs);
  return req->cls->n_regs;
Sebastian Hack's avatar
Sebastian Hack committed
129
130
}

Sebastian Hack's avatar
Sebastian Hack committed
131
132
133
134
135
136
137
138
139
140
void arch_put_non_ignore_regs(const arch_env_t *env, const arch_register_class_t *cls, bitset_t *bs)
{
	int i;

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

141
142
143
int arch_is_register_operand(const arch_env_t *env,
    const ir_node *irn, int pos)
{
Sebastian Hack's avatar
Sebastian Hack committed
144
145
	arch_register_req_t local_req;
	const arch_irn_ops_t *ops = get_irn_ops(env, irn);
146
	const arch_register_req_t *req = ops->impl->get_irn_reg_req(ops, &local_req, irn, pos);
Sebastian Hack's avatar
Sebastian Hack committed
147
	return req != NULL;
148
149
}

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

	arch_get_register_req(env, &req, irn, pos);
Sebastian Hack's avatar
Sebastian Hack committed
156
157
158
159
160
161

	if(req.type == arch_register_req_type_none)
		return 0;

	if(arch_register_req_is(&req, limited)) {
		bitset_t *bs = bitset_alloca(req.cls->n_regs);
Sebastian Hack's avatar
Sebastian Hack committed
162
		req.limited(req.limited_env, bs);
Sebastian Hack's avatar
Sebastian Hack committed
163
		return bitset_is_set(bs, arch_register_get_index(reg));
164
165
	}

Sebastian Hack's avatar
Sebastian Hack committed
166
	return req.cls == reg->reg_class;
Sebastian Hack's avatar
Sebastian Hack committed
167
168
}

Sebastian Hack's avatar
Sebastian Hack committed
169
170
const arch_register_class_t *
arch_get_irn_reg_class(const arch_env_t *env, const ir_node *irn, int pos)
Sebastian Hack's avatar
Sebastian Hack committed
171
{
Sebastian Hack's avatar
Sebastian Hack committed
172
  arch_register_req_t local_req;
Sebastian Hack's avatar
Sebastian Hack committed
173
  const arch_irn_ops_t *ops = get_irn_ops(env, irn);
174
  const arch_register_req_t *req = ops->impl->get_irn_reg_req(ops, &local_req, irn, pos);
Sebastian Hack's avatar
Sebastian Hack committed
175
  return req ? req->cls : NULL;
Sebastian Hack's avatar
Sebastian Hack committed
176
177
}

Sebastian Hack's avatar
Sebastian Hack committed
178
extern const arch_register_t *
Sebastian Hack's avatar
Sebastian Hack committed
179
arch_get_irn_register(const arch_env_t *env, const ir_node *irn)
180
{
Sebastian Hack's avatar
Sebastian Hack committed
181
  const arch_irn_ops_t *ops = get_irn_ops(env, irn);
182
  return ops->impl->get_irn_reg(ops, irn);
183
}
184

Sebastian Hack's avatar
Sebastian Hack committed
185
extern void arch_set_irn_register(const arch_env_t *env,
Sebastian Hack's avatar
Sebastian Hack committed
186
    ir_node *irn, const arch_register_t *reg)
187
{
Sebastian Hack's avatar
Sebastian Hack committed
188
  const arch_irn_ops_t *ops = get_irn_ops(env, irn);
189
  ops->impl->set_irn_reg(ops, irn, reg);
190
}
191
192
193
194

extern arch_irn_class_t arch_irn_classify(const arch_env_t *env, const ir_node *irn)
{
  const arch_irn_ops_t *ops = get_irn_ops(env, irn);
195
  return ops->impl->classify(ops, irn);
196
}
Sebastian Hack's avatar
Sebastian Hack committed
197
198
199
200

extern arch_irn_flags_t arch_irn_get_flags(const arch_env_t *env, const ir_node *irn)
{
  const arch_irn_ops_t *ops = get_irn_ops(env, irn);
201
  return ops->impl->get_flags(ops, irn);
Sebastian Hack's avatar
Sebastian Hack committed
202
}
Sebastian Hack's avatar
Sebastian Hack committed
203
204
205
206
207
208
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

extern const char *arch_irn_flag_str(arch_irn_flags_t fl)
{
	switch(fl) {
#define XXX(x) case arch_irn_flags_ ## x: return #x;
		XXX(dont_spill);
		XXX(ignore);
		XXX(rematerializable);
		XXX(none);
#undef XXX
	}
	return "n/a";
}

extern char *arch_register_req_format(char *buf, size_t len, const arch_register_req_t *req)
{
	char tmp[128];
	snprintf(buf, len, "class: %s", req->cls->name);

	if(arch_register_req_is(req, limited)) {
		bitset_pos_t elm;
		bitset_t *bs = bitset_alloca(req->cls->n_regs);
		req->limited(req->limited_env, bs);
		strncat(buf, " limited:", len);
		bitset_foreach(bs, elm) {
			strncat(buf, " ", len);
			strncat(buf, req->cls->regs[elm].name, len);
		}
	}

	if(arch_register_req_is(req, should_be_same)) {
Sebastian Hack's avatar
Sebastian Hack committed
234
		ir_snprintf(tmp, sizeof(tmp), " same to: %+F", req->other_different);
Sebastian Hack's avatar
Sebastian Hack committed
235
236
237
238
		strncat(buf, tmp, len);
	}

	if(arch_register_req_is(req, should_be_different)) {
Sebastian Hack's avatar
Sebastian Hack committed
239
		ir_snprintf(tmp, sizeof(tmp), " different to: %+F", req->other_different);
Sebastian Hack's avatar
Sebastian Hack committed
240
241
242
243
244
		strncat(buf, tmp, len);
	}

	return buf;
}