bearch_ia32.c 30.9 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
3
4
5
6
/**
 * This is the main ia32 firm backend driver.
 *
 * $Id$
 */

7
8
9
10
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

Christian Würdig's avatar
Christian Würdig committed
11
12
13
14
15
16
#ifdef _WIN32
#include <malloc.h>
#else
#include <alloca.h>
#endif

Christian Würdig's avatar
Christian Würdig committed
17
18
#include "pseudo_irg.h"
#include "irgwalk.h"
Christian Würdig's avatar
Christian Würdig committed
19
20
#include "irprog.h"
#include "irprintf.h"
21
#include "iredges_t.h"
22
#include "ircons.h"
Christian Würdig's avatar
Christian Würdig committed
23
#include "irgmod.h"
Christian Würdig's avatar
Christian Würdig committed
24
#include "irgopt.h"
Christian Würdig's avatar
Christian Würdig committed
25
26
27
28

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

29
#include "../beabi.h"                 /* the general register allocator interface */
30
#include "../benode_t.h"
31
#include "../belower.h"
Christian Würdig's avatar
Christian Würdig committed
32
#include "../besched_t.h"
Christian Würdig's avatar
Christian Würdig committed
33
#include "../be.h"
34
#include "bearch_ia32_t.h"
Christian Würdig's avatar
Christian Würdig committed
35
36
37
38
39

#include "ia32_new_nodes.h"           /* ia32 nodes interface */
#include "gen_ia32_regalloc_if.h"     /* the generated interface (register type and class defenitions) */
#include "ia32_gen_decls.h"           /* interface declaration emitter */
#include "ia32_transform.h"
Christian Würdig's avatar
Christian Würdig committed
40
41
#include "ia32_emitter.h"
#include "ia32_map_regs.h"
Christian Würdig's avatar
Christian Würdig committed
42
#include "ia32_optimize.h"
43
#include "ia32_x87.h"
Christian Würdig's avatar
Christian Würdig committed
44

Christian Würdig's avatar
Christian Würdig committed
45
#define DEBUG_MODULE "firm.be.ia32.isa"
Christian Würdig's avatar
Christian Würdig committed
46

Christian Würdig's avatar
Christian Würdig committed
47
48
/* TODO: ugly */
static set *cur_reg_set = NULL;
Christian Würdig's avatar
Christian Würdig committed
49

Christian Würdig's avatar
Christian Würdig committed
50
51
#undef is_Start
#define is_Start(irn) (get_irn_opcode(irn) == iro_Start)
Christian Würdig's avatar
Christian Würdig committed
52

53
ir_node *ia32_new_NoReg_gp(ia32_code_gen_t *cg) {
54
	return be_abi_get_callee_save_irn(cg->birg->abi, &ia32_gp_regs[REG_GP_NOREG]);
55
56
57
}

ir_node *ia32_new_NoReg_fp(ia32_code_gen_t *cg) {
58
59
	return be_abi_get_callee_save_irn(cg->birg->abi,
		USE_SSE2(cg) ? &ia32_xmm_regs[REG_XMM_NOREG] : &ia32_vfp_regs[REG_VFP_NOREG]);
60
}
61

Christian Würdig's avatar
Christian Würdig committed
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/**************************************************
 *                         _ _              _  __
 *                        | | |            (_)/ _|
 *  _ __ ___  __ _    __ _| | | ___   ___   _| |_
 * | '__/ _ \/ _` |  / _` | | |/ _ \ / __| | |  _|
 * | | |  __/ (_| | | (_| | | | (_) | (__  | | |
 * |_|  \___|\__, |  \__,_|_|_|\___/ \___| |_|_|
 *            __/ |
 *           |___/
 **************************************************/

static ir_node *my_skip_proj(const ir_node *n) {
	while (is_Proj(n))
		n = get_Proj_pred(n);
	return (ir_node *)n;
}
Christian Würdig's avatar
Christian Würdig committed
78

Sebastian Hack's avatar
Sebastian Hack committed
79

Christian Würdig's avatar
Christian Würdig committed
80
81
82
83
84
/**
 * Return register requirements for an ia32 node.
 * If the node returns a tuple (mode_T) then the proj's
 * will be asked for this information.
 */
