bearch.c 5.89 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"
25

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

Sebastian Hack's avatar
Sebastian Hack committed
30
arch_env_t *arch_env_init(arch_env_t *env, const arch_isa_if_t *isa_if)
31
{
Sebastian Hack's avatar
Sebastian Hack committed
32
  memset(env, 0, sizeof(*env));
Sebastian Hack's avatar
Sebastian Hack committed
33
  env->isa = isa_if->init();
Sebastian Hack's avatar
Sebastian Hack committed
34
  return env;
Sebastian Hack's avatar
Sebastian Hack committed
35
36
}

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

45
46
47
48
49
50
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
51
static const arch_irn_ops_t *fallback_irn_ops = NULL;
Sebastian Hack's avatar
Sebastian Hack committed
52

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

Sebastian Hack's avatar
Sebastian Hack committed
61
  return cls->n_regs;
62
63
}

Sebastian Hack's avatar
Sebastian Hack committed
64
/**
Sebastian Hack's avatar
Sebastian Hack committed
65
66
67
68
 * 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
69
 */
Sebastian Hack's avatar
Sebastian Hack committed
70
71
static INLINE const arch_irn_ops_t *
get_irn_ops(const arch_env_t *env, const ir_node *irn)
72
{
Sebastian Hack's avatar
Sebastian Hack committed
73
  int i;
74

Sebastian Hack's avatar
Sebastian Hack committed
75
  for(i = env->handlers_tos - 1; i >= 0; --i) {
Sebastian Hack's avatar
Sebastian Hack committed
76
77
78
    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
79
80
81
    if(ops)
      return ops;
  }
Sebastian Hack's avatar
Sebastian Hack committed
82

Sebastian Hack's avatar
Sebastian Hack committed
83
  return fallback_irn_ops;
84
85
}

Sebastian Hack's avatar
Sebastian Hack committed
86
87
88
89
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
90
  req->type = arch_register_req_type_none;
91
  return ops->impl->get_irn_reg_req(ops, req, irn, pos);
Sebastian Hack's avatar
Sebastian Hack committed
92
93
}

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

100
101
102
103
104
105
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
106

Sebastian Hack's avatar
Sebastian Hack committed
107
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
108
{
Sebastian Hack's avatar
Sebastian Hack committed
109
  arch_register_req_t local_req;
Sebastian Hack's avatar
Sebastian Hack committed
110
  const arch_irn_ops_t *ops = get_irn_ops(env, irn);
111
  const arch_register_req_t *req = ops->impl->get_irn_reg_req(ops, &local_req, irn, pos);
Sebastian Hack's avatar
Sebastian Hack committed
112

Sebastian Hack's avatar
Sebastian Hack committed
113
  if(req->type == arch_register_req_type_none) {
Sebastian Hack's avatar
Sebastian Hack committed
114
115
	  bitset_clear_all(bs);
	  return 0;
Sebastian Hack's avatar
Sebastian Hack committed
116
  }
Sebastian Hack's avatar
Sebastian Hack committed
117

Sebastian Hack's avatar
Sebastian Hack committed
118
  if(arch_register_req_is(req, limited)) {
Sebastian Hack's avatar
Sebastian Hack committed
119
	  req->limited(req->limited_env, bs);
Sebastian Hack's avatar
Sebastian Hack committed
120
121
	  return bitset_popcnt(bs);
  }
Sebastian Hack's avatar
Sebastian Hack committed
122
123
124

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

Sebastian Hack's avatar
Sebastian Hack committed
127
128
129
130
131
132
133
134
135
136
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);
	}
}

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

Sebastian Hack's avatar
Sebastian Hack committed
146
147
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
148
{
149
150
151
	arch_register_req_t req;

	arch_get_register_req(env, &req, irn, pos);
Sebastian Hack's avatar
Sebastian Hack committed
152
153
154
155
156
157

	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
158
		req.limited(req.limited_env, bs);
Sebastian Hack's avatar
Sebastian Hack committed
159
		return bitset_is_set(bs, arch_register_get_index(reg));
160
161
	}

Sebastian Hack's avatar
Sebastian Hack committed
162
	return req.cls == reg->reg_class;
Sebastian Hack's avatar
Sebastian Hack committed
163
164
}

Sebastian Hack's avatar
Sebastian Hack committed
165
166
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
167
{
Sebastian Hack's avatar
Sebastian Hack committed
168
  arch_register_req_t local_req;
Sebastian Hack's avatar
Sebastian Hack committed
169
  const arch_irn_ops_t *ops = get_irn_ops(env, irn);
170
  const arch_register_req_t *req = ops->impl->get_irn_reg_req(ops, &local_req, irn, pos);
Sebastian Hack's avatar
Sebastian Hack committed
171
  return req ? req->cls : NULL;
Sebastian Hack's avatar
Sebastian Hack committed
172
173
}

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

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

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);
191
  return ops->impl->classify(ops, irn);
192
}
Sebastian Hack's avatar
Sebastian Hack committed
193
194
195
196

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);
197
  return ops->impl->get_flags(ops, irn);
Sebastian Hack's avatar
Sebastian Hack committed
198
}
Sebastian Hack's avatar
Sebastian Hack committed
199
200
201
202
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

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
230
		ir_snprintf(tmp, sizeof(tmp), " same to: %+F", req->other_different);
Sebastian Hack's avatar
Sebastian Hack committed
231
232
233
234
		strncat(buf, tmp, len);
	}

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

	return buf;
}