mips_new_nodes.c 12.4 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
Christian Würdig's avatar
Christian Würdig committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * This file is part of libFirm.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

20
/**
21
 * @file
22
23
 * @brief    This file implements the creation of the architecture specific firm
 *           opcodes and the corresponding node constructors for the MIPS
24
25
26
 *           assembler irg.
 * @author   Matthias Braun, Mehdi
 * @version  $Id$
27
28
29
30
31
32
33
34
35
36
37
38
39
40
 */
#include "config.h"

#include <stdlib.h>

#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 "irvrfy_t.h"
#include "irprintf.h"
41
#include "xmalloc.h"
42

43
#include "../bearch.h"
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

#include "mips_nodes_attr.h"
#include "mips_new_nodes.h"
#include "gen_mips_regalloc_if.h"



/***********************************************************************************
 *      _                                   _       _             __
 *     | |                                 (_)     | |           / _|
 *   __| |_   _ _ __ ___  _ __   ___ _ __   _ _ __ | |_ ___ _ __| |_ __ _  ___ ___
 *  / _` | | | | '_ ` _ \| '_ \ / _ \ '__| | | '_ \| __/ _ \ '__|  _/ _` |/ __/ _ \
 * | (_| | |_| | | | | | | |_) |  __/ |    | | | | | ||  __/ |  | || (_| | (_|  __/
 *  \__,_|\__,_|_| |_| |_| .__/ \___|_|    |_|_| |_|\__\___|_|  |_| \__,_|\___\___|
 *                       | |
 *                       |_|
 ***********************************************************************************/

/**
 * Dumps the register requirements for either in or out.
 */
65
66
67
static void dump_reg_req(FILE *F, ir_node *n, const arch_register_req_t **reqs,
                         int inout)
{
68
	char *dir = inout ? "out" : "in";
69
	int   max = inout ? (int) arch_irn_get_n_outs(n) : get_irn_arity(n);
Matthias Braun's avatar
Matthias Braun committed
70
	char  buf[1024];
71
72
	int   i;

Matthias Braun's avatar
Matthias Braun committed
73
	memset(buf, 0, sizeof(buf));
74
75
76
77
78

	if (reqs) {
		for (i = 0; i < max; i++) {
			fprintf(F, "%sreq #%d =", dir, i);

Matthias Braun's avatar
Matthias Braun committed
79
			if (reqs[i]->type == arch_register_req_type_none) {
80
81
82
				fprintf(F, " n/a");
			}

Matthias Braun's avatar
Matthias Braun committed
83
84
			if (reqs[i]->type & arch_register_req_type_normal) {
				fprintf(F, " %s", reqs[i]->cls->name);
85
86
			}

Matthias Braun's avatar
Matthias Braun committed
87
88
89
			if (reqs[i]->type & arch_register_req_type_limited) {
				fprintf(F, " %s",
				        arch_register_req_format(buf, sizeof(buf), reqs[i], n));
90
91
			}

Matthias Braun's avatar
Matthias Braun committed
92
			if (reqs[i]->type & arch_register_req_type_should_be_same) {
93
94
95
96
97
98
99
100
101
				const unsigned other = reqs[i]->other_same;
				int i;

				ir_fprintf(F, " same as");
				for (i = 0; 1U << i <= other; ++i) {
					if (other & (1U << i)) {
						ir_fprintf(F, " %+F", i);
					}
				}
102
103
			}

104
			if (reqs[i]->type & arch_register_req_type_must_be_different) {
105
106
107
108
109
110
111
112
113
				const unsigned other = reqs[i]->other_different;
				int i;

				ir_fprintf(F, " different from");
				for (i = 0; 1U << i <= other; ++i) {
					if (other & (1U << i)) {
						ir_fprintf(F, " %+F", i);
					}
				}
114
115
116
117
118
119
			}

			fprintf(F, "\n");
		}

		fprintf(F, "\n");
Matthias Braun's avatar
Matthias Braun committed
120
	} else {
121
122
123
124
125
126
127
128
129
130
131
132
		fprintf(F, "%sreq = N/A\n", dir);
	}
}