Christian Würdig's avatar
Christian Würdig committed
85
static const arch_register_req_t *ia32_get_irn_reg_req(const void *self, arch_register_req_t *req, const ir_node *irn, int pos) {
86
	const ia32_irn_ops_t      *ops = self;
87
88
	const ia32_register_req_t *irn_req;
	long                       node_pos = pos == -1 ? 0 : pos;
89
	ir_mode                   *mode     = is_Block(irn) ? NULL : get_irn_mode(irn);
90
	FIRM_DBG_REGISTER(firm_dbg_module_t *mod, DEBUG_MODULE);
Christian Würdig's avatar
Christian Würdig committed
91

92
93
94
95
96
97
98
	if (is_Block(irn) || mode == mode_M || mode == mode_X) {
		DBG((mod, LEVEL_1, "ignoring Block, mode_M, mode_X node %+F\n", irn));
		return NULL;
	}

	if (mode == mode_T && pos < 0) {
		DBG((mod, LEVEL_1, "ignoring request OUT requirements for node %+F\n", irn));
Christian Würdig's avatar
Christian Würdig committed
99
100
101
102
103
		return NULL;
	}

	DBG((mod, LEVEL_1, "get requirements at pos %d for %+F ... ", pos, irn));

104
	if (is_Proj(irn)) {
105
		if (pos == -1) {
106
			node_pos = ia32_translate_proj_pos(irn);
107
108
		}
		else {
Christian Würdig's avatar
Christian Würdig committed
109
			node_pos = pos;
110
		}
Christian Würdig's avatar
Christian Würdig committed
111
112
113

		irn = my_skip_proj(irn);

Christian Würdig's avatar
Christian Würdig committed
114
		DB((mod, LEVEL_1, "skipping Proj, going to %+F at pos %d ... ", irn, node_pos));
Christian Würdig's avatar
Christian Würdig committed
115
116
117
118
	}

	if (is_ia32_irn(irn)) {
		if (pos >= 0) {
119
			irn_req = get_ia32_in_req(irn, pos);
Christian Würdig's avatar
Christian Würdig committed
120
121
		}
		else {
122
			irn_req = get_ia32_out_req(irn, node_pos);
Christian Würdig's avatar
Christian Würdig committed
123
124
		}

Christian Würdig's avatar
Christian Würdig committed
125
		DB((mod, LEVEL_1, "returning reqs for %+F at pos %d\n", irn, pos));
Christian Würdig's avatar
Christian Würdig committed
126

127
128
		memcpy(req, &(irn_req->req), sizeof(*req));

129
130
131
132
133
134
135
136
		if (arch_register_req_is(&(irn_req->req), should_be_same)) {
			assert(irn_req->same_pos >= 0 && "should be same constraint for in -> out NYI");
			req->other_same = get_irn_n(irn, irn_req->same_pos);
		}

		if (arch_register_req_is(&(irn_req->req), should_be_different)) {
			assert(irn_req->different_pos >= 0 && "should be different constraint for in -> out NYI");
			req->other_different = get_irn_n(irn, irn_req->different_pos);
137
		}
Christian Würdig's avatar
Christian Würdig committed
138
139
140
141
	}
	else {
		/* treat Phi like Const with default requirements */
		if (is_Phi(irn)) {
Christian Würdig's avatar
Christian Würdig committed
142
			DB((mod, LEVEL_1, "returning standard reqs for %+F\n", irn));
143
144
145
146
147
148
			if (mode_is_float(mode)) {
				if (USE_SSE2(ops->cg))
					memcpy(req, &(ia32_default_req_ia32_xmm.req), sizeof(*req));
				else
					memcpy(req, &(ia32_default_req_ia32_vfp.req), sizeof(*req));
			}
Christian Würdig's avatar
Christian Würdig committed
149
			else if (mode_is_int(mode) || mode_is_reference(mode))
150
				memcpy(req, &(ia32_default_req_ia32_gp.req), sizeof(*req));
Christian Würdig's avatar
Christian Würdig committed
151
152
153
154
155
156
157
158
			else if (mode == mode_T || mode == mode_M) {
				DBG((mod, LEVEL_1, "ignoring Phi node %+F\n", irn));
				return NULL;
			}
			else
				assert(0 && "unsupported Phi-Mode");
		}
		else {
Christian Würdig's avatar
Christian Würdig committed
159
			DB((mod, LEVEL_1, "returning NULL for %+F (not ia32)\n", irn));
160
			req = NULL;
Christian Würdig's avatar
Christian Würdig committed
161
162
163
164
165
		}
	}

	return req;
}
Christian Würdig's avatar
Christian Würdig committed
166

Christian Würdig's avatar
Christian Würdig committed
167
static void ia32_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) {
168
169
170
	int                   pos = 0;
	const ia32_irn_ops_t *ops = self;

171
172
173
174
	if (get_irn_mode(irn) == mode_X) {
		return;
	}

175
	DBG((ops->cg->mod, LEVEL_1, "ia32 assigned register %s to node %+F\n", reg->name, irn));
Christian Würdig's avatar
Christian Würdig committed
176

177
	if (is_Proj(irn)) {
178
		pos = ia32_translate_proj_pos(irn);
Christian Würdig's avatar
Christian Würdig committed
179
180
		irn = my_skip_proj(irn);
	}
Christian Würdig's avatar
Christian Würdig committed
181

Christian Würdig's avatar
Christian Würdig committed
182
183
	if (is_ia32_irn(irn)) {
		const arch_register_t **slots;
Christian Würdig's avatar
Christian Würdig committed
184

Christian Würdig's avatar
Christian Würdig committed
185
186
187
188
		slots      = get_ia32_slots(irn);
		slots[pos] = reg;
	}
	else {
189
		ia32_set_firm_reg(irn, reg, cur_reg_set);
Christian Würdig's avatar
Christian Würdig committed
190
	}
Christian Würdig's avatar
Christian Würdig committed
191
192
}

Christian Würdig's avatar
Christian Würdig committed
193
static const arch_register_t *ia32_get_irn_reg(const void *self, const ir_node *irn) {
Christian Würdig's avatar
Christian Würdig committed
194
195
196
	int pos = 0;
	const arch_register_t *reg = NULL;

197
	if (is_Proj(irn)) {
198
199
200
201
202

		if (get_irn_mode(irn) == mode_X) {
			return NULL;
		}

203
		pos = ia32_translate_proj_pos(irn);
Christian Würdig's avatar
Christian Würdig committed
204
205
206
207
208
209
210
211
212
		irn = my_skip_proj(irn);
	}

	if (is_ia32_irn(irn)) {
		const arch_register_t **slots;
		slots = get_ia32_slots(irn);
		reg   = slots[pos];
	}
	else {
213
		reg = ia32_get_firm_reg(irn, cur_reg_set);
Christian Würdig's avatar
Christian Würdig committed
214
215
216
	}

	return reg;
Christian Würdig's avatar
Christian Würdig committed
217
218
}

Christian Würdig's avatar
Christian Würdig committed
219
static arch_irn_class_t ia32_classify(const void *self, const ir_node *irn) {
Christian Würdig's avatar
Christian Würdig committed
220
221
222
	irn = my_skip_proj(irn);
	if (is_cfop(irn))
		return arch_irn_class_branch;
Christian Würdig's avatar
Christian Würdig committed
223
	else if (is_ia32_irn(irn))
Christian Würdig's avatar
Christian Würdig committed
224
		return arch_irn_class_normal;
Christian Würdig's avatar
Christian Würdig committed
225
226
	else
		return 0;
Christian Würdig's avatar
Christian Würdig committed
227
}
Christian Würdig's avatar
Christian Würdig committed
228

Christian Würdig's avatar
Christian Würdig committed
229
static arch_irn_flags_t ia32_get_flags(const void *self, const ir_node *irn) {
Christian Würdig's avatar
Christian Würdig committed
230
231
232
233
234
235
	irn = my_skip_proj(irn);
	if (is_ia32_irn(irn))
		return get_ia32_flags(irn);
	else {
		return 0;
	}
Christian Würdig's avatar
Christian Würdig committed
236
237
}

Christian Würdig's avatar
Christian Würdig committed
238
239
static entity *ia32_get_frame_entity(const void *self, const ir_node *irn) {
	return is_ia32_irn(irn) ? get_ia32_frame_ent(irn) : NULL;
240
241
}

