bearch.c 4.17 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
Christian Würdig's avatar
Christian Würdig committed
4
5
 */

6
/**
Christian Würdig's avatar
Christian Würdig committed
7
8
9
 * @file
 * @brief       Processor architecture specification.
 * @author      Sebastian Hack
10
 */
11
#include "bearch.h"
12
#include "benode.h"
13
#include "beinfo.h"
Sebastian Hack's avatar
Sebastian Hack committed
14
#include "ircons_t.h"
Daniel Grund's avatar
Daniel Grund committed
15
#include "irnode_t.h"
16
#include "irop_t.h"
Matthias Braun's avatar
Matthias Braun committed
17
#include "raw_bitset.h"
18

19
arch_register_req_t const arch_no_requirement = {
20
21
22
23
24
25
	.cls             = NULL,
	.limited         = NULL,
	.type            = arch_register_req_type_none,
	.other_same      = 0,
	.other_different = 0,
	.width           = 0,
26
27
};

Sebastian Hack's avatar
Sebastian Hack committed
28
/**
Sebastian Hack's avatar
Sebastian Hack committed
29
30
31
 * Get the isa responsible for a node.
 * @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
32
 */
33
static const arch_irn_ops_t *get_irn_ops(const ir_node *irn)
34
{
35
36
37
	ir_op          const *const op     = get_irn_op(irn);
	arch_irn_ops_t const *const be_ops = get_op_ops(op)->be_ops;
	assert(be_ops);
Matthias Braun's avatar
Matthias Braun committed
38
	return be_ops;
39
40
}

41
ir_entity *arch_get_frame_entity(const ir_node *irn)
42
{
43
	const arch_irn_ops_t *ops = get_irn_ops(irn);
44
	return ops->get_frame_entity(irn);
45
46
}

47
void arch_perform_memory_operand(ir_node *irn, unsigned int i)
48
{
49
	const arch_irn_ops_t *ops = get_irn_ops(irn);
50
51
	if (ops->perform_memory_operand)
		ops->perform_memory_operand(irn, i);
52
53
}

54
int arch_get_op_estimated_cost(const ir_node *irn)
55
{
56
	const arch_irn_ops_t *ops = get_irn_ops(irn);
Matthias Braun's avatar
Matthias Braun committed
57

58
	if (ops->get_op_estimated_cost) {
59
		return ops->get_op_estimated_cost(irn);
Matthias Braun's avatar
Matthias Braun committed
60
61
62
	} else {
		return 1;
	}
63
64
}

65
static reg_out_info_t *get_out_info_n(const ir_node *node, unsigned pos)
66
{
67
	const backend_info_t *info = be_get_info(node);
68
	assert(pos < (unsigned)ARR_LEN(info->out_infos));
69
	return &info->out_infos[pos];
70
}
71

72
73

const arch_register_t *arch_get_irn_register(const ir_node *node)
74
{
75
76
	const reg_out_info_t *out = get_out_info(node);
	return out->reg;
77
}
Sebastian Hack's avatar
Sebastian Hack committed
78

79
80
const arch_register_t *arch_get_irn_register_out(const ir_node *node,
                                                 unsigned pos)
Sebastian Hack's avatar
Sebastian Hack committed
81
{
82
83
84
85
	const reg_out_info_t *out = get_out_info_n(node, pos);
	return out->reg;
}

86
87
88
89
90
91
const arch_register_t *arch_get_irn_register_in(const ir_node *node, int pos)
{
	ir_node *op = get_irn_n(node, pos);
	return arch_get_irn_register(op);
}

92
void arch_set_irn_register_out(ir_node *node, unsigned pos,
93
                               const arch_register_t *reg)
94
95
96
97
98
99
100
101
102
103
104
{
	reg_out_info_t *out = get_out_info_n(node, pos);
	out->reg            = reg;
}

void arch_set_irn_register(ir_node *node, const arch_register_t *reg)
{
	reg_out_info_t *out = get_out_info(node);
	out->reg = reg;
}

105
void arch_set_irn_flags(ir_node *node, arch_irn_flags_t flags)
106
{
107
	backend_info_t *const info = be_get_info(node);
108
109
110
	info->flags = flags;
}

111
void arch_add_irn_flags(ir_node *node, arch_irn_flags_t flags)
112
{
113
	backend_info_t *const info = be_get_info(node);
114
	info->flags |= flags;
Sebastian Hack's avatar
Sebastian Hack committed
115
}
Sebastian Hack's avatar
Sebastian Hack committed
116

117
118
119
bool arch_reg_is_allocatable(const arch_register_req_t *req,
                             const arch_register_t *reg)
{
120
	assert(req->type != arch_register_req_type_none);
121
	if (req->cls != reg->cls)
122
		return false;
123
	if (reg->type & arch_register_type_virtual)
124
		return true;
125
	if (arch_register_req_is(req, limited))
126
		return rbitset_is_set(req->limited, reg->index);
127
	return true;
128
129
}

130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
void be_make_start_mem(be_start_info_t *const info, ir_node *const start, unsigned const pos)
{
  info->pos = pos;
  info->irn = NULL;
  arch_set_irn_register_req_out(start, pos, arch_no_register_req);
}

void be_make_start_out(be_start_info_t *const info, struct obstack *const obst, ir_node *const start, unsigned const pos, arch_register_t const *const reg, arch_register_req_type_t const flags)
{
	info->pos = pos;
	info->irn = NULL;
	arch_register_req_t const *const req =
		flags == arch_register_req_type_none ? reg->single_req :
		be_create_reg_req(obst, reg, flags);
	arch_set_irn_register_req_out(start, pos, req);
	arch_set_irn_register_out(start, pos, reg);
}

ir_node *be_get_start_proj(ir_graph *const irg, be_start_info_t *const info)
{
	if (!info->irn) {
		/* This is already the transformed start node. */
		ir_node                     *const start = get_irg_start(irg);
		arch_register_class_t const *const cls   = arch_get_irn_register_req_out(start, info->pos)->cls;
		info->irn = new_r_Proj(start, cls ? cls->mode : mode_M, info->pos);
	}
	return info->irn;
}