bemain.c 19.3 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
 */

6
/**
Christian Würdig's avatar
Christian Würdig committed
7
8
9
10
 * @file
 * @brief       Main Backend driver.
 * @author      Sebastian Hack
 * @date        25.11.2004
11
 */
12

13
#include <stdio.h>
14

Matthias Braun's avatar
Matthias Braun committed
15
16
#include "lc_opts.h"
#include "lc_opts_enum.h"
17

Sebastian Hack's avatar
Sebastian Hack committed
18
#include "obst.h"
19
#include "statev.h"
Sebastian Hack's avatar
Sebastian Hack committed
20
#include "irprog.h"
Sebastian Hack's avatar
Sebastian Hack committed
21
#include "irgopt.h"
Daniel Grund's avatar
Daniel Grund committed
22
#include "irdump.h"
Sebastian Hack's avatar
Sebastian Hack committed
23
24
#include "irdom_t.h"
#include "iredges_t.h"
25
#include "irloop_t.h"
Sebastian Hack's avatar
Sebastian Hack committed
26
#include "irtools.h"
27
#include "irverify.h"
Matthias Braun's avatar
Matthias Braun committed
28
#include "iroptimize.h"
Christian Würdig's avatar
Christian Würdig committed
29
#include "firmstat.h"
30
#include "execfreq_t.h"
31
#include "irprofile.h"
32
#include "ircons.h"
33
#include "util.h"
Sebastian Hack's avatar
Sebastian Hack committed
34

35
#include "bearch.h"
Sebastian Hack's avatar
Sebastian Hack committed
36
#include "be_t.h"
37
#include "begnuas.h"
38
#include "bemodule.h"
39
#include "beutil.h"
40
#include "benode.h"
41
#include "beirgmod.h"
42
#include "besched.h"
43
44
#include "belistsched.h"
#include "belive_t.h"
45
46
47
#include "bera.h"
#include "bechordal_t.h"
#include "beifg.h"
Daniel Grund's avatar
Daniel Grund committed
48
#include "becopyopt.h"
49
#include "becopystat.h"
50
#include "bessadestr.h"
Sebastian Hack's avatar
Sebastian Hack committed
51
#include "beabi.h"
Christian Würdig's avatar
Christian Würdig committed
52
#include "belower.h"
53
#include "bestat.h"
54
#include "beverify.h"
55
#include "beirg.h"
56
#include "bestack.h"
57
#include "beemitter.h"
Sebastian Hack's avatar
Sebastian Hack committed
58

59
60
#define NEW_ID(s) new_id_from_chars(s, sizeof(s) - 1)

Sebastian Hack's avatar
Sebastian Hack committed
61
/* options visible for anyone */
62
be_options_t be_options = {
63
	DUMP_NONE,                         /* dump flags */
64
	BE_TIME_OFF,                       /* no timing */
65
66
	false,                             /* profile_generate */
	false,                             /* profile_use */
Michael Beck's avatar
Michael Beck committed
67
	0,                                 /* try to omit frame pointer */
68
	0,                                 /* create PIC code */
Matthias Braun's avatar
Matthias Braun committed
69
	true,                              /* do verification */
Sebastian Hack's avatar
Sebastian Hack committed
70
	"",                                /* ilp server */
71
	"",                                /* ilp solver */
72
	1,                                 /* verbose assembler output */
Sebastian Hack's avatar
Sebastian Hack committed
73
74
75
};

/* back end instruction set architecture to use */
76
static const arch_isa_if_t *isa_if = NULL;
Michael Beck's avatar
Michael Beck committed
77

Sebastian Hack's avatar
Sebastian Hack committed
78
79
/* possible dumping options */
static const lc_opt_enum_mask_items_t dump_items[] = {
80
	{ "none",       DUMP_NONE },
Sebastian Hack's avatar
Sebastian Hack committed
81
82
83
	{ "initial",    DUMP_INITIAL },
	{ "sched",      DUMP_SCHED  },
	{ "prepared",   DUMP_PREPARED },
84
	{ "regalloc",   DUMP_RA },
Sebastian Hack's avatar
Sebastian Hack committed
85
	{ "final",      DUMP_FINAL },
86
87
	{ "be",         DUMP_BE },
	{ "all",        2 * DUMP_BE - 1 },
Sebastian Hack's avatar
Sebastian Hack committed
88
89
90
91
	{ NULL,         0 }
};