242
static void ia32_set_stack_bias(const void *self, ir_node *irn, int bias) {
Christian Würdig's avatar
Christian Würdig committed
243
244
245
	char buf[64];
	const ia32_irn_ops_t *ops = self;

Christian Würdig's avatar
Christian Würdig committed
246
	if (get_ia32_frame_ent(irn)) {
Christian Würdig's avatar
Christian Würdig committed
247
248
249
250
		ia32_am_flavour_t am_flav = get_ia32_am_flavour(irn);

		DBG((ops->cg->mod, LEVEL_1, "stack biased %+F with %d\n", irn, bias));
		snprintf(buf, sizeof(buf), "%d", bias);
Christian Würdig's avatar
Christian Würdig committed
251
252
253
254
255
256
257
258
259

		if (get_ia32_op_type(irn) == ia32_Normal) {
			set_ia32_cnst(irn, buf);
		}
		else {
			add_ia32_am_offs(irn, buf);
			am_flav |= ia32_O;
			set_ia32_am_flavour(irn, am_flav);
		}
260
261
262
	}
}

Sebastian Hack's avatar
Sebastian Hack committed
263
264
265
266
267
268
typedef struct {
	be_abi_call_flags_bits_t flags;
	const arch_isa_t *isa;
	ir_graph *irg;
} ia32_abi_env_t;

Sebastian Hack's avatar
Sebastian Hack committed
269
static void *ia32_abi_init(const be_abi_call_t *call, const arch_env_t *aenv, ir_graph *irg)
Sebastian Hack's avatar
Sebastian Hack committed
270
271
272
273
274
{
	ia32_abi_env_t *env    = xmalloc(sizeof(env[0]));
	be_abi_call_flags_t fl = be_abi_call_get_flags(call);
	env->flags = fl.bits;
	env->irg   = irg;
Sebastian Hack's avatar
Sebastian Hack committed
275
	env->isa   = aenv->isa;
Sebastian Hack's avatar
Sebastian Hack committed
276
277
278
279
280
281
282
283
284
285
	return env;
}

static void ia32_abi_dont_save_regs(void *self, pset *s)
{
	ia32_abi_env_t *env = self;
	if(env->flags.try_omit_fp)
		pset_insert_ptr(s, env->isa->bp);
}

Sebastian Hack's avatar
Sebastian Hack committed
286
static const arch_register_t *ia32_abi_prologue(void *self, ir_node **mem, pmap *reg_map)
Sebastian Hack's avatar
Sebastian Hack committed
287
{
Sebastian Hack's avatar
Sebastian Hack committed
288
289
290
291
292
293
294
295
	ia32_abi_env_t *env              = self;
	const arch_register_t *frame_reg = env->isa->sp;

	if(!env->flags.try_omit_fp) {
		int reg_size         = get_mode_size_bytes(env->isa->bp->reg_class->mode);
		ir_node *bl          = get_irg_start_block(env->irg);
		ir_node *curr_sp     = be_abi_reg_map_get(reg_map, env->isa->sp);
		ir_node *curr_bp     = be_abi_reg_map_get(reg_map, env->isa->bp);
296
		ir_node *curr_no_reg = be_abi_reg_map_get(reg_map, &ia32_gp_regs[REG_GP_NOREG]);
Sebastian Hack's avatar
Sebastian Hack committed
297
298
		ir_node *store_bp;

299
		curr_sp  = be_new_IncSP(env->isa->sp, env->irg, bl, curr_sp, *mem, reg_size, be_stack_dir_expand);
Sebastian Hack's avatar
Sebastian Hack committed
300
		store_bp = new_rd_ia32_Store(NULL, env->irg, bl, curr_sp, curr_no_reg, curr_bp, *mem, mode_T);
Daniel Grund's avatar
Daniel Grund committed
301
302
303
		set_ia32_am_support(store_bp, ia32_am_Dest);
		set_ia32_am_flavour(store_bp, ia32_B);
		set_ia32_op_type(store_bp, ia32_AddrModeD);
Sebastian Hack's avatar
Sebastian Hack committed
304
305
306
307
308
309
310
311
312
313
		*mem     = new_r_Proj(env->irg, bl, store_bp, mode_M, 0);
		curr_bp  = be_new_Copy(env->isa->bp->reg_class, env->irg, bl, curr_sp);
		be_set_constr_single_reg(curr_bp, BE_OUT_POS(0), env->isa->bp);
		be_node_set_flags(curr_bp, BE_OUT_POS(0), arch_irn_flags_ignore);

		be_abi_reg_map_set(reg_map, env->isa->sp, curr_sp);
		be_abi_reg_map_set(reg_map, env->isa->bp, curr_bp);
	}

	return frame_reg;
Sebastian Hack's avatar
Sebastian Hack committed
314
315
316
317
}

static void ia32_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_map)
{
Sebastian Hack's avatar
Sebastian Hack committed
318
319
320
	ia32_abi_env_t *env = self;
	ir_node *curr_sp     = be_abi_reg_map_get(reg_map, env->isa->sp);
	ir_node *curr_bp     = be_abi_reg_map_get(reg_map, env->isa->bp);
321
	ir_node *curr_no_reg = be_abi_reg_map_get(reg_map, &ia32_gp_regs[REG_GP_NOREG]);
Sebastian Hack's avatar
Sebastian Hack committed
322
323

	if(env->flags.try_omit_fp) {
324
		curr_sp = be_new_IncSP(env->isa->sp, env->irg, bl, curr_sp, *mem, BE_STACK_FRAME_SIZE, be_stack_dir_shrink);
Sebastian Hack's avatar
Sebastian Hack committed
325
326
327
328
329
330
331
332
	}

	else {
		ir_node *load_bp;
		ir_mode *mode_bp = env->isa->bp->reg_class->mode;

		curr_sp = be_new_SetSP(env->isa->sp, env->irg, bl, curr_sp, curr_bp, *mem);
		load_bp = new_rd_ia32_Load(NULL, env->irg, bl, curr_sp, curr_no_reg, *mem, mode_T);
Daniel Grund's avatar
Daniel Grund committed
333
334
335
		set_ia32_am_support(load_bp, ia32_am_Source);
		set_ia32_am_flavour(load_bp, ia32_B);
		set_ia32_op_type(load_bp, ia32_AddrModeS);
Sebastian Hack's avatar
Sebastian Hack committed
336
337
338
339
340
341
342
		set_ia32_ls_mode(load_bp, mode_bp);
		curr_bp = new_r_Proj(env->irg, bl, load_bp, mode_bp, 0);
		*mem    = new_r_Proj(env->irg, bl, load_bp, mode_M, 1);
	}

	be_abi_reg_map_set(reg_map, env->isa->sp, curr_sp);
	be_abi_reg_map_set(reg_map, env->isa->bp, curr_bp);
Sebastian Hack's avatar
Sebastian Hack committed
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
}