/**
 * Dumper interface for dumping mips nodes in vcg.
 * @param n        the node to dump
 * @param F        the output file
 * @param reason   indicates which kind of information should be dumped
 * @return 0 on success or != 0 on failure
 */
133
static int mips_dump_node(ir_node *n, FILE *F, dump_reason_t reason) {
134
	int          bad  = 0;
135
	int          i, n_res, flags;
Matthias Braun's avatar
Matthias Braun committed
136
	const arch_register_req_t **reqs;
137
138
139
140
141
142
143
144
145
146
147

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

		case dump_node_mode_txt:
			break;

		case dump_node_nodeattr_txt:

148
149
150
			if(is_mips_Immediate(n)) {
				const mips_immediate_attr_t *attr
					= get_mips_immediate_attr_const(n);
Matthias Braun's avatar
Matthias Braun committed
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
				switch(attr->imm_type) {
				case MIPS_IMM_CONST:
					fprintf(F, " %ld ", attr->val);
					break;
				case MIPS_IMM_SYMCONST_LO:
					fprintf(F, " lo(%s", get_entity_ld_name(attr->entity));
					if(attr->val != 0) {
						fprintf(F, "%+ld", attr->val);
					}
					fprintf(F, ") ");
					break;
				case MIPS_IMM_SYMCONST_HI:
					fprintf(F, " hi(%s", get_entity_ld_name(attr->entity));
					if(attr->val != 0) {
						fprintf(F, "%+ld", attr->val);
					}
					fprintf(F, ") ");
					break;
				default:
					fprintf(F, " INVALID ");
					break;
				}
173
			}
174
175
176
177
178
179
180
181
182
183
184
			break;

		case dump_node_info_txt:
			fprintf(F, "=== mips attr begin ===\n");

			/* dump IN requirements */
			if (get_irn_arity(n) > 0) {
				reqs = get_mips_in_req_all(n);
				dump_reg_req(F, n, reqs, 0);
			}

185
186
187
			n_res = arch_irn_get_n_outs(n);
			if (n_res > 0) {
				/* dump OUT requirements */
188
189
190
				reqs = get_mips_out_req_all(n);
				dump_reg_req(F, n, reqs, 1);

191
192
193
194
195
				/* dump assigned registers */
				for (i = 0; i < n_res; i++) {
					const arch_register_t *reg = arch_irn_get_register(n, i);

					fprintf(F, "reg #%d = %s\n", i, reg ? arch_register_get_name(reg) : "n/a");
196
				}
197
				fprintf(F, "\n");
198
199
200
			}

			/* dump n_res */
201
			fprintf(F, "n_res = %d\n", n_res);
202
203
204

			/* dump flags */
			fprintf(F, "flags =");
205
206
			flags = arch_irn_get_flags(n);
			if (flags == arch_irn_flags_none) {
207
208
209
				fprintf(F, " none");
			}
			else {
210
				if (flags & arch_irn_flags_dont_spill) {
211
212
					fprintf(F, " unspillable");
				}
213
				if (flags & arch_irn_flags_rematerializable) {
214
215
					fprintf(F, " remat");
				}
216
217
218
				if (flags & arch_irn_flags_modify_flags) {
					fprintf(F, " modify_flags");
				}
219
			}
220
			fprintf(F, " (%d)\n", flags);
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243

			fprintf(F, "=== mips attr end ===\n");
			/* end of: case dump_node_info_txt */
			break;
	}


	return bad;
}