static lc_opt_enum_mask_var_t dump_var = {
92
	&be_options.dump_flags, dump_items
93
94
};

Sebastian Hack's avatar
Sebastian Hack committed
95
static const lc_opt_table_entry_t be_main_options[] = {
96
97
98
	LC_OPT_ENT_ENUM_MASK("dump",       "dump irg on several occasions",                       &dump_var),
	LC_OPT_ENT_BOOL     ("omitfp",     "omit frame pointer",                                  &be_options.omit_fp),
	LC_OPT_ENT_BOOL     ("pic",        "create PIC code",                                     &be_options.pic),
Matthias Braun's avatar
Matthias Braun committed
99
	LC_OPT_ENT_BOOL     ("verify",     "verify the backend irg",                              &be_options.do_verify),
100
	LC_OPT_ENT_BOOL     ("time",       "get backend timing statistics",                       &be_options.timing),
101
102
	LC_OPT_ENT_BOOL     ("profilegenerate", "instrument the code for execution count profiling",   &be_options.opt_profile_generate),
	LC_OPT_ENT_BOOL     ("profileuse",      "use existing profile data",                           &be_options.opt_profile_use),
103
	LC_OPT_ENT_BOOL     ("verboseasm", "enable verbose assembler output",                     &be_options.verbose_asm),
104

105
106
	LC_OPT_ENT_STR("ilp.server", "the ilp server name", &be_options.ilp_server),
	LC_OPT_ENT_STR("ilp.solver", "the ilp solver name", &be_options.ilp_solver),
107
	LC_OPT_LAST
Sebastian Hack's avatar
Sebastian Hack committed
108
109
};

110
111
static be_module_list_entry_t *isa_ifs         = NULL;
static bool                    isa_initialized = false;
112

113
asm_constraint_flags_t asm_constraint_flags[256];
114

115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
static void be_init_default_asm_constraint_flags(void)
{
	/* list of constraints supported by gcc for any machine (or at least
	 * recognized). Mark them as NO_SUPPORT so we can differentiate them
	 * from INVALID. Backends should change the flags they support. */
	static const unsigned char gcc_common_flags[] = {
		'?', '!', '&', '%', 'i', 's', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
		'M', 'N', 'O', 'P', 'm', 'o', 'r', 'V', '<', '>', 'p', 'g', 'X',
		'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
	};
	for (size_t i = 0; i < ARRAY_SIZE(gcc_common_flags); ++i) {
		unsigned char const c = gcc_common_flags[i];
		asm_constraint_flags[c] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
	}
}

131
132
133
134
static void initialize_isa(void)
{
	if (isa_initialized)
		return;
135
	be_init_default_asm_constraint_flags();
136
	isa_if->init();
Matthias Braun's avatar
Matthias Braun committed
137
138
139
140
141
142
143
144
145
	isa_initialized = true;
}

static void finish_isa(void)
{
	if (isa_initialized) {
		isa_if->finish();
		isa_initialized = false;
	}
146
147
}

