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

Matthias Braun's avatar
Matthias Braun committed
20
21
22
23
/**
 * @file
 * @brief    The main TEMPLATE backend driver file.
 */
24
#include "config.h"
25

26
27
#include "bearch_TEMPLATE_t.h"

28
29
30
31
32
#include "irgwalk.h"
#include "irprog.h"
#include "irprintf.h"
#include "ircons.h"
#include "irgmod.h"
33
#include "lower_calls.h"
34
#include "lower_builtins.h"
35
36
37
38

#include "bitset.h"
#include "debug.h"

39
#include "be.h"
40
41
42
43
44
45
46
47
48
49
#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"
50

51
52
#include "TEMPLATE_new_nodes.h"
#include "gen_TEMPLATE_regalloc_if.h"
53
54
55
#include "TEMPLATE_transform.h"
#include "TEMPLATE_emitter.h"

56
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
57

58
59
static ir_entity *TEMPLATE_get_frame_entity(const ir_node *node)
{
Matthias Braun's avatar
Matthias Braun committed
60
	(void) node;
61
	/* TODO: return the ir_entity assigned to the frame */
Christian Würdig's avatar
Christian Würdig committed
62
63
64
65
66
67
68
	return NULL;
}

/**
 * This function is called by the generic backend to correct offsets for
 * nodes accessing the stack.
 */
69
70
static void TEMPLATE_set_frame_offset(ir_node *irn, int offset)
{
Matthias Braun's avatar
Matthias Braun committed
71
72
	(void) irn;
	(void) offset;
Christian Würdig's avatar
Christian Würdig committed
73
74
75
	/* TODO: correct offset if irn accesses the stack */
}

76
77
static int TEMPLATE_get_sp_bias(const ir_node *irn)
{
Matthias Braun's avatar
Matthias Braun committed
78
	(void) irn;
79
80
81
	return 0;
}

82
83
/* fill register allocator interface */

Matthias Braun's avatar
Matthias Braun committed
84
static const arch_irn_ops_t TEMPLATE_irn_ops = {
Christian Würdig's avatar
Christian Würdig committed
85
	TEMPLATE_get_frame_entity,
86
87
	TEMPLATE_set_frame_offset,
	TEMPLATE_get_sp_bias,
88
89
90
91
	NULL,    /* get_inverse             */
	NULL,    /* get_op_estimated_cost   */
	NULL,    /* possible_memory_operand */
	NULL,    /* perform_memory_operand  */
92
93
};

94

95
96
97
98
99

/**
 * Transforms the standard firm graph into
 * a TEMLPATE firm graph
 */
100
static void TEMPLATE_prepare_graph(ir_graph *irg)
101
{
102
	/* transform nodes into assembler instructions */
103
	TEMPLATE_transform_graph(irg);
104
105
106
107
108
}



/**
Christian Würdig's avatar
Christian Würdig committed
109
 * Called immediatly before emit phase.
110
 */
111
static void TEMPLATE_finish_irg(ir_graph *irg)
112
{
113
114
115
	/* fix stack entity offsets */
	be_abi_fix_stack_nodes(irg);
	be_abi_fix_stack_bias(irg);
116
117
118
}


119
static void TEMPLATE_before_ra(ir_graph *irg)
120
{
121
	(void) irg;
122
	/* Some stuff you need to do after scheduling but before register allocation */
123
124
}

125
static void TEMPLATE_init_graph(ir_graph *irg)
126
{
127
	(void) irg;
128
129
130
131
}