/**
 * Produces the type which sits between the stack args and the locals on the stack.
 * it will contain the return address and space to store the old base pointer.
 * @return The Firm type modeling the ABI between type.
 */
static ir_type *ia32_abi_get_between_type(void *self)
{
	static ir_type *omit_fp_between_type = NULL;
	static ir_type *between_type         = NULL;

	ia32_abi_env_t *env = self;

	if(!between_type) {
		entity *old_bp_ent;
		entity *ret_addr_ent;
		entity *omit_fp_ret_addr_ent;

		ir_type *old_bp_type   = new_type_primitive(new_id_from_str("bp"), mode_P);
		ir_type *ret_addr_type = new_type_primitive(new_id_from_str("return_addr"), mode_P);

		between_type           = new_type_class(new_id_from_str("ia32_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("ret_addr"), ret_addr_type);

		set_entity_offset_bytes(old_bp_ent, 0);
		set_entity_offset_bytes(ret_addr_ent, get_type_size_bytes(old_bp_type));
		set_type_size_bytes(between_type, get_type_size_bytes(old_bp_type) + get_type_size_bytes(ret_addr_type));

		omit_fp_between_type   = new_type_class(new_id_from_str("ia32_between_type_omit_fp"));
		omit_fp_ret_addr_ent   = new_entity(omit_fp_between_type, new_id_from_str("ret_addr"), ret_addr_type);

		set_entity_offset_bytes(omit_fp_ret_addr_ent, 0);
		set_type_size_bytes(omit_fp_between_type, get_type_size_bytes(ret_addr_type));
	}

	return env->flags.try_omit_fp ? omit_fp_between_type : between_type;
}

static const be_abi_callbacks_t ia32_abi_callbacks = {
	ia32_abi_init,
	free,
	ia32_abi_get_between_type,
	ia32_abi_dont_save_regs,
	ia32_abi_prologue,
	ia32_abi_epilogue,
};

Christian Würdig's avatar
Christian Würdig committed
392
393
/* fill register allocator interface */

Christian Würdig's avatar
Christian Würdig committed
394
static const arch_irn_ops_if_t ia32_irn_ops_if = {
Christian Würdig's avatar
Christian Würdig committed
395
396
397
398
	ia32_get_irn_reg_req,
	ia32_set_irn_reg,
	ia32_get_irn_reg,
	ia32_classify,
399
	ia32_get_flags,
400
	ia32_get_frame_entity,
401
	ia32_set_stack_bias
Christian Würdig's avatar
Christian Würdig committed
402
403
};

Christian Würdig's avatar
Christian Würdig committed
404
405
406
407
408
ia32_irn_ops_t ia32_irn_ops = {
	&ia32_irn_ops_if,
	NULL
};

Christian Würdig's avatar
Christian Würdig committed
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426


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

/**
 * Transforms the standard firm graph into
 * an ia32 firm graph
 */
static void ia32_prepare_graph(void *self) {
Christian Würdig's avatar
Christian Würdig committed
427
	ia32_code_gen_t *cg = self;
428
	DEBUG_ONLY(firm_dbg_module_t *old_mod = cg->mod;)
429

430
	FIRM_DBG_REGISTER(cg->mod, "firm.be.ia32.transform");
Christian Würdig's avatar
Christian Würdig committed
431
	irg_walk_blkwise_graph(cg->irg, ia32_place_consts_set_modes, ia32_transform_node, cg);
Christian Würdig's avatar
Christian Würdig committed
432
	be_dump(cg->irg, "-transformed", dump_ir_block_graph_sched);
Christian Würdig's avatar
Christian Würdig committed
433

434
	DEBUG_ONLY(cg->mod = old_mod;)
435
436

	if (cg->opt.doam) {
437
438
439
440
		edges_deactivate(cg->irg);
		//dead_node_elimination(cg->irg);
		edges_activate(cg->irg);

441
		irg_walk_blkwise_graph(cg->irg, NULL, ia32_optimize_am, cg);
Christian Würdig's avatar
Christian Würdig committed
442
		be_dump(cg->irg, "-am", dump_ir_block_graph_sched);
443
	}
Christian Würdig's avatar
Christian Würdig committed
444
445
}

Christian Würdig's avatar
Christian Würdig committed
446

Christian Würdig's avatar
Christian Würdig committed
447
448
449
/**
 * Insert copies for all ia32 nodes where the should_be_same requirement
 * is not fulfilled.
Christian Würdig's avatar
Christian Würdig committed
450
 * Transform Sub into Neg -- Add if IN2 == OUT
Christian Würdig's avatar
Christian Würdig committed
451
452
453
454
 */
static void ia32_finish_irg_walker(ir_node *irn, void *env) {
	ia32_code_gen_t            *cg = env;
	const ia32_register_req_t **reqs;
Christian Würdig's avatar
Christian Würdig committed
455
	const arch_register_t      *out_reg, *in_reg, *in2_reg;
Christian Würdig's avatar
Christian Würdig committed
456
	int                         n_res, i;
Christian Würdig's avatar
Christian Würdig committed
457
	ir_node                    *copy, *in_node, *block, *in2_node;
Christian Würdig's avatar
Christian Würdig committed
458
	ia32_op_type_t              op_tp;
Christian Würdig's avatar
Christian Würdig committed
459

460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
	if (is_ia32_irn(irn)) {
		/* AM Dest nodes don't produce any values  */
		op_tp = get_ia32_op_type(irn);
		if (op_tp == ia32_AddrModeD)
			return;

		reqs  = get_ia32_out_req_all(irn);
		n_res = get_ia32_n_res(irn);
		block = get_nodes_block(irn);

		/* check all OUT requirements, if there is a should_be_same */
		if (op_tp == ia32_Normal) {
			for (i = 0; i < n_res; i++) {
				if (arch_register_req_is(&(reqs[i]->req), should_be_same)) {
					/* get in and out register */
Christian Würdig's avatar
Christian Würdig committed
475
476
477
478
479
					out_reg  = get_ia32_out_reg(irn, i);
					in_node  = get_irn_n(irn, reqs[i]->same_pos);
					in_reg   = arch_get_irn_register(cg->arch_env, in_node);
					in2_node = get_irn_n(irn, reqs[i]->same_pos ^ 1);
					in2_reg  = arch_get_irn_register(cg->arch_env, in2_node);
480
481

					/* don't copy ignore nodes */
Christian Würdig's avatar
Christian Würdig committed
482
					if (arch_irn_is(cg->arch_env, in_node, ignore) && is_Proj(in_node))
483
484
485
						continue;

					/* check if in and out register are equal */
Christian Würdig's avatar
Christian Würdig committed
486
487
					if (! REGS_ARE_EQUAL(out_reg, in_reg)) {
						/* in case of a commutative op: just exchange the in's */
Christian Würdig's avatar
Christian Würdig committed
488
489
490
						if (is_ia32_commutative(irn) && REGS_ARE_EQUAL(out_reg, in2_reg)) {
							set_irn_n(irn, reqs[i]->same_pos, in2_node);
							set_irn_n(irn, reqs[i]->same_pos ^ 1, in_node);
Christian Würdig's avatar
Christian Würdig committed
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
						}
						else {
							DBG((cg->mod, LEVEL_1, "inserting copy for %+F in_pos %d\n", irn, reqs[i]->same_pos));
							/* create copy from in register */
							copy = be_new_Copy(arch_register_get_class(in_reg), cg->irg, block, in_node);

							/* destination is the out register */
							arch_set_irn_register(cg->arch_env, copy, out_reg);

							/* insert copy before the node into the schedule */
							sched_add_before(irn, copy);

							/* set copy as in */
							set_irn_n(irn, reqs[i]->same_pos, copy);
						}
506
					}
507
				}
Christian Würdig's avatar
Christian Würdig committed
508
509
			}
		}
Christian Würdig's avatar
Christian Würdig committed
510

511
512
513
514
515
516
517
518
519
		/* If we have a CondJmp with immediate, we need to    */
		/* check if it's the right operand, otherwise we have */
		/* to change it, as CMP doesn't support immediate as  */
		/* left operands.                                     */
		if (is_ia32_CondJmp(irn) && (is_ia32_ImmConst(irn) || is_ia32_ImmSymConst(irn)) && op_tp == ia32_AddrModeS) {
			long pnc = get_negated_pnc(get_ia32_pncode(irn), get_ia32_res_mode(irn));
			set_ia32_op_type(irn, ia32_AddrModeD);
			set_ia32_pncode(irn, pnc);
		}
Christian Würdig's avatar
Christian Würdig committed
520

521
522
		/* check if there is a sub which need to be transformed */
		ia32_transform_sub_to_neg_add(irn, cg);
523

524
525
526
		/* transform a LEA into an Add if possible */
		ia32_transform_lea_to_add(irn, cg);
	}
527
528
529

	/* check for peephole optimization */
	ia32_peephole_optimization(irn, cg);
Christian Würdig's avatar
Christian Würdig committed
530
}
Christian Würdig's avatar
Christian Würdig committed
531
532

/**
Christian Würdig's avatar
Christian Würdig committed
533
 * Add Copy nodes for not fulfilled should_be_equal constraints
Christian Würdig's avatar
Christian Würdig committed
534
 */
Christian Würdig's avatar
Christian Würdig committed
535
static void ia32_finish_irg(ir_graph *irg, ia32_code_gen_t *cg) {
Christian Würdig's avatar
Christian Würdig committed
536
	irg_walk_blkwise_graph(irg, NULL, ia32_finish_irg_walker, cg);
Christian Würdig's avatar
Christian Würdig committed
537
538
}

539
540


541
/**
542
 * Dummy functions for hooks we don't need but which must be filled.
543
 */
544
static void ia32_before_sched(void *self) {
545
546
}

547
548
549
550
551
/**
 * Called before the register allocator.
 * Calculate a block schedule here. We need it for the x87
 * simulator and the emitter.
 */
552
static void ia32_before_ra(void *self) {
553
	ia32_code_gen_t *cg = self;
554

555
556
	cg->blk_sched = sched_create_block_schedule(cg->irg);
}
557

Christian Würdig's avatar
Christian Würdig committed
558

Christian Würdig's avatar
Christian Würdig committed
559
560
561
562
/**
 * Transforms a be node into a Load.
 */
static void transform_to_Load(ia32_transform_env_t *env) {
Christian Würdig's avatar
Christian Würdig committed
563
564
565
566
567
	ir_node *irn         = env->irn;
	entity  *ent         = be_get_frame_entity(irn);
	ir_mode *mode        = env->mode;
	ir_node *noreg       = ia32_new_NoReg_gp(env->cg);
	ir_node *nomem       = new_rd_NoMem(env->irg);
Christian Würdig's avatar
Christian Würdig committed
568
	ir_node *sched_point = NULL;
Christian Würdig's avatar
Christian Würdig committed
569
570
571
	ir_node *ptr         = get_irn_n(irn, 0);
	ir_node *mem         = be_is_Reload(irn) ? get_irn_n(irn, 1) : nomem;
	ir_node *new_op, *proj;
572
	const arch_register_t *reg;
Christian Würdig's avatar
Christian Würdig committed
573
574
575
576
577
578

	if (sched_is_scheduled(irn)) {
		sched_point = sched_prev(irn);
	}

	if (mode_is_float(mode)) {
579
580
581
582
		if (USE_SSE2(env->cg))
			new_op = new_rd_ia32_fLoad(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T);
		else
			new_op = new_rd_ia32_vfld(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T);
Christian Würdig's avatar
Christian Würdig committed
583
584
	}
	else {
Christian Würdig's avatar
Christian Würdig committed
585
		new_op = new_rd_ia32_Load(env->dbg, env->irg, env->block, ptr, noreg, mem, mode_T);
Christian Würdig's avatar
Christian Würdig committed
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
	}

	set_ia32_am_support(new_op, ia32_am_Source);
	set_ia32_op_type(new_op, ia32_AddrModeS);
	set_ia32_am_flavour(new_op, ia32_B);
	set_ia32_ls_mode(new_op, mode);
	set_ia32_frame_ent(new_op, ent);
	set_ia32_use_frame(new_op);

	proj = new_rd_Proj(env->dbg, env->irg, env->block, new_op, mode, pn_Load_res);

	if (sched_point) {
		sched_add_after(sched_point, new_op);
		sched_add_after(new_op, proj);

		sched_remove(irn);
	}

604
605
	/* copy the register from the old node to the new Load */
	reg = arch_get_irn_register(env->cg->arch_env, irn);
Christian Würdig's avatar
Christian Würdig committed
606
	arch_set_irn_register(env->cg->arch_env, new_op, reg);
607

Christian Würdig's avatar
Christian Würdig committed
608
	SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, new_op));
Christian Würdig's avatar
Christian Würdig committed
609

Christian Würdig's avatar
Christian Würdig committed
610
	exchange(irn, proj);
Christian Würdig's avatar
Christian Würdig committed
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
}