148
asm_constraint_flags_t be_parse_asm_constraints(const char *constraint)
149
{
150
151
	initialize_isa();

Matthias Braun's avatar
Matthias Braun committed
152
153
	asm_constraint_flags_t flags = ASM_CONSTRAINT_FLAG_NONE;
	for (const char *c = constraint; *c != '\0'; ++c) {
154
		switch (*c) {
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
		case ' ':
		case '\t':
		case '\n':
		case '\r':
			break;
		case '=':
			flags |= ASM_CONSTRAINT_FLAG_MODIFIER_WRITE;
			flags |= ASM_CONSTRAINT_FLAG_MODIFIER_NO_READ;
			break;
		case '+':
			flags |= ASM_CONSTRAINT_FLAG_MODIFIER_READ;
			flags |= ASM_CONSTRAINT_FLAG_MODIFIER_WRITE;
			break;
		case '&':
		case '%':
			/* not really supported by libFirm yet */
			flags |= ASM_CONSTRAINT_FLAG_NO_SUPPORT;
			break;
173
		case '#':
174
			/* text until comma is a comment */
175
			while (*c != 0 && *c != ',')
176
177
178
				++c;
			break;
		case '*':
179
			/* next character is a comment */
180
181
			++c;
			break;
Matthias Braun's avatar
Matthias Braun committed
182
183
		default: {
			asm_constraint_flags_t tflags = asm_constraint_flags[(int) *c];
184
185
186
			if (tflags != 0) {
				flags |= tflags;
			} else {
187
				flags |= ASM_CONSTRAINT_FLAG_INVALID;
188
189
190
			}
			break;
		}
Matthias Braun's avatar
Matthias Braun committed
191
		}
192
193
	}

194
	if ((
195
196
	        flags & ASM_CONSTRAINT_FLAG_MODIFIER_WRITE &&
	        flags & ASM_CONSTRAINT_FLAG_MODIFIER_NO_WRITE
197
	    ) || (
198
199
	        flags & ASM_CONSTRAINT_FLAG_MODIFIER_READ &&
	        flags & ASM_CONSTRAINT_FLAG_MODIFIER_NO_READ
200
	    )) {
201
202
		flags |= ASM_CONSTRAINT_FLAG_INVALID;
	}
203
204
205
206
207
	if (!(flags & (ASM_CONSTRAINT_FLAG_MODIFIER_READ     |
	               ASM_CONSTRAINT_FLAG_MODIFIER_WRITE    |
	               ASM_CONSTRAINT_FLAG_MODIFIER_NO_WRITE |
	               ASM_CONSTRAINT_FLAG_MODIFIER_NO_READ)
	    )) {
208
209
		flags |= ASM_CONSTRAINT_FLAG_MODIFIER_READ;
	}
210
211
212
213

	return flags;
}

214
int be_is_valid_clobber(const char *clobber)
215
{
216
217
	initialize_isa();

218
219
220
	/* memory is a valid clobber. (the frontend has to detect this case too,
	 * because it has to add memory edges to the asm) */
	if (strcmp(clobber, "memory") == 0)
221
		return 1;
222
223
	/* cc (condition code) is always valid */
	if (strcmp(clobber, "cc") == 0)
224
		return 1;
225

226
	return isa_if->is_valid_clobber(clobber);
227
228
}

229
230
void be_register_isa_if(const char *name, const arch_isa_if_t *isa)
{
231
	if (isa_if == NULL)
232
233
234
235
236
		isa_if = isa;

	be_add_module_to_list(&isa_ifs, name, (void*) isa);
}

237
static void be_opt_register(void)
Sebastian Hack's avatar
Sebastian Hack committed
238
{
Matthias Braun's avatar
Matthias Braun committed
239
	static bool run_once = false;
240
	if (run_once)
241
		return;
Matthias Braun's avatar
Matthias Braun committed
242
	run_once = true;
243

Matthias Braun's avatar
Matthias Braun committed
244
	lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
245
	lc_opt_add_table(be_grp, be_main_options);
246
247
248

	be_add_module_list_opt(be_grp, "isa", "the instruction set architecture",
	                       &isa_ifs, (void**) &isa_if);
249
250

	be_init_modules();
251
}
Sebastian Hack's avatar
Sebastian Hack committed
252

253
/* Parse one argument. */
254
255
int be_parse_arg(const char *arg)
{
256
	lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
Michael Beck's avatar
Michael Beck committed
257
	if (strcmp(arg, "help") == 0 || (arg[0] == '?' && arg[1] == '\0')) {
258
		lc_opt_print_help_for_entry(be_grp, '-', stdout);
Michael Beck's avatar
Michael Beck committed
259
260
		return -1;
	}
261
	return lc_opt_from_single_arg(be_grp, arg);
262
263
}

Christian Würdig's avatar
Christian Würdig committed
264
/* Perform schedule verification if requested. */
Matthias Braun's avatar
Matthias Braun committed
265
static void be_sched_verify(ir_graph *irg)
266
{
Matthias Braun's avatar
Matthias Braun committed
267
268
	if (be_options.do_verify) {
		be_timer_push(T_VERIFY);
269
		be_verify_schedule(irg);
Matthias Braun's avatar
Matthias Braun committed
270
		be_timer_pop(T_VERIFY);
Christian Würdig's avatar
Christian Würdig committed
271
272
273
	}
}

274
275
/* Initialize the Firm backend. Must be run first in init_firm()! */
void firm_be_init(void)
276
{
Sebastian Hack's avatar
Sebastian Hack committed
277
	be_opt_register();
278
	be_init_modules();
279
}
280

