bearch.c 5.52 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
}

Sebastian Hack's avatar
Sebastian Hack committed
37
38
arch_env_t *arch_env_add_irn_handler(arch_env_t *env,
    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
}

Sebastian Hack's avatar
Sebastian Hack committed
45
static const arch_irn_ops_t *fallback_irn_ops = NULL;
Sebastian Hack's avatar
Sebastian Hack committed
46

Sebastian Hack's avatar
Sebastian Hack committed
47
int arch_register_class_put(const arch_register_class_t *cls, bitset_t *bs)
48
{
Sebastian Hack's avatar
Sebastian Hack committed
49
50
51
52
53
  if(bs) {
    int i, n;
    for(i = 0, n = cls->n_regs; i < n; ++i)
      bitset_set(bs, i);
  }
54

Sebastian Hack's avatar
Sebastian Hack committed
55
  return cls->n_regs;
56
57
}

Sebastian Hack's avatar
Sebastian Hack committed
58
/**
Sebastian Hack's avatar
Sebastian Hack committed
59
60
61
62
 * 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
63
 */
Sebastian Hack's avatar
Sebastian Hack committed
64
65
static INLINE const arch_irn_ops_t *
get_irn_ops(const arch_env_t *env, const ir_node *irn)
66
{
Sebastian Hack's avatar
Sebastian Hack committed
67
  int i;
68

Sebastian Hack's avatar
Sebastian Hack committed
69
  for(i = env->handlers_tos - 1; i >= 0; --i) {
Sebastian Hack's avatar
Sebastian Hack committed
70
71
72
    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
73
74
75
    if(ops)
      return ops;
  }
Sebastian Hack's avatar
Sebastian Hack committed
76

Sebastian Hack's avatar
Sebastian Hack committed
77
  return fallback_irn_ops;
78
79
}

Sebastian Hack's avatar
Sebastian Hack committed
80
81
82
83
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
84
  req->type = arch_register_req_type_none;
85
  return ops->impl->get_irn_reg_req(ops, req, irn, pos);
Sebastian Hack's avatar
Sebastian Hack committed
86
87
}

Sebastian Hack's avatar
Sebastian Hack committed
88
89
90
91
92
93
94
void arch_set_stack_bias(const arch_env_t *env, ir_node *irn, int bias)
{
  const arch_irn_ops_t *ops = get_irn_ops(env, irn);
  ops->impl->set_stack_bias(ops, irn, bias);
}


Sebastian Hack's avatar
Sebastian Hack committed
95
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
96
{
Sebastian Hack's avatar
Sebastian Hack committed
97
  arch_register_req_t local_req;
Sebastian Hack's avatar
Sebastian Hack committed
98
  const arch_irn_ops_t *ops = get_irn_ops(env, irn);
99
  const arch_register_req_t *req = ops->impl->get_irn_reg_req(ops, &local_req, irn, pos);
Sebastian Hack's avatar
Sebastian Hack committed
100

Sebastian Hack's avatar
Sebastian Hack committed
101
  if(req->type == arch_register_req_type_none) {
Sebastian Hack's avatar
Sebastian Hack committed
102
103
	  bitset_clear_all(bs);
	  return 0;
Sebastian Hack's avatar
Sebastian Hack committed
104
  }
Sebastian Hack's avatar
Sebastian Hack committed
105

Sebastian Hack's avatar
Sebastian Hack committed
106
  if(arch_register_req_is(req, limited)) {
Sebastian Hack's avatar
Sebastian Hack committed
107
	  req->limited(req->limited_env, bs);
Sebastian Hack's avatar
Sebastian Hack committed
108
109
	  return bitset_popcnt(bs);
  }
Sebastian Hack's avatar
Sebastian Hack committed
110
111
112

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

Sebastian Hack's avatar
Sebastian Hack committed
115
116
117
118
119
120
121
122
123
124
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);
	}
}

125
126
127
int arch_is_register_operand(const arch_env_t *env,
    const ir_node *irn, int pos)
{
Sebastian Hack's avatar
Sebastian Hack committed
128
129
	arch_register_req_t local_req;
	const arch_irn_ops_t *ops = get_irn_ops(env, irn);
130
	const arch_register_req_t *req = ops->impl->get_irn_reg_req(ops, &local_req, irn, pos);
Sebastian Hack's avatar
Sebastian Hack committed
131
	return req != NULL;
132
133
}

Sebastian Hack's avatar
Sebastian Hack committed
134
135
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
136
{
137
138
139
	arch_register_req_t req;

	arch_get_register_req(env, &req, irn, pos);
Sebastian Hack's avatar
Sebastian Hack committed
140
141
142
143
144
145

	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
146
		req.limited(req.limited_env, bs);
Sebastian Hack's avatar
Sebastian Hack committed
147
		return bitset_is_set(bs, arch_register_get_index(reg));
148
149
	}

Sebastian Hack's avatar
Sebastian Hack committed
150
	return req.cls == reg->reg_class;
Sebastian Hack's avatar
Sebastian Hack committed
151
152
}

Sebastian Hack's avatar
Sebastian Hack committed
153
154
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
155
{
Sebastian Hack's avatar
Sebastian Hack committed
156
  arch_register_req_t local_req;
Sebastian Hack's avatar
Sebastian Hack committed
157
  const arch_irn_ops_t *ops = get_irn_ops(env, irn);
158
  const arch_register_req_t *req = ops->impl->get_irn_reg_req(ops, &local_req, irn, pos);
Sebastian Hack's avatar
Sebastian Hack committed
159
  return req ? req->cls : NULL;
Sebastian Hack's avatar
Sebastian Hack committed
160
161
}

Sebastian Hack's avatar
Sebastian Hack committed
162
extern const arch_register_t *
Sebastian Hack's avatar
Sebastian Hack committed
163
arch_get_irn_register(const arch_env_t *env, const ir_node *irn)
164
{
Sebastian Hack's avatar
Sebastian Hack committed
165
  const arch_irn_ops_t *ops = get_irn_ops(env, irn);
166
  return ops->impl->get_irn_reg(ops, irn);
167
}
168

Sebastian Hack's avatar
Sebastian Hack committed
169
extern void arch_set_irn_register(const arch_env_t *env,
Sebastian Hack's avatar
Sebastian Hack committed
170
    ir_node *irn, const arch_register_t *reg)
171
{
Sebastian Hack's avatar
Sebastian Hack committed
172
  const arch_irn_ops_t *ops = get_irn_ops(env, irn);
173
  ops->impl->set_irn_reg(ops, irn, reg);
174
}
175
176
177
178

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);
179
  return ops->impl->classify(ops, irn);
180
}
Sebastian Hack's avatar
Sebastian Hack committed
181
182
183
184

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);
185
  return ops->impl->get_flags(ops, irn);
Sebastian Hack's avatar
Sebastian Hack committed
186
}
Sebastian Hack's avatar
Sebastian Hack committed
187
188
189
190
191
192
193
194
195
196
197
198
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

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)) {
		snprintf(tmp, sizeof(tmp), " same to: %+F", req->other_different);
		strncat(buf, tmp, len);
	}

	if(arch_register_req_is(req, should_be_different)) {
		snprintf(tmp, sizeof(tmp), " different to: %+F", req->other_different);
		strncat(buf, tmp, len);
	}

	return buf;
}