/**
 * Transforms a be node into a Store.
 */
static void transform_to_Store(ia32_transform_env_t *env) {
	ir_node *irn   = env->irn;
	entity  *ent   = be_get_frame_entity(irn);
	ir_mode *mode  = env->mode;
	ir_node *noreg = ia32_new_NoReg_gp(env->cg);
	ir_node *nomem = new_rd_NoMem(env->irg);
	ir_node *ptr   = get_irn_n(irn, 0);
	ir_node *val   = get_irn_n(irn, 1);
	ir_node *new_op, *proj;
	ir_node *sched_point = NULL;

	if (sched_is_scheduled(irn)) {
		sched_point = sched_prev(irn);
	}

	if (mode_is_float(mode)) {
632
633
634
635
		if (USE_SSE2(env->cg))
			new_op = new_rd_ia32_fStore(env->dbg, env->irg, env->block, ptr, noreg, val, nomem, mode_T);
		else
			new_op = new_rd_ia32_vfst(env->dbg, env->irg, env->block, ptr, noreg, val, nomem, mode_T);
Christian Würdig's avatar
Christian Würdig committed
636
	}
637
638
639
	else if (get_mode_size_bits(mode) == 8) {
		new_op = new_rd_ia32_Store8Bit(env->dbg, env->irg, env->block, ptr, noreg, val, nomem, mode_T);
	}
Christian Würdig's avatar
Christian Würdig committed
640
641
642
643
644
645
646
	else {
		new_op = new_rd_ia32_Store(env->dbg, env->irg, env->block, ptr, noreg, val, nomem, mode_T);
	}

	set_ia32_am_support(new_op, ia32_am_Dest);
	set_ia32_op_type(new_op, ia32_AddrModeD);
	set_ia32_am_flavour(new_op, ia32_B);
Christian Würdig's avatar
Christian Würdig committed
647
	set_ia32_ls_mode(new_op, mode);
Christian Würdig's avatar
Christian Würdig committed
648
649
650
	set_ia32_frame_ent(new_op, ent);
	set_ia32_use_frame(new_op);

651
	proj = new_rd_Proj(env->dbg, env->irg, env->block, new_op, mode_M, 0);
Christian Würdig's avatar
Christian Würdig committed
652
653
654
655
656
657
658
659

	if (sched_point) {
		sched_add_after(sched_point, new_op);
		sched_add_after(new_op, proj);

		sched_remove(irn);
	}

Christian Würdig's avatar
Christian Würdig committed
660
	SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env->cg, new_op));