yb9976's avatar
yb9976 committed
281
282
283
/* Finalize the Firm backend. */
void firm_be_finish(void)
{
Matthias Braun's avatar
Matthias Braun committed
284
	finish_isa();
yb9976's avatar
yb9976 committed
285
286
287
	be_quit_modules();
}

288
289
290
/* Returns the backend parameter */
const backend_params *be_get_backend_param(void)
{
291
	initialize_isa();
292
	return isa_if->get_params();
293
294
}

Manuel Mohr's avatar
Manuel Mohr committed
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
320
321
322
323
324
int be_is_big_endian(void)
{
	return be_get_backend_param()->byte_order_big_endian;
}

unsigned be_get_machine_size(void)
{
	return be_get_backend_param()->machine_size;
}

ir_mode *be_get_mode_float_arithmetic(void)
{
	return be_get_backend_param()->mode_float_arithmetic;
}

ir_type *be_get_type_long_long(void)
{
	return be_get_backend_param()->type_long_long;
}

ir_type *be_get_type_unsigned_long_long(void)
{
	return be_get_backend_param()->type_unsigned_long_long;
}

ir_type *be_get_type_long_double(void)
{
	return be_get_backend_param()->type_long_double;
}

325
326
327
328
329
float_int_conversion_overflow_style_t be_get_float_int_overflow(void)
{
	return be_get_backend_param()->float_int_overflow;
}

330
331
332
333
334
335
/**
 * Initializes the main environment for the backend.
 *
 * @param env          an empty environment
 * @param file_handle  the file handle where the output will be written to
 */
Matthias Braun's avatar
Matthias Braun committed
336
337
static be_main_env_t *be_init_env(be_main_env_t *const env,
                                  char const *const compilation_unit_name)
Sebastian Hack's avatar
Sebastian Hack committed
338
{
Sebastian Hack's avatar
Sebastian Hack committed
339
	memset(env, 0, sizeof(*env));
340
	env->ent_trampoline_map   = pmap_create();
341
	env->pic_trampolines_type = new_type_segment(NEW_ID("$PIC_TRAMPOLINE_TYPE"), tf_none);
342
	env->ent_pic_symbol_map   = pmap_create();
343
	env->pic_symbols_type     = new_type_segment(NEW_ID("$PIC_SYMBOLS_TYPE"), tf_none);
344
	env->cup_name             = compilation_unit_name;
345
	env->arch_env             = isa_if->begin_codegeneration();
346

347
	memset(asm_constraint_flags, 0, sizeof(asm_constraint_flags));
Sebastian Hack's avatar
Sebastian Hack committed
348
349

	return env;
350
351
}

352
353
354
/**
 * Called when the be_main_env_t can be destroyed.
 */
Sebastian Hack's avatar
Sebastian Hack committed
355
static void be_done_env(be_main_env_t *env)
356
{
357
358
	pmap_destroy(env->ent_trampoline_map);
	pmap_destroy(env->ent_pic_symbol_map);
359
360
	free_type(env->pic_trampolines_type);
	free_type(env->pic_symbols_type);
Sebastian Hack's avatar
Sebastian Hack committed
361
}
Sebastian Hack's avatar
Sebastian Hack committed
362

Michael Beck's avatar
Michael Beck committed
363
/**
364
 * Prepare a backend graph for code generation and initialize its irg
Michael Beck's avatar
Michael Beck committed
365
 */
366
static void initialize_birg(be_irg_t *birg, ir_graph *irg, be_main_env_t *env)
Sebastian Hack's avatar
Sebastian Hack committed
367
{
368
369
370
	/* don't duplicate locals in backend when dumping... */
	ir_remove_dump_flags(ir_dump_flag_consts_local);

371
	be_dump(DUMP_INITIAL, irg, "begin");
372

373
374
375
376
377
	assure_irg_properties(irg,
		IR_GRAPH_PROPERTY_NO_BADS
		| IR_GRAPH_PROPERTY_NO_UNREACHABLE_CODE
		| IR_GRAPH_PROPERTY_NO_CRITICAL_EDGES
		| IR_GRAPH_PROPERTY_MANY_RETURNS);
yb9976's avatar
yb9976 committed
378

379
380
	memset(birg, 0, sizeof(*birg));
	birg->main_env = env;
381
	obstack_init(&birg->obst);
382
	irg->be_data = birg;
Sebastian Hack's avatar
Sebastian Hack committed
383

384
	be_info_init_irg(irg);
385
	birg->lv = be_liveness_new(irg);
386

387
	be_dump(DUMP_INITIAL, irg, "prepared");
Sebastian Hack's avatar
Sebastian Hack committed
388
389
}

