bearch_TEMPLATE.c 8.47 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
 */

Matthias Braun's avatar
Matthias Braun committed
6
7
8
9
/**
 * @file
 * @brief    The main TEMPLATE backend driver file.
 */
10
#include "config.h"
11

12
13
#include "bearch_TEMPLATE_t.h"

14
15
16
17
#include "irgwalk.h"
#include "irprog.h"
#include "ircons.h"
#include "irgmod.h"
18
#include "lower_calls.h"
19
#include "lower_builtins.h"
20
#include "debug.h"
21
#include "be_t.h"
22
23
24
25
26
27
28
29
30
31
#include "bearch.h"
#include "benode.h"
#include "belower.h"
#include "besched.h"
#include "beabi.h"
#include "bemodule.h"
#include "begnuas.h"
#include "belistsched.h"
#include "bestack.h"
#include "bespillutil.h"
32

33
34
#include "TEMPLATE_new_nodes.h"
#include "gen_TEMPLATE_regalloc_if.h"
35
36
37
#include "TEMPLATE_transform.h"
#include "TEMPLATE_emitter.h"

38
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
39

40
41
static ir_entity *TEMPLATE_get_frame_entity(const ir_node *node)
{
Matthias Braun's avatar
Matthias Braun committed
42
	(void) node;
43
	/* TODO: return the ir_entity assigned to the frame */
Christian Würdig's avatar
Christian Würdig committed
44
45
46
47
48
49
50
	return NULL;
}

/**
 * This function is called by the generic backend to correct offsets for
 * nodes accessing the stack.
 */
51
52
static void TEMPLATE_set_frame_offset(ir_node *irn, int offset)
{
Matthias Braun's avatar
Matthias Braun committed
53
54
	(void) irn;
	(void) offset;
Christian Würdig's avatar
Christian Würdig committed
55
56
57
	/* TODO: correct offset if irn accesses the stack */
}

58
59
static int TEMPLATE_get_sp_bias(const ir_node *irn)
{
Matthias Braun's avatar
Matthias Braun committed
60
	(void) irn;
61
62
63
	return 0;
}

64
65
/* fill register allocator interface */

Matthias Braun's avatar
Matthias Braun committed
66
static const arch_irn_ops_t TEMPLATE_irn_ops = {
Christian Würdig's avatar
Christian Würdig committed
67
	TEMPLATE_get_frame_entity,
68
69
	TEMPLATE_set_frame_offset,
	TEMPLATE_get_sp_bias,
70
71
72
	NULL,    /* get_op_estimated_cost   */
	NULL,    /* possible_memory_operand */
	NULL,    /* perform_memory_operand  */
73
74
};

75

76
77
78
79
80

/**
 * Transforms the standard firm graph into
 * a TEMLPATE firm graph
 */
81
static void TEMPLATE_prepare_graph(ir_graph *irg)
82
{
83
	/* transform nodes into assembler instructions */
84
	TEMPLATE_transform_graph(irg);
85
86
87
88
89
}



/**
Christian Würdig's avatar
Christian Würdig committed
90
 * Called immediatly before emit phase.
91
 */
92
static void TEMPLATE_finish_irg(ir_graph *irg)
93
{
94
95
96
	/* fix stack entity offsets */
	be_abi_fix_stack_nodes(irg);
	be_abi_fix_stack_bias(irg);
97
98
99
}


100
static void TEMPLATE_before_ra(ir_graph *irg)
101
{
102
	(void) irg;
103
	/* Some stuff you need to do after scheduling but before register allocation */
104
105
}

106
static void TEMPLATE_init_graph(ir_graph *irg)
107
{
108
	(void) irg;
109
110
111
112
}



113
extern const arch_isa_if_t TEMPLATE_isa_if;
Christian Würdig's avatar
Christian Würdig committed
114
static TEMPLATE_isa_t TEMPLATE_isa_template = {
Matthias Braun's avatar
Matthias Braun committed
115
	{
116
		&TEMPLATE_isa_if,            /* isa interface implementation */
117
118
		N_TEMPLATE_REGISTERS,
		TEMPLATE_registers,
119
120
		N_TEMPLATE_CLASSES,
		TEMPLATE_reg_classes,
121
122
		&TEMPLATE_registers[REG_SP], /* stack pointer register */
		&TEMPLATE_registers[REG_BP], /* base pointer register */
123
		2,                           /* power of two stack alignment for calls, 2^2 == 4 */
124
125
		7,                           /* costs for a spill instruction */
		5,                           /* costs for a reload instruction */
Christoph Mallon's avatar
Christoph Mallon committed
126
		true,                        /* custom abi handling */
Matthias Braun's avatar
Matthias Braun committed
127
	},
Christian Würdig's avatar
Christian Würdig committed
128
129
};