Christian Würdig's avatar
Christian Würdig committed
661

Christian Würdig's avatar
Christian Würdig committed
662
	exchange(irn, proj);
Christian Würdig's avatar
Christian Würdig committed
663
664
665
}

/**
666
 * Fix the mode of Spill/Reload
Christian Würdig's avatar
Christian Würdig committed
667
 */
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
static ir_mode *fix_spill_mode(ia32_code_gen_t *cg, ir_mode *mode)
{
	if (mode_is_float(mode)) {
		if (USE_SSE2(cg))
			mode = mode_D;
		else
			mode = mode_E;
	}
	else
		mode = mode_Is;
	return mode;
}

/**
 * Block-Walker: Calls the transform functions Spill and Reload.
 */
static void ia32_after_ra_walker(ir_node *block, void *env) {
	ir_node *node, *prev;
Christian Würdig's avatar
Christian Würdig committed
686
687
688
	ia32_code_gen_t *cg = env;
	ia32_transform_env_t tenv;

689
	tenv.block = block;
Christian Würdig's avatar
Christian Würdig committed
690
691
	tenv.irg   = current_ir_graph;
	tenv.cg    = cg;
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
	DEBUG_ONLY(tenv.mod = cg->mod;)

	/* beware: the schedule is changed here */
	for (node = sched_last(block); !sched_is_begin(node); node = prev) {
		prev = sched_prev(node);
		if (be_is_Reload(node)) {
			/* we always reload the whole register  */
			tenv.dbg  = get_irn_dbg_info(node);
			tenv.irn  = node;
			tenv.mode = fix_spill_mode(cg, get_irn_mode(node));
			transform_to_Load(&tenv);
		}
		else if (be_is_Spill(node)) {
			/* we always spill the whole register  */
			tenv.dbg  = get_irn_dbg_info(node);
			tenv.irn  = node;
			tenv.mode = fix_spill_mode(cg, get_irn_mode(be_get_Spill_context(node)));
			transform_to_Store(&tenv);
		}
Christian Würdig's avatar
Christian Würdig committed
711
712
713
714
	}
}

/**
715
 * We transform Spill and Reload here. This needs to be done before
Christian Würdig's avatar
Christian Würdig committed
716
 * stack biasing otherwise we would miss the corrected offset for these nodes.
717
718
719
 *
 * If x87 instruction should be emitted, run the x87 simulator and patch
 * the virtual instructions. This must obviously be done after register allocation.
Christian Würdig's avatar
Christian Würdig committed
720
721
722
 */
static void ia32_after_ra(void *self) {
	ia32_code_gen_t *cg = self;
723
	irg_block_walk_graph(cg->irg, NULL, ia32_after_ra_walker, self);
724
725

	/* if we do x87 code generation, rewrite all the virtual instructions and registers */
726
	if (cg->used_x87) {
727
728
		x87_simulate_graph(cg->arch_env, cg->irg, cg->blk_sched);
	}
Christian Würdig's avatar
Christian Würdig committed
729
730
731
}