Matthias Braun's avatar
Matthias Braun committed
390
int be_timing;
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420

static const char *get_timer_name(be_timer_id_t id)
{
	switch (id) {
	case T_ABI:            return "abi";
	case T_CODEGEN:        return "codegen";
	case T_RA_PREPARATION: return "ra_preparation";
	case T_SCHED:          return "sched";
	case T_CONSTR:         return "constr";
	case T_FINISH:         return "finish";
	case T_EMIT:           return "emit";
	case T_VERIFY:         return "verify";
	case T_OTHER:          return "other";
	case T_HEIGHTS:        return "heights";
	case T_LIVE:           return "live";
	case T_EXECFREQ:       return "execfreq";
	case T_SSA_CONSTR:     return "ssa_constr";
	case T_RA_EPILOG:      return "ra_epilog";
	case T_RA_CONSTR:      return "ra_constr";
	case T_RA_SPILL:       return "ra_spill";
	case T_RA_SPILL_APPLY: return "ra_spill_apply";
	case T_RA_COLOR:       return "ra_color";
	case T_RA_IFG:         return "ra_ifg";
	case T_RA_COPYMIN:     return "ra_copymin";
	case T_RA_SSA:         return "ra_ssa";
	case T_RA_OTHER:       return "ra_other";
	}
	return "unknown";
}
ir_timer_t *be_timers[T_LAST+1];
421

422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
static void dummy_after_transform(ir_graph *irg, const char *name)
{
	(void)irg;
	(void)name;
}

after_transform_func be_after_transform = dummy_after_transform;

void be_set_after_transform_func(after_transform_func after_transform)
{
	be_after_transform = after_transform;
}

void be_after_irp_transform(const char *name)
{
	if (be_after_transform == NULL)
		return;

440
	foreach_irp_irg_r(i, irg) {
441
442
443
444
		be_after_transform(irg, name);
	}
}

445
446
void be_lower_for_target(void)
{
447
448
	initialize_isa();

449
450
	isa_if->lower_for_target();
	/* set the phase to low */
451
	foreach_irp_irg_r(i, irg) {
452
453
		assert(!irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_TARGET_LOWERED));
		add_irg_constraints(irg, IR_GRAPH_CONSTRAINT_TARGET_LOWERED);
454
455
456
	}
}

Michael Beck's avatar
Michael Beck committed
457
458
459
460
/**
 * The Firm backend main loop.
 * Do architecture specific lowering for all graphs
 * and call the architecture specific code generator.
461
462
 *
 * @param file_handle   the file handle the output will be written to
463
 * @param cup_name      name of the compilation unit
Michael Beck's avatar
Michael Beck committed
464
 */
