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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	return buf;
}