Christian Würdig's avatar
Christian Würdig committed
732
733
734
735
736
737
/**
 * Emits the code, closes the output file and frees
 * the code generator interface.
 */
static void ia32_codegen(void *self) {
	ia32_code_gen_t *cg = self;
Christian Würdig's avatar
Christian Würdig committed
738
739
	ir_graph        *irg = cg->irg;
	FILE            *out = cg->out;
Christian Würdig's avatar
Christian Würdig committed
740
741
742
743
744
745

	if (cg->emit_decls) {
		ia32_gen_decls(cg->out);
		cg->emit_decls = 0;
	}

Christian Würdig's avatar
Christian Würdig committed
746
	ia32_finish_irg(irg, cg);
Christian Würdig's avatar
Christian Würdig committed
747
	be_dump(irg, "-finished", dump_ir_block_graph_sched);
Christian Würdig's avatar
Christian Würdig committed
748
	ia32_gen_routine(out, irg, cg);
Christian Würdig's avatar
Christian Würdig committed
749
750
751

	cur_reg_set = NULL;

752
753
754
	pmap_destroy(cg->tv_ent);
	pmap_destroy(cg->types);

Christian Würdig's avatar
Christian Würdig committed
755
756
757
758
759
	/* de-allocate code generator */
	del_set(cg->reg_set);
	free(self);
}

Christian Würdig's avatar
Christian Würdig committed
760
static void *ia32_cg_init(FILE *F, const be_irg_t *birg);
Christian Würdig's avatar
Christian Würdig committed
761

Christian Würdig's avatar
Christian Würdig committed
762
static const arch_code_generator_if_t ia32_code_gen_if = {
Christian Würdig's avatar
Christian Würdig committed
763
	ia32_cg_init,
Christian Würdig's avatar
Christian Würdig committed
764
	NULL,                /* before abi introduce hook */
Christian Würdig's avatar
Christian Würdig committed
765
	ia32_prepare_graph,
766
	ia32_before_sched,   /* before scheduling hook */
Christian Würdig's avatar
Christian Würdig committed
767
	ia32_before_ra,      /* before register allocation hook */
Christian Würdig's avatar
Christian Würdig committed
768
	ia32_after_ra,       /* after register allocation hook */
Christian Würdig's avatar
Christian Würdig committed
769
	ia32_codegen         /* emit && done */
Christian Würdig's avatar
Christian Würdig committed
770
771
};

Christian Würdig's avatar
Christian Würdig committed
772
773
774
/**
 * Initializes the code generator.
 */
Christian Würdig's avatar
Christian Würdig committed
775
776
static void *ia32_cg_init(FILE *F, const be_irg_t *birg) {
	ia32_isa_t      *isa = (ia32_isa_t *)birg->main_env->arch_env->isa;
777
778
	ia32_code_gen_t *cg  = xcalloc(1, sizeof(*cg));

779
780
781
782
783
784
785
786
787
788
	cg->impl      = &ia32_code_gen_if;
	cg->irg       = birg->irg;
	cg->reg_set   = new_set(ia32_cmp_irn_reg_assoc, 1024);
	cg->out       = F;
	cg->arch_env  = birg->main_env->arch_env;
	cg->types     = pmap_create();
	cg->tv_ent    = pmap_create();
	cg->birg      = birg;
	cg->blk_sched = NULL;
	cg->fp_kind   = isa->fp_kind;
789
790
	cg->used_x87  = 0;

791
	FIRM_DBG_REGISTER(cg->mod, "firm.be.ia32.cg");
Christian Würdig's avatar
Christian Würdig committed
792

793
794
	/* set optimizations */
	cg->opt.incdec    = 0;
Christian Würdig's avatar
Christian Würdig committed
795
	cg->opt.doam      = 1;
796
797
	cg->opt.placecnst = 1;
	cg->opt.immops    = 1;
798
	cg->opt.extbb     = 1;
799

Christian Würdig's avatar
Christian Würdig committed
800
801
802
803
804
805
806
807
808
#ifndef NDEBUG
	if (isa->name_obst_size) {
		//printf("freed %d bytes from name obst\n", isa->name_obst_size);
		isa->name_obst_size = 0;
		obstack_free(isa->name_obst, NULL);
		obstack_init(isa->name_obst);
	}
#endif /* NDEBUG */

Christian Würdig's avatar
Christian Würdig committed
809
810
811
812
813
814
815
816
817
	isa->num_codegens++;

	if (isa->num_codegens > 1)
		cg->emit_decls = 0;
	else
		cg->emit_decls = 1;

	cur_reg_set = cg->reg_set;

Christian Würdig's avatar
Christian Würdig committed
818
819
	ia32_irn_ops.cg = cg;

Christian Würdig's avatar
Christian Würdig committed
820
821
822
	return (arch_code_generator_t *)cg;
}

Christian Würdig's avatar
Christian Würdig committed
823

Christian Würdig's avatar
Christian Würdig committed
824
825
826
827
828
829
830
831
832
833
834

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

835
static ia32_isa_t ia32_isa_template = {
Christian Würdig's avatar
Christian Würdig committed
836
837
838
839
840
	&ia32_isa_if,            /* isa interface implementation */
	&ia32_gp_regs[REG_ESP],  /* stack pointer register */
	&ia32_gp_regs[REG_EBP],  /* base pointer register */
	-1,                      /* stack direction */
	0,                       /* number of code generator objects so far */
841
842
	NULL,                    /* 16bit register names */
	NULL,                    /* 8bit register names */
843
	fp_sse2,                 /* use SSE2 unit for fp operations */
844
845
846
847
#ifndef NDEBUG
	NULL,                    /* name obstack */
	0                        /* name obst size */
#endif
848
849
};

Christian Würdig's avatar
Christian Würdig committed
850
/**
851
 * Initializes the backend ISA.
Christian Würdig's avatar
Christian Würdig committed
852
 */