465
static void be_main_loop(FILE *file_handle, const char *cup_name)
466
{
Matthias Braun's avatar
Matthias Braun committed
467
468
	be_timing = (be_options.timing == BE_TIME_ON);

469
	/* perform target lowering if it didn't happen yet */
470
	if (get_irp_n_irgs() > 0 && !irg_is_constrained(get_irp_irg(0), IR_GRAPH_CONSTRAINT_TARGET_LOWERED))
471
472
		be_lower_for_target();

Matthias Braun's avatar
Matthias Braun committed
473
	if (be_timing) {
Matthias Braun's avatar
Matthias Braun committed
474
		for (size_t i = 0; i < T_LAST+1; ++i) {
475
476
			be_timers[i] = ir_timer_new();
		}
477
	}
478

479
480
	be_emit_init(file_handle);

Matthias Braun's avatar
Matthias Braun committed
481
	be_main_env_t env;
482
	be_init_env(&env, cup_name);
Matthias Braun's avatar
Matthias Braun committed
483
	be_info_init();
Matthias Braun's avatar
Matthias Braun committed
484
	arch_env_t *arch_env = env.arch_env;
485
486

	be_gas_begin_compilation_unit(&env);
487

Christian Würdig's avatar
Christian Würdig committed
488
	/* First: initialize all birgs */
489
	size_t          num_birgs = 0;
Matthias Braun's avatar
Matthias Braun committed
490
	/* we might need 1 birg more for instrumentation constructor */
491
492
	be_irg_t *const birgs     = ALLOCAN(be_irg_t, get_irp_n_irgs() + 1);
	foreach_irp_irg(i, irg) {
493
494
495
496
		ir_entity *entity = get_irg_entity(irg);
		if (get_entity_linkage(entity) & IR_LINKAGE_NO_CODEGEN)
			continue;
		initialize_birg(&birgs[num_birgs++], irg, &env);
Matthias Braun's avatar
Matthias Braun committed
497
498
		if (arch_env->impl->handle_intrinsics)
			arch_env->impl->handle_intrinsics(irg);
499
	}
Michael Beck's avatar
Michael Beck committed
500

Christian Würdig's avatar
Christian Würdig committed
501
502
503
504
	/*
		Get the filename for the profiling data.
		Beware: '\0' is already included in sizeof(suffix)
	*/
Matthias Braun's avatar
Matthias Braun committed
505
506
	static const char suffix[] = ".prof";
	char prof_filename[256];
507
508
509
	sprintf(prof_filename, "%.*s%s",
	        (int)(sizeof(prof_filename) - sizeof(suffix)), cup_name, suffix);

510
	bool have_profile = false;
511
512
513
514
515
	if (be_options.opt_profile_use) {
		bool res = ir_profile_read(prof_filename);
		if (!res) {
			fprintf(stderr, "Warning: Couldn't read profile data '%s'\n",
			        prof_filename);
516
517
518
519
		} else {
			ir_create_execfreqs_from_profile();
			ir_profile_free();
			have_profile = true;
520
521
		}
	}
522

523
	if (num_birgs > 0 && be_options.opt_profile_generate) {
524
		ir_graph *const prof_init_irg = ir_profile_instrument(prof_filename);
525
		assert(prof_init_irg->be_data == NULL);
526
		initialize_birg(&birgs[num_birgs++], prof_init_irg, &env);
527
528
	}

Matthias Braun's avatar
Matthias Braun committed
529
530
531
	for (be_timer_id_t t = T_FIRST; t < T_LAST+1; ++t) {
		ir_timer_init_parent(be_timers[t]);
	}
532
533
	if (!have_profile) {
		be_timer_push(T_EXECFREQ);
534
		foreach_irp_irg(i, irg) {
535
536
537
			ir_estimate_execfreq(irg);
		}
		be_timer_pop(T_EXECFREQ);
538
	}
Adam Szalkowski's avatar
Adam Szalkowski committed
539

540
	/* For all graphs */
541
	foreach_irp_irg(i, irg) {
542
543
544
		ir_entity *const entity = get_irg_entity(irg);
		if (get_entity_linkage(entity) & IR_LINKAGE_NO_CODEGEN)
			continue;
Sebastian Hack's avatar
Sebastian Hack committed
545

546
		if (stat_ev_enabled) {
Matthias Braun's avatar
Matthias Braun committed
547
548
549
			stat_ev_ctx_push_fmt("bemain_irg", "%+F", irg);
			stat_ev_ull("bemain_insns_start", be_count_insns(irg));
			stat_ev_ull("bemain_blocks_start", be_count_blocks(irg));
Matthias Braun's avatar
Matthias Braun committed
550
		}
551

552
		/* stop and reset timers */
553
		be_timer_push(T_OTHER);
554

555
		/* Verify the initial graph */
Matthias Braun's avatar
Matthias Braun committed
556
557
		if (be_options.do_verify) {
			be_timer_push(T_VERIFY);
Matthias Braun's avatar
Matthias Braun committed
558
			irg_assert_verify(irg);
Matthias Braun's avatar
Matthias Braun committed
559
			be_timer_pop(T_VERIFY);
560
561
		}

562
		/* prepare and perform codeselection */
563
564
		if (arch_env->impl->prepare_graph != NULL)
			arch_env->impl->prepare_graph(irg);
565

Christian Würdig's avatar
Christian Würdig committed
566
		/* schedule the irg */
567
		be_timer_push(T_SCHED);
568
		be_schedule_graph(irg);
569
		be_timer_pop(T_SCHED);
Sebastian Hack's avatar
Sebastian Hack committed
570

571
		be_dump(DUMP_SCHED, irg, "sched");
Christian Würdig's avatar
Christian Würdig committed
572

Christian Würdig's avatar
Christian Würdig committed
573
		/* check schedule */
Matthias Braun's avatar
Matthias Braun committed
574
		be_sched_verify(irg);
575

Christian Würdig's avatar
Christian Würdig committed
576
		/* introduce patterns to assure constraints */
577
		be_timer_push(T_CONSTR);
578
		/* we switch off optimizations here, because they might cause trouble */
579
		optimization_state_t state;
580
		save_optimization_state(&state);
581
		set_optimize(0);
582
583
		set_opt_cse(0);

584
585
		/* add Keeps for should_be_different constrained nodes  */
		/* beware: needs schedule due to usage of be_ssa_constr */
586
		assure_constraints(irg);
587
		be_timer_pop(T_CONSTR);
588

589
		be_dump(DUMP_SCHED, irg, "assured");
Christian Würdig's avatar
Christian Würdig committed
590

591
		/* stuff needs to be done after scheduling but before register allocation */
592
		be_timer_push(T_RA_PREPARATION);
593
594
		if (arch_env->impl->before_ra != NULL)
			arch_env->impl->before_ra(irg);
595
		be_timer_pop(T_RA_PREPARATION);
596

Sebastian Hack's avatar
Sebastian Hack committed
597
		/* connect all stack modifying nodes together (see beabi.c) */
598
		be_timer_push(T_ABI);
599
		be_abi_fix_stack_nodes(irg);
600
		be_timer_pop(T_ABI);
Christian Würdig's avatar
Christian Würdig committed
601

602
		be_dump(DUMP_SCHED, irg, "fix_stack");
Sebastian Hack's avatar
Sebastian Hack committed
603

Christian Würdig's avatar
Christian Würdig committed
604
		/* check schedule */
Matthias Braun's avatar
Matthias Braun committed
605
		be_sched_verify(irg);
Sebastian Hack's avatar
Sebastian Hack committed
606

607
		if (stat_ev_enabled) {
608
			stat_ev_dbl("bemain_costs_before_ra", be_estimate_irg_costs(irg));
Matthias Braun's avatar
Matthias Braun committed
609
610
			stat_ev_ull("bemain_insns_before_ra", be_count_insns(irg));
			stat_ev_ull("bemain_blocks_before_ra", be_count_blocks(irg));
Matthias Braun's avatar
Matthias Braun committed
611
		}
612

613
614
615
616
617
618
619
		/* add missing copies to make hidden register pressure increases
		 * explicit */
		be_timer_push(T_RA_CONSTR);
		be_add_missing_copies(irg);
		be_timer_pop(T_RA_CONSTR);
		be_dump(DUMP_RA, irg, "spillprepare");

620
		/* Do register allocation */
621
		be_allocate_registers(irg);
622

Matthias Braun's avatar
Matthias Braun committed
623
624
		if (be_options.do_verify) {
			be_timer_push(T_VERIFY);
625
			be_verify_register_allocation(irg, true);
Matthias Braun's avatar
Matthias Braun committed
626
627
628
			be_timer_pop(T_VERIFY);
		}

629
630
631
632
633
		if (stat_ev_enabled) {
			stat_ev_dbl("bemain_costs_after_ra", be_estimate_irg_costs(irg));
			stat_ev_ull("bemain_insns_after_ra", be_count_insns(irg));
			stat_ev_ull("bemain_blocks_after_ra", be_count_blocks(irg));
		}
634

635
		be_dump(DUMP_RA, irg, "ra");
Christian Würdig's avatar
Christian Würdig committed
636

Christian Würdig's avatar
Christian Würdig committed
637
		/* emit assembler code */
638
		be_timer_push(T_EMIT);
639
640
		if (arch_env->impl->emit != NULL)
			arch_env->impl->emit(irg);
641
		be_timer_pop(T_EMIT);
Christian Würdig's avatar
Christian Würdig committed
642

643
644
645
646
647
648
		if (stat_ev_enabled) {
			stat_ev_ull("bemain_insns_finish", be_count_insns(irg));
			stat_ev_ull("bemain_blocks_finish", be_count_blocks(irg));
		}

		be_dump(DUMP_FINAL, irg, "final");
Christian Würdig's avatar
Christian Würdig committed
649

650
		restore_optimization_state(&state);
651

652
653
654
655
		be_timer_pop(T_OTHER);

		if (be_timing) {
			if (stat_ev_enabled) {
Matthias Braun's avatar
Matthias Braun committed
656
				for (be_timer_id_t t = T_FIRST; t < T_LAST+1; ++t) {
657
658
659
					char buf[128];
					snprintf(buf, sizeof(buf), "bemain_time_%s",
					         get_timer_name(t));
Manuel Mohr's avatar
Manuel Mohr committed
660
					stat_ev_dbl(buf, ir_timer_elapsed_usec(be_timers[t]));
661
				}
Matthias Braun's avatar
Matthias Braun committed
662
			} else {
663
664
				printf("==>> IRG %s <<==\n",
				       get_entity_name(get_irg_entity(irg)));
Matthias Braun's avatar
Matthias Braun committed
665
				for (be_timer_id_t t = T_FIRST; t < T_LAST+1; ++t) {
666
					double val = ir_timer_elapsed_usec(be_timers[t]) / 1000.0;
667
					printf("%-20s: %10.3f msec\n", get_timer_name(t), val);
668
				}
669
			}
Matthias Braun's avatar
Matthias Braun committed
670
			for (be_timer_id_t t = T_FIRST; t < T_LAST+1; ++t) {
671
672
673
				ir_timer_reset(be_timers[t]);
			}
		}
Michael Beck's avatar
BugFix:    
Michael Beck committed
674

675
		be_free_birg(irg);
Sebastian Hack's avatar
Sebastian Hack committed
676
		stat_ev_ctx_pop("bemain_irg");
677
	}
678

679
680
681
	be_gas_end_compilation_unit(&env);
	be_emit_exit();

682
	arch_env_end_codegeneration(arch_env);
683

Sebastian Hack's avatar
Sebastian Hack committed
684
	be_done_env(&env);
685
686

	be_info_free();
687
688
}