/***************************************************************************************************
 *        _   _                   _       __        _                    _   _               _
 *       | | | |                 | |     / /       | |                  | | | |             | |
 *   __ _| |_| |_ _ __   ___  ___| |_   / /_ _  ___| |_   _ __ ___   ___| |_| |__   ___   __| |___
 *  / _` | __| __| '__| / __|/ _ \ __| / / _` |/ _ \ __| | '_ ` _ \ / _ \ __| '_ \ / _ \ / _` / __|
 * | (_| | |_| |_| |    \__ \  __/ |_ / / (_| |  __/ |_  | | | | | |  __/ |_| | | | (_) | (_| \__ \
 *  \__,_|\__|\__|_|    |___/\___|\__/_/ \__, |\___|\__| |_| |_| |_|\___|\__|_| |_|\___/ \__,_|___/
 *                                        __/ |
 *                                       |___/
 ***************************************************************************************************/

244
245
mips_attr_t *get_mips_attr(ir_node *node)
{
246
247
248
249
	assert(is_mips_irn(node) && "need mips node to get attributes");
	return (mips_attr_t *) get_irn_generic_attr(node);
}

250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
const mips_attr_t *get_mips_attr_const(const ir_node *node)
{
	assert(is_mips_irn(node) && "need mips node to get attributes");
	return get_irn_generic_attr_const(node);
}

const mips_immediate_attr_t *get_mips_immediate_attr_const(const ir_node *node)
{
	assert(is_mips_irn(node) && "need mips node to get attributes");
	return get_irn_generic_attr_const(node);
}

const mips_load_store_attr_t *get_mips_load_store_attr_const(
		const ir_node *node)
{
265
	assert(is_mips_irn(node) && "need mips node to get attributes");
266
	return get_irn_generic_attr_const(node);
267
268
269
270
271
}

/**
 * Returns the argument register requirements of a mips node.
 */
272
273
const arch_register_req_t **get_mips_in_req_all(const ir_node *node)
{
274
	const mips_attr_t *attr = get_mips_attr_const(node);
275
276
277
278
279
280
	return attr->in_req;
}

/**
 * Returns the result register requirements of an mips node.
 */
281
282
const arch_register_req_t **get_mips_out_req_all(const ir_node *node)
{
283
	const mips_attr_t *attr = get_mips_attr_const(node);
284
285
286
287
288
289
	return attr->out_req;
}

/**
 * Returns the argument register requirement at position pos of an mips node.
 */
290
291
const arch_register_req_t *get_mips_in_req(const ir_node *node, int pos)
{
292
	const mips_attr_t *attr = get_mips_attr_const(node);
293
294
295
296
297
298
	return attr->in_req[pos];
}

/**
 * Returns the result register requirement at position pos of an mips node.
 */
299
300
const arch_register_req_t *get_mips_out_req(const ir_node *node, int pos)
{
301
	const mips_attr_t *attr = get_mips_attr_const(node);
302
303
304
305
306
307
	return attr->out_req[pos];
}

/**
 * Sets the OUT register requirements at position pos.
 */
308
309
void set_mips_req_out(ir_node *node, const arch_register_req_t *req, int pos)
{
310
311
312
313
314
315
316
	mips_attr_t *attr   = get_mips_attr(node);
	attr->out_req[pos] = req;
}

/**
 * Sets the IN register requirements at position pos.
 */
317
318
void set_mips_req_in(ir_node *node, const arch_register_req_t *req, int pos)
{
319
320
321
322
323
324
325
	mips_attr_t *attr  = get_mips_attr(node);
	attr->in_req[pos] = req;
}

/**
 * Initializes the nodes attributes.
 */
326
327
328
329
static void init_mips_attributes(ir_node *node, arch_irn_flags_t flags,
                                 const arch_register_req_t **in_reqs,
                                 const arch_register_req_t **out_reqs,
                                 const be_execution_unit_t ***execution_units,
330
                                 int n_res)