Christian Würdig's avatar
Christian Würdig committed
853
static void *ia32_init(void) {
854
	static int inited = 0;
855
	ia32_isa_t *isa;
Christian Würdig's avatar
Christian Würdig committed
856
857
858
859

	if(inited)
		return NULL;

860
861
	isa = xcalloc(1, sizeof(*isa));
	memcpy(isa, &ia32_isa_template, sizeof(*isa));
Christian Würdig's avatar
Christian Würdig committed
862

863
	ia32_register_init(isa);
Christian Würdig's avatar
Christian Würdig committed
864
	ia32_create_opcodes();
865
	ia32_register_copy_attr_func();
Christian Würdig's avatar
Christian Würdig committed
866

867
868
	isa->regs_16bit = pmap_create();
	isa->regs_8bit  = pmap_create();
869
//	isa->fp_kind    = fp_x87;
870
871
872
873

	ia32_build_16bit_reg_map(isa->regs_16bit);
	ia32_build_8bit_reg_map(isa->regs_8bit);

Christian Würdig's avatar
Christian Würdig committed
874
875
876
#ifndef NDEBUG
	isa->name_obst = xcalloc(1, sizeof(*(isa->name_obst)));
	obstack_init(isa->name_obst);
Christian Würdig's avatar
Christian Würdig committed
877
	isa->name_obst_size = 0;
Christian Würdig's avatar
Christian Würdig committed
878
879
#endif /* NDEBUG */

880
881
	inited = 1;

Christian Würdig's avatar
Christian Würdig committed
882
	return isa;
Christian Würdig's avatar
Christian Würdig committed
883
884
}

Christian Würdig's avatar
Christian Würdig committed
885
886
887
888
889
890


/**
 * Closes the output file and frees the ISA structure.
 */
static void ia32_done(void *self) {
Christian Würdig's avatar
Christian Würdig committed
891
892
	ia32_isa_t *isa = self;

893
894
895
	pmap_destroy(isa->regs_16bit);
	pmap_destroy(isa->regs_8bit);

Christian Würdig's avatar
Christian Würdig committed
896
#ifndef NDEBUG
Christian Würdig's avatar
Christian Würdig committed
897
	//printf("name obst size = %d bytes\n", isa->name_obst_size);
Christian Würdig's avatar
Christian Würdig committed
898
899
900
	obstack_free(isa->name_obst, NULL);
#endif /* NDEBUG */

Christian Würdig's avatar
Christian Würdig committed
901
	free(self);
Christian Würdig's avatar
Christian Würdig committed
902
903
}

Christian Würdig's avatar
Christian Würdig committed
904

905
906
907
908
909
910
911
/**
 * Return the number of register classes for this architecture.
 * We report always these:
 *  - the general purpose registers
 *  - the floating point register set (depending on the unit used for FP)
 *  - MMX/SE registers (currently not supported)
 */
Christian Würdig's avatar
Christian Würdig committed
912
static int ia32_get_n_reg_class(const void *self) {
913
	return 2;
Christian Würdig's avatar
Christian Würdig committed
914
915
}

916
917
918
/**
 * Return the register class for index i.
 */
Christian Würdig's avatar
Christian Würdig committed
919
static const arch_register_class_t *ia32_get_reg_class(const void *self, int i) {
920
921
922
923
924
	const ia32_isa_t *isa = self;
	assert(i >= 0 && i < 2 && "Invalid ia32 register class requested.");
	if (i == 0)
		return &ia32_reg_classes[CLASS_ia32_gp];
	return USE_SSE2(isa) ? &ia32_reg_classes[CLASS_ia32_xmm] : &ia32_reg_classes[CLASS_ia32_vfp];
Christian Würdig's avatar
Christian Würdig committed
925
926
}

927
928
929
930
931
932
933
/**
 * Get the register class which shall be used to store a value of a given mode.
 * @param self The this pointer.
 * @param mode The mode in question.
 * @return A register class which can hold values of the given mode.
 */
const arch_register_class_t *ia32_get_reg_class_for_mode(const void *self, const ir_mode *mode) {
934
935
936
937
	const ia32_isa_t *isa = self;
	if (mode_is_float(mode)) {
		return USE_SSE2(isa) ? &ia32_reg_classes[CLASS_ia32_xmm] : &ia32_reg_classes[CLASS_ia32_vfp];
	}
938
939
940
941
942
943
944
945
946
947
	else
		return &ia32_reg_classes[CLASS_ia32_gp];
}

/**
 * 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
 */
948
949
static void ia32_get_call_abi(const void *self, ir_type *method_type, be_abi_call_t *abi) {
	const ia32_isa_t *isa = self;
950
951
952
953
954
955
	ir_type  *tp;
	ir_mode  *mode;
	unsigned  cc        = get_method_calling_convention(method_type);
	int       n         = get_method_n_params(method_type);
	int       biggest_n = -1;
	int       stack_idx = 0;
Christian Würdig's avatar
Christian Würdig committed
956
	int       i, ignore_1, ignore_2;
957
958
	ir_mode **modes;
	const arch_register_t *reg;
959
960
961
962
963
964
965
966
	be_abi_call_flags_t call_flags;

	/* set abi flags for calls */
	call_flags.bits.left_to_right         = 0;
	call_flags.bits.store_args_sequential = 0;
	call_flags.bits.try_omit_fp           = 1;
	call_flags.bits.fp_free               = 0;
	call_flags.bits.call_has_imm          = 1;
967
968

	/* set stack parameter passing style */
Sebastian Hack's avatar
Sebastian Hack committed
969
	be_abi_call_set_flags(abi, call_flags, &ia32_abi_callbacks);
970
971
972
973
974
975
976
977
978
979

	/* collect the mode for each type */
	modes = alloca(n * sizeof(modes[0]));

	for (i = 0; i < n; i++) {
		tp       = get_method_param_type(method_type, i);
		modes[i] = get_type_mode(tp);
	}

	/* set register parameters  */
980
	if (cc & cc_reg_param) {
981
		/* determine the number of parameters passed via registers */
Christian Würdig's avatar
Christian Würdig committed
982
		biggest_n = ia32_get_n_regparam_class(n, modes, &ignore_1, &ignore_2);
983
984
985
986
987
988
989
990
991
992
993
994
995
996

		/* loop over all parameters and set the register requirements */
		for (i = 0; i <= biggest_n; i++) {
			reg = ia32_get_RegParam_reg(n, modes, i, cc);
			assert(reg && "kaputt");
			be_abi_call_param_reg(abi, i, reg);
		}

		stack_idx = i;
	}


	/* set stack parameters */
	for (i = stack_idx; i < n; i++) {
997
		be_abi_call_param_stack(abi, i, 1, 0, 0);
998
999
1000
	}


For faster browsing, not all history is shown. View entire blame