bearch.c 5.92 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
31
#include "irprintf.h"

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

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

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

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

Sebastian Hack's avatar
Sebastian Hack committed
63
  return cls->n_regs;
64
65
}

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

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

Sebastian Hack's avatar
Sebastian Hack committed
85
  return fallback_irn_ops;
86
87
}

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

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

102
103
104
105
106
107
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
108

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	return buf;
}