331
{
332
333
334
	ir_graph       *irg  = get_irn_irg(node);
	struct obstack *obst = get_irg_obstack(irg);
	mips_attr_t    *attr = get_mips_attr(node);
335
	backend_info_t *info;
Matthias Braun's avatar
Matthias Braun committed
336
	(void) execution_units;
337

338
	arch_irn_set_flags(node, flags);
339
	attr->out_req = out_reqs;
340
	attr->in_req  = in_reqs;
341

342
343
344
	info            = be_get_info(node);
	info->out_infos = NEW_ARR_D(reg_out_info_t, obst, n_res);
	memset(info->out_infos, 0, n_res * sizeof(info->out_infos[0]));
345
346
}

347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
static void init_mips_immediate_attributes(ir_node *node,
                                           mips_immediate_type_t type,
                                           ir_entity *entity, long val)
{
	mips_immediate_attr_t *attr = get_irn_generic_attr(node);

	attr->imm_type = type;
	attr->entity   = entity;
	attr->val      = val;
}

static void init_mips_load_store_attributes(ir_node *node, ir_entity *entity,
                                            long offset)
{
	mips_load_store_attr_t *attr = get_irn_generic_attr(node);
	attr->stack_entity = entity;
	attr->offset       = offset;
}

static int mips_compare_nodes_attr(ir_node *node_a, ir_node *node_b)
Matthias Braun's avatar
Matthias Braun committed
367
{
368
369
370
	const mips_attr_t *a = get_mips_attr_const(node_a);
	const mips_attr_t *b = get_mips_attr_const(node_b);

Matthias Braun's avatar
Matthias Braun committed
371
372
373
374
375
376
	if(a->switch_default_pn != b->switch_default_pn)
		return 1;

	return 0;
}

377
static int mips_compare_immediate_attr(ir_node *node_a, ir_node *node_b)
378
{
379
380
	const mips_immediate_attr_t *a = get_mips_immediate_attr_const(node_a);
	const mips_immediate_attr_t *b = get_mips_immediate_attr_const(node_b);
381

382
383
384
385
	if(a->val != b->val)
		return 1;

	return 0;
386
387
}

388
389
390
391
392
393
394
395
396
397
398
399
400
static int mips_compare_load_store_attr(ir_node *node_a, ir_node *node_b)
{
	const mips_load_store_attr_t *a = get_mips_load_store_attr_const(node_a);
	const mips_load_store_attr_t *b = get_mips_load_store_attr_const(node_b);

	if(mips_compare_nodes_attr(node_a, node_b))
		return 1;
	if(a->stack_entity != b->stack_entity)
		return 1;
	if(a->offset != b->offset)
		return 1;

	return 0;
401
402
}

403
404
405
406
407
408
static void mips_copy_attr(const ir_node *old_node , ir_node *new_node)
{
	ir_graph          *irg      = get_irn_irg(new_node);
	struct obstack    *obst     = get_irg_obstack(irg);
	const mips_attr_t *attr_old = get_mips_attr_const(old_node);
	mips_attr_t       *attr_new = get_mips_attr(new_node);
409
410
	backend_info_t    *old_info = be_get_info(old_node);
	backend_info_t    *new_info = be_get_info(new_node);
411
412
413
414

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

415
416
417
	/* copy out flags */
	new_info->out_infos =
		DUP_ARR_D(reg_out_info_t, obst, old_info->out_infos);
418
419
420
421
422
423
424
425
426
427
428
429
430
431
}

/***************************************************************************************
 *                  _                            _                   _
 *                 | |                          | |                 | |
 *  _ __   ___   __| | ___    ___ ___  _ __  ___| |_ _ __ _   _  ___| |_ ___  _ __ ___
 * | '_ \ / _ \ / _` |/ _ \  / __/ _ \| '_ \/ __| __| '__| | | |/ __| __/ _ \| '__/ __|
 * | | | | (_) | (_| |  __/ | (_| (_) | | | \__ \ |_| |  | |_| | (__| || (_) | |  \__ \
 * |_| |_|\___/ \__,_|\___|  \___\___/|_| |_|___/\__|_|   \__,_|\___|\__\___/|_|  |___/
 *
 ***************************************************************************************/

/* Include the generated constructor functions */
#include "gen_mips_new_nodes.c.inl"