132
extern const arch_isa_if_t TEMPLATE_isa_if;
Christian Würdig's avatar
Christian Würdig committed
133
static TEMPLATE_isa_t TEMPLATE_isa_template = {
Matthias Braun's avatar
Matthias Braun committed
134
135
	{
		&TEMPLATE_isa_if,             /* isa interface implementation */
136
137
		N_TEMPLATE_REGISTERS,
		TEMPLATE_registers,
138
139
		N_TEMPLATE_CLASSES,
		TEMPLATE_reg_classes,
140
141
		&TEMPLATE_registers[REG_SP],  /* stack pointer register */
		&TEMPLATE_registers[REG_BP],  /* base pointer register */
142
		&TEMPLATE_reg_classes[CLASS_TEMPLATE_gp],  /* link pointer register class */
143
		2,                           /* power of two stack alignment for calls, 2^2 == 4 */
Matthias Braun's avatar
Matthias Braun committed
144
		NULL,                        /* main environment */
145
146
		7,                           /* costs for a spill instruction */
		5,                           /* costs for a reload instruction */
147
		false,                       /* no custom abi handling */
Matthias Braun's avatar
Matthias Braun committed
148
	},
Christian Würdig's avatar
Christian Würdig committed
149
150
};

151
/**
152
 * Initializes the backend ISA
153
 */
154
static arch_env_t *TEMPLATE_init(const be_main_env_t *env)
155
{
156
	TEMPLATE_isa_t *isa = XMALLOC(TEMPLATE_isa_t);
157
	*isa = TEMPLATE_isa_template;
158

Matthias Braun's avatar
Matthias Braun committed
159
	TEMPLATE_register_init();
Matthias Braun's avatar
Matthias Braun committed
160
	TEMPLATE_create_opcodes(&TEMPLATE_irn_ops);
161

162
163
164
	be_emit_init(env->file_handle);
	be_gas_begin_compilation_unit(env);

165
	return &isa->base;
166
167
168
169
170
}

/**
 * Closes the output file and frees the ISA structure.
 */
171
172
static void TEMPLATE_done(void *self)
{
173
	TEMPLATE_isa_t *isa = (TEMPLATE_isa_t*)self;
Matthias Braun's avatar
Matthias Braun committed
174
175

	/* emit now all global declarations */
176
	be_gas_end_compilation_unit(isa->base.main_env);
Matthias Braun's avatar
Matthias Braun committed
177

178
	be_emit_exit();
179
180
181
	free(self);
}

Christian Würdig's avatar
Christian Würdig committed
182
/**
Michael Beck's avatar
Michael Beck committed
183
184
185
 * 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
186
 */
187
static ir_type *TEMPLATE_get_between_type(ir_graph *irg)
Matthias Braun's avatar
Matthias Braun committed
188
{
Christian Würdig's avatar
Christian Würdig committed
189
	static ir_type *between_type = NULL;
Matthias Braun's avatar
Matthias Braun committed
190
	static ir_entity *old_bp_ent = NULL;
191
	(void) irg;
Christian Würdig's avatar
Christian Würdig committed
192

193
	if (!between_type) {
194
		ir_entity *ret_addr_ent;
195
196
		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
197
198
199
200
201

		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
202
203
		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
204
205
206
207
208
209
		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
210
211
212
213
static const be_abi_callbacks_t TEMPLATE_abi_callbacks = {
	TEMPLATE_get_between_type,
};

Christian Würdig's avatar
Christian Würdig committed
214
215
216
217
218
219
/**
 * 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
 */
220
static void TEMPLATE_get_call_abi(ir_type *method_type, be_abi_call_t *abi)
Matthias Braun's avatar
Matthias Braun committed
221
{
Christian Würdig's avatar
Christian Würdig committed
222
223
224
	ir_type  *tp;
	ir_mode  *mode;
	int       i, n = get_method_n_params(method_type);
225
226
227
228
229
230
231
	be_abi_call_flags_t call_flags;

	/* set abi flags for calls */
	call_flags.bits.store_args_sequential = 1;
	call_flags.bits.try_omit_fp           = 1;
	call_flags.bits.fp_free               = 0;
	call_flags.bits.call_has_imm          = 1;
Christian Würdig's avatar
Christian Würdig committed
232
233

	/* set stack parameter passing style */
Michael Beck's avatar
Michael Beck committed
234
	be_abi_call_set_flags(abi, call_flags, &TEMPLATE_abi_callbacks);
Christian Würdig's avatar
Christian Würdig committed
235
236
237
238

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

		/* default: all parameters on stack */
242
243
		tp   = get_method_param_type(method_type, i);
		mode = get_type_mode(tp);
244
		be_abi_call_param_stack(abi, i, mode, 4, 0, 0, ABI_CONTEXT_BOTH);
Christian Würdig's avatar
Christian Würdig committed
245
246
247
248
249
250
251
252
253
	}

	/* 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,
254
			mode_is_float(mode) ? &TEMPLATE_registers[REG_F0] : &TEMPLATE_registers[REG_R0], ABI_CONTEXT_BOTH);
Christian Würdig's avatar
Christian Würdig committed
255
256
257
	}
}

258
259
static void TEMPLATE_lower_for_target(void)
{
260
261
	lower_builtins(0, NULL);

262
	/* lower compound param handling */
263
	lower_calls_with_compounds(LF_RETURN_HIDDEN);
264
265
}

266
267
268
269
270
271
272
273
274
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;
}