130
static void TEMPLATE_init(void)
131
{
Matthias Braun's avatar
Matthias Braun committed
132
	TEMPLATE_register_init();
Matthias Braun's avatar
Matthias Braun committed
133
	TEMPLATE_create_opcodes(&TEMPLATE_irn_ops);
134
135
}

Matthias Braun's avatar
Matthias Braun committed
136
137
138
139
140
static void TEMPLATE_finish(void)
{
	TEMPLATE_free_opcodes();
}

141
static arch_env_t *TEMPLATE_begin_codegeneration(void)
142
143
144
{
	TEMPLATE_isa_t *isa = XMALLOC(TEMPLATE_isa_t);
	*isa = TEMPLATE_isa_template;
145

146
	return &isa->base;
147
148
149
150
151
}

/**
 * Closes the output file and frees the ISA structure.
 */
152
static void TEMPLATE_end_codegeneration(void *self)
153
{
154
155
156
	free(self);
}

Christian Würdig's avatar
Christian Würdig committed
157
/**
Michael Beck's avatar
Michael Beck committed
158
159
160
 * Get the between type for that call.
 * @param self The callback object.
 * @return The between type of for that call.
Christian Würdig's avatar
Christian Würdig committed
161
 */
162
static ir_type *TEMPLATE_get_between_type(ir_graph *irg)
Matthias Braun's avatar
Matthias Braun committed
163
{
Christian Würdig's avatar
Christian Würdig committed
164
	static ir_type *between_type = NULL;
Matthias Braun's avatar
Matthias Braun committed
165
	static ir_entity *old_bp_ent = NULL;
166
	(void) irg;
Christian Würdig's avatar
Christian Würdig committed
167

168
	if (!between_type) {
169
		ir_entity *ret_addr_ent;
170
171
		ir_type *ret_addr_type = new_type_primitive(mode_P);
		ir_type *old_bp_type   = new_type_primitive(mode_P);
Christian Würdig's avatar
Christian Würdig committed
172
173
174
175
176

		between_type           = new_type_class(new_id_from_str("TEMPLATE_between_type"));
		old_bp_ent             = new_entity(between_type, new_id_from_str("old_bp"), old_bp_type);
		ret_addr_ent           = new_entity(between_type, new_id_from_str("old_bp"), ret_addr_type);

Michael Beck's avatar
Michael Beck committed
177
178
		set_entity_offset(old_bp_ent, 0);
		set_entity_offset(ret_addr_ent, get_type_size_bytes(old_bp_type));
Christian Würdig's avatar
Christian Würdig committed
179
180
181
182
183
184
		set_type_size_bytes(between_type, get_type_size_bytes(old_bp_type) + get_type_size_bytes(ret_addr_type));
	}

	return between_type;
}

Michael Beck's avatar
Michael Beck committed
185
186
187
188
static const be_abi_callbacks_t TEMPLATE_abi_callbacks = {
	TEMPLATE_get_between_type,
};

Christian Würdig's avatar
Christian Würdig committed
189
190
191
192
193
194
/**
 * Get the ABI restrictions for procedure calls.
 * @param self        The this pointer.
 * @param method_type The type of the method (procedure) in question.
 * @param abi         The abi object to be modified
 */
195
static void TEMPLATE_get_call_abi(ir_type *method_type, be_abi_call_t *abi)
Matthias Braun's avatar
Matthias Braun committed
196
{
Christian Würdig's avatar
Christian Würdig committed
197
198
199
	ir_type  *tp;
	ir_mode  *mode;
	int       i, n = get_method_n_params(method_type);
200
201

	/* set abi flags for calls */
202
	be_abi_call_flags_t call_flags = be_abi_call_get_flags(abi);
203
	call_flags.call_has_imm = true;
Michael Beck's avatar
Michael Beck committed
204
	be_abi_call_set_flags(abi, call_flags, &TEMPLATE_abi_callbacks);
Christian Würdig's avatar
Christian Würdig committed
205
206
207
208

	for (i = 0; i < n; i++) {
		/* TODO: implement register parameter: */
		/* reg = get reg for param i;          */
209
		/* be_abi_call_param_reg(abi, i, reg, ABI_CONTEXT_BOTH); */
Christian Würdig's avatar
Christian Würdig committed
210
211

		/* default: all parameters on stack */
212
213
		tp   = get_method_param_type(method_type, i);
		mode = get_type_mode(tp);
214
		be_abi_call_param_stack(abi, i, mode, 4, 0, 0, ABI_CONTEXT_BOTH);
Christian Würdig's avatar
Christian Würdig committed
215
216
217
218
219
220
221
222
223
	}

	/* TODO: set correct return register */
	/* default: return value is in R0 resp. F0 */
	if (get_method_n_ress(method_type) > 0) {
		tp   = get_method_res_type(method_type, 0);
		mode = get_type_mode(tp);

		be_abi_call_res_reg(abi, 0,
224
			mode_is_float(mode) ? &TEMPLATE_registers[REG_F0] : &TEMPLATE_registers[REG_R0], ABI_CONTEXT_BOTH);
Christian Würdig's avatar
Christian Würdig committed
225
226
227
	}
}

228
229
static void TEMPLATE_lower_for_target(void)
{
230
231
	lower_builtins(0, NULL);

232
	/* lower compound param handling */
233
	lower_calls_with_compounds(LF_RETURN_HIDDEN);
234
235
}

236
237
238
239
240
241
242
243
244
static int TEMPLATE_is_mux_allowed(ir_node *sel, ir_node *mux_false,
                                   ir_node *mux_true)
{
	(void) sel;
	(void) mux_false;
	(void) mux_true;
	return false;
}

245
246
247
/**
 * Returns the libFirm configuration parameter for this backend.
 */
248
249
static const backend_params *TEMPLATE_get_backend_params(void)
{
250
	static backend_params p = {
251
		0,     /* no support for Rotl nodes */
252
		0,     /* 0: little-endian, 1: big-endian */
253
254
		1,     /* modulo shift efficient */
		0,     /* non-modulo shift efficient */
255
		NULL,  /* architecture dependent settings, will be set later */
256
		TEMPLATE_is_mux_allowed,  /* parameter for if conversion */
257
		32,    /* machine size - a 32bit CPU */
258
		NULL,  /* float arithmetic mode */
259
260
261
		NULL,  /* long long type */
		NULL,  /* unsigned long long type */
		NULL,  /* long double type */
262
263
		0,     /* no trampoline support: size 0 */
		0,     /* no trampoline support: align 0 */
264
265
		NULL,  /* no trampoline support: no trampoline builder */
		4      /* alignment of stack parameter: typically 4 (32bit) or 8 (64bit) */
266
267
268
269
	};
	return &p;
}

270
static int TEMPLATE_is_valid_clobber(const char *clobber)
271
272
{
	(void) clobber;
273
	return 0;
274
}
Michael Beck's avatar
Michael Beck committed
275

276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
/**
 * Check if the given register is callee or caller save.
 */
static int TEMPLATE_register_saved_by(const arch_register_t *reg, int callee)
{
	if (callee) {
		/* check for callee saved */
		if (reg->reg_class == &TEMPLATE_reg_classes[CLASS_TEMPLATE_gp]) {
			switch (reg->index) {
			case REG_GP_R7:
			case REG_GP_R8:
			case REG_GP_R9:
			case REG_GP_R10:
			case REG_GP_R11:
			case REG_GP_R12:
			case REG_GP_R13:
				return 1;
			default:
				return 0;
			}
		}
	} else {
		/* check for caller saved */
		if (reg->reg_class == &TEMPLATE_reg_classes[CLASS_TEMPLATE_gp]) {
			switch (reg->index) {
			case REG_GP_R0:
			case REG_GP_R1:
			case REG_GP_R2:
			case REG_GP_R3:
			case REG_GP_R4:
			case REG_GP_R5:
			case REG_GP_R6:
				return 1;
			default:
				return 0;
			}
		} else if (reg->reg_class == &TEMPLATE_reg_classes[CLASS_TEMPLATE_fp]) {
			/* all FP registers are caller save */
			return 1;
		}
	}
	return 0;
}

320
321
const arch_isa_if_t TEMPLATE_isa_if = {
	TEMPLATE_init,
Matthias Braun's avatar
Matthias Braun committed
322
	TEMPLATE_finish,
323
    TEMPLATE_get_backend_params,
324
	TEMPLATE_lower_for_target,
325
326
	TEMPLATE_is_valid_clobber,

327
328
	TEMPLATE_begin_codegeneration,
	TEMPLATE_end_codegeneration,
329
	TEMPLATE_init_graph,
330
331
332
333
334
335
336
337
338
	TEMPLATE_get_call_abi,
	NULL, /* mark remat */
	NULL, /* get_pic_base */
	be_new_spill,
	be_new_reload,
	TEMPLATE_register_saved_by,

	NULL, /* handle intrinsics */
	NULL, /* before_abi */
339
340
341
342
	TEMPLATE_prepare_graph,
	TEMPLATE_before_ra,
	TEMPLATE_finish_irg,
	TEMPLATE_emit_routine,
343
};
344

Matthias Braun's avatar
Matthias Braun committed
345
BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_TEMPLATE)
346
347
348
void be_init_arch_TEMPLATE(void)
{
	be_register_isa_if("TEMPLATE", &TEMPLATE_isa_if);
349
350
	FIRM_DBG_REGISTER(dbg, "firm.be.TEMPLATE.cg");
	TEMPLATE_init_transform();
351
}