amd64_new_nodes.c 6.84 KB
Newer Older
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
4
5
6
7
8
9
10
11
12
13
 */

/**
 * @file
 * @brief   This file implements the creation of the achitecture specific firm
 *          opcodes and the coresponding node constructors for the amd64
 *          assembler irg.
 */
#include <stdlib.h>

14
#include "error.h"
15
16
17
18
19
20
21
22
23
24
#include "irprog_t.h"
#include "irgraph_t.h"
#include "irnode_t.h"
#include "irmode_t.h"
#include "ircons_t.h"
#include "iropt_t.h"
#include "irop.h"
#include "irprintf.h"
#include "xmalloc.h"

25
#include "bearch.h"
26
27
28
29
30

#include "amd64_nodes_attr.h"
#include "amd64_new_nodes.h"
#include "gen_amd64_regalloc_if.h"

31
32
33
34
35
36
void set_amd64_ls_mode(ir_node *node, ir_mode *mode)
{
  amd64_attr_t *attr = get_amd64_attr(node);
  attr->ls_mode = mode;
}

37
38
39
/**
 * Dumper interface for dumping amd64 nodes in vcg.
 * @param F        the output file
40
 * @param n        the node to dump
41
42
 * @param reason   indicates which kind of information should be dumped
 */
43
static void amd64_dump_node(FILE *F, const ir_node *n, dump_reason_t reason)
44
{
45
	ir_mode *mode = NULL;
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

	switch (reason) {
	case dump_node_opcode_txt:
		fprintf(F, "%s", get_irn_opname(n));
		break;

	case dump_node_mode_txt:
		mode = get_irn_mode(n);

		if (mode) {
			fprintf(F, "[%s]", get_mode_name(mode));
		} else {
			fprintf(F, "[?NOMODE?]");
		}
		break;

	case dump_node_nodeattr_txt:

		/* TODO: dump some attributes which should show up */
		/* in node name in dump (e.g. consts or the like)  */

		break;

	case dump_node_info_txt:
		arch_dump_reqs_and_registers(F, n);
		break;
	}
}

const amd64_attr_t *get_amd64_attr_const(const ir_node *node)
{
	assert(is_amd64_irn(node) && "need amd64 node to get attributes");
	return (const amd64_attr_t *)get_irn_generic_attr_const(node);
}

amd64_attr_t *get_amd64_attr(ir_node *node)
{
	assert(is_amd64_irn(node) && "need amd64 node to get attributes");
	return (amd64_attr_t *)get_irn_generic_attr(node);
}

87
88
89
90
91
92
93
94
95
96
97
98
99
100
const amd64_switch_jmp_attr_t *get_amd64_switch_jmp_attr_const(const ir_node *node)
{
	const amd64_switch_jmp_attr_t *attr
		= (const amd64_switch_jmp_attr_t*)get_irn_generic_attr_const(node);
	return attr;
}

amd64_switch_jmp_attr_t *get_amd64_switch_jmp_attr(ir_node *node)
{
	amd64_switch_jmp_attr_t *attr
		= (amd64_switch_jmp_attr_t*)get_irn_generic_attr(node);
	return attr;
}

101
const amd64_movimm_attr_t *get_amd64_movimm_attr_const(const ir_node *node)
102
{
103
104
105
	assert(is_amd64_irn(node));
	return (const amd64_movimm_attr_t*)get_irn_generic_attr_const(node);
}
106

107
108
109
110
111
amd64_movimm_attr_t *get_amd64_movimm_attr(ir_node *node)
{
	assert(is_amd64_irn(node));
	return (amd64_movimm_attr_t*)get_irn_generic_attr(node);
}
112

113
114
115
116
117
const amd64_cc_attr_t *get_amd64_cc_attr_const(const ir_node *node)
{
	assert(is_amd64_irn(node));
	return (const amd64_cc_attr_t*)get_irn_generic_attr_const(node);
}
118

119
120
121
122
amd64_cc_attr_t *get_amd64_cc_attr(ir_node *node)
{
	assert(is_amd64_irn(node));
	return (amd64_cc_attr_t*)get_irn_generic_attr(node);
123
124
}

125
/**
126
 * Initializes the nodes attributes.
127
 */
128
129
130
static void init_amd64_attributes(ir_node *node, arch_irn_flags_t flags,
                                  const arch_register_req_t **in_reqs,
                                  int n_res)
131
{
132
133
134
135
136
137
138
	arch_set_irn_flags(node, flags);
	arch_set_irn_register_reqs_in(node, in_reqs);

	ir_graph       *irg  = get_irn_irg(node);
	struct obstack *obst = get_irg_obstack(irg);
	backend_info_t *info = be_get_info(node);
	info->out_infos = NEW_ARR_DZ(reg_out_info_t, obst, n_res);
139
140
}

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/**
 * Initialize SwitchJmp attributes.
 */