275
276
277
/**
 * Returns the libFirm configuration parameter for this backend.
 */
278
279
static const backend_params *TEMPLATE_get_backend_params(void)
{
280
	static backend_params p = {
281
		0,     /* no inline assembly */
282
		0,     /* no support for Rotl nodes */
283
		0,     /* 0: little-endian, 1: big-endian */
284
285
		1,     /* modulo shift efficient */
		0,     /* non-modulo shift efficient */
286
		NULL,  /* architecture dependent settings, will be set later */
287
		TEMPLATE_is_mux_allowed,  /* parameter for if conversion */
288
		32,    /* machine size - a 32bit CPU */
289
		NULL,  /* float arithmetic mode */
290
291
292
		NULL,  /* long long type */
		NULL,  /* unsigned long long type */
		NULL,  /* long double type */
293
294
		0,     /* no trampoline support: size 0 */
		0,     /* no trampoline support: align 0 */
295
296
		NULL,  /* no trampoline support: no trampoline builder */
		4      /* alignment of stack parameter: typically 4 (32bit) or 8 (64bit) */
297
298
299
300
	};
	return &p;
}

301
static asm_constraint_flags_t TEMPLATE_parse_asm_constraint(const char **c)
302
303
304
305
306
{
	(void) c;
	return ASM_CONSTRAINT_FLAG_INVALID;
}

307
static int TEMPLATE_is_valid_clobber(const char *clobber)
308
309
{
	(void) clobber;
310
	return 0;
311
}
Michael Beck's avatar
Michael Beck committed
312

313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
/**
 * 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;
}

357
358
const arch_isa_if_t TEMPLATE_isa_if = {
	TEMPLATE_init,
359
	TEMPLATE_lower_for_target,
360
	TEMPLATE_done,
361
	NULL,                /* handle intrinsics */
Christian Würdig's avatar
Christian Würdig committed
362
	TEMPLATE_get_call_abi,
363
    TEMPLATE_get_backend_params,
364
	NULL,                    /* mark remat */
365
	TEMPLATE_parse_asm_constraint,
366
367
368
369
370
371
372
373
374
	TEMPLATE_is_valid_clobber,

	TEMPLATE_init_graph,
	NULL,   /* get_pic_base */
	NULL,   /* before_abi */
	TEMPLATE_prepare_graph,
	TEMPLATE_before_ra,
	TEMPLATE_finish_irg,
	TEMPLATE_emit_routine,
375
	TEMPLATE_register_saved_by,
376
377
	be_new_spill,
	be_new_reload,
378
};
379

Matthias Braun's avatar
Matthias Braun committed
380
BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_TEMPLATE)
381
382
383
void be_init_arch_TEMPLATE(void)
{
	be_register_isa_if("TEMPLATE", &TEMPLATE_isa_if);
384
385
	FIRM_DBG_REGISTER(dbg, "firm.be.TEMPLATE.cg");
	TEMPLATE_init_transform();
386
}