Michael Beck's avatar
Michael Beck committed
689
/* Main interface to the frontend. */
690
void be_main(FILE *file_handle, const char *cup_name)
691
{
Matthias Braun's avatar
Matthias Braun committed
692
	ir_timer_t *t = NULL;
693

694
	if (be_options.timing == BE_TIME_ON) {
695
		t = ir_timer_new();
696

Matthias Braun's avatar
Matthias Braun committed
697
		if (ir_timer_enter_high_priority()) {
698
699
700
			fprintf(stderr, "Warning: Could not enter high priority mode.\n");
		}

Matthias Braun's avatar
Matthias Braun committed
701
		ir_timer_reset_and_start(t);
702
	}
703

704
	if (stat_ev_enabled) {
705
		const char *dot = strrchr(cup_name, '.');
Sebastian Hack's avatar
Sebastian Hack committed
706
		const char *pos = dot ? dot : cup_name + strlen(cup_name);
707
		char       *buf = ALLOCAN(char, pos - cup_name + 1);
Sebastian Hack's avatar
Sebastian Hack committed
708
		strncpy(buf, cup_name, pos - cup_name);
Sebastian Hack's avatar
Sebastian Hack committed
709
		buf[pos - cup_name] = '\0';
Sebastian Hack's avatar
Sebastian Hack committed
710

711
		stat_ev_ctx_push_str("bemain_compilation_unit", cup_name);
Sebastian Hack's avatar
Sebastian Hack committed
712
	}
713

714
	be_main_loop(file_handle, cup_name);
715
716

	if (be_options.timing == BE_TIME_ON) {
Matthias Braun's avatar
Matthias Braun committed
717
718
		ir_timer_stop(t);
		ir_timer_leave_high_priority();
719
		if (stat_ev_enabled) {
720
			stat_ev_dbl("bemain_backend_time", ir_timer_elapsed_msec(t));
721
		} else {
722
			double val = ir_timer_elapsed_usec(t) / 1000.0;
723
			printf("%-20s: %10.3f msec\n", "BEMAINLOOP", val);
724
		}
725
	}
726

727
	if (stat_ev_enabled) {
728
729
		stat_ev_ctx_pop("bemain_compilation_unit");
	}
730
}