static void init_amd64_switch_attributes(ir_node *node, const ir_switch_table *table, ir_entity *table_entity)
{
	unsigned n_outs = arch_get_irn_n_outs(node);
	unsigned o;

	amd64_switch_jmp_attr_t *attr = get_amd64_switch_jmp_attr(node);
	attr->table        = table;
	attr->table_entity = table_entity;

	for (o = 0; o < n_outs; o++) {
		arch_set_irn_register_req_out(node, o, arch_no_register_req);
	}
}

158
static void init_amd64_cc_attributes(ir_node *node, x86_condition_code_t cc)
159
{
160
	amd64_cc_attr_t *attr = get_amd64_cc_attr(node);
161
	attr->cc = cc;
162
163
}

164
165
static void init_amd64_movimm_attributes(ir_node *node, ir_entity *symconst,
                                         int64_t offset)
166
{
167
168
169
	amd64_movimm_attr_t *attr = get_amd64_movimm_attr(node);
	attr->symconst = symconst;
	attr->offset   = offset;
170
171
}

Matthias Braun's avatar
Matthias Braun committed
172
173
174
175
176
177
178
179
180
181
static int cmp_am(const amd64_am_info_t *const am0,
                  const amd64_am_info_t *const am1)
{
	return am0->offset != am1->offset || am0->symconst != am1->symconst
	    || am0->base_input != am1->base_input
	    || am0->index_input != am1->index_input
	    || am0->log_scale != am1->log_scale
	    || am0->segment != am1->segment;
}

182
/** Compare common amd64 node attributes. */
Michael Beck's avatar
Michael Beck committed
183
static int cmp_amd64_attr(const ir_node *a, const ir_node *b)
184
185
186
{
	const amd64_attr_t *attr_a = get_amd64_attr_const(a);
	const amd64_attr_t *attr_b = get_amd64_attr_const(b);
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
	return cmp_am(&attr_a->am, &attr_b->am)
	    || attr_a->data.insn_mode != attr_b->data.insn_mode
	    || attr_a->data.needs_frame_ent != attr_b->data.needs_frame_ent
	    || attr_a->ls_mode != attr_b->ls_mode;
}

static int cmp_amd64_movimm_attr(const ir_node *const a,
                                 const ir_node *const b)
{
	if (cmp_amd64_attr(a, b))
		return true;
	const amd64_movimm_attr_t *const attr_a = get_amd64_movimm_attr_const(a);
	const amd64_movimm_attr_t *const attr_b = get_amd64_movimm_attr_const(b);
	return attr_a->symconst != attr_b->symconst
	    || attr_a->offset != attr_b->offset;
}

static int cmp_amd64_cc_attr(const ir_node *const a,
                             const ir_node *const b)
{
	if (cmp_amd64_attr(a, b))
		return true;
	const amd64_cc_attr_t *const attr_a = get_amd64_cc_attr_const(a);
	const amd64_cc_attr_t *const attr_b = get_amd64_cc_attr_const(b);
211
	return attr_a->cc != attr_b->cc;
212
213
214
215
216
217
218
219
220
221
222
223
}

static int cmp_amd64_switch_jmp_attr(const ir_node *const a,
                                    const ir_node *const b)
{
	if (cmp_amd64_attr(a, b))
		return true;
	const amd64_switch_jmp_attr_t *const attr_a
		= get_amd64_switch_jmp_attr_const(a);
	const amd64_switch_jmp_attr_t *const attr_b
		= get_amd64_switch_jmp_attr_const(b);
	return attr_a->table != attr_b->table;
224
225
}

226
227
/** copies the AMD64 attributes of a node. */
static void amd64_copy_attr(ir_graph *irg, const ir_node *old_node,
228
                            ir_node *new_node)
229
230
231
232
233
234
235
236
237
238
239
{
	struct obstack   *obst       = get_irg_obstack(irg);
	const amd64_attr_t *attr_old = get_amd64_attr_const(old_node);
	amd64_attr_t     *attr_new   = get_amd64_attr(new_node);
	backend_info_t   *old_info   = be_get_info(old_node);
	backend_info_t   *new_info   = be_get_info(new_node);

	/* copy the attributes */
	memcpy(attr_new, attr_old, get_op_attr_size(get_irn_op(old_node)));

	/* copy out flags */
240
	new_info->flags = old_info->flags;
241
242
	new_info->out_infos =
		DUP_ARR_D(reg_out_info_t, obst, old_info->out_infos);
243
	new_info->in_reqs = old_info->in_reqs;
244
245
}

246
247
/* Include the generated constructor functions */
#include "gen_amd64_new_nodes.c.inl"