bemain.c 20.7 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
 */
Sebastian Hack's avatar
Sebastian Hack committed
12
#include <stdarg.h>
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 */
69
	BE_VERIFY_WARN,                    /* verification level: warn */
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
	{ "initial",    DUMP_INITIAL },
82
	{ "abi",        DUMP_ABI    },
Sebastian Hack's avatar
Sebastian Hack committed
83
84
	{ "sched",      DUMP_SCHED  },
	{ "prepared",   DUMP_PREPARED },
85
	{ "regalloc",   DUMP_RA },
Sebastian Hack's avatar
Sebastian Hack committed
86
	{ "final",      DUMP_FINAL },
87
88
	{ "be",         DUMP_BE },
	{ "all",        2 * DUMP_BE - 1 },
Sebastian Hack's avatar
Sebastian Hack committed
89
90
91
	{ NULL,         0 }
};

Christian Würdig's avatar
Christian Würdig committed
92
/* verify options. */
93
94
95
96
static const lc_opt_enum_int_items_t verify_items[] = {
	{ "off",    BE_VERIFY_OFF    },
	{ "warn",   BE_VERIFY_WARN   },
	{ "assert", BE_VERIFY_ASSERT },
Christian Würdig's avatar
Christian Würdig committed
97
	{ NULL,     0 }
Christian Würdig's avatar
Christian Würdig committed
98
};
99

Sebastian Hack's avatar
Sebastian Hack committed
100
static lc_opt_enum_mask_var_t dump_var = {
101
	&be_options.dump_flags, dump_items
102
103
};

104
105
static lc_opt_enum_int_var_t verify_var = {
	&be_options.verify_option, verify_items
Christian Würdig's avatar
Christian Würdig committed
106
107
};

Sebastian Hack's avatar
Sebastian Hack committed
108
static const lc_opt_table_entry_t be_main_options[] = {
109
110
111
	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),
112
	LC_OPT_ENT_ENUM_INT ("verify",     "verify the backend irg",                              &verify_var),
113
	LC_OPT_ENT_BOOL     ("time",       "get backend timing statistics",                       &be_options.timing),
114
115
	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),
116
	LC_OPT_ENT_BOOL     ("verboseasm", "enable verbose assembler output",                     &be_options.verbose_asm),
117

118
119
	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),
120
	LC_OPT_LAST
Sebastian Hack's avatar
Sebastian Hack committed
121
122
};

123
124
static be_module_list_entry_t *isa_ifs         = NULL;
static bool                    isa_initialized = false;
125

126
asm_constraint_flags_t asm_constraint_flags[256];
127

128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
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;
	}
}

144
145
146
147
static void initialize_isa(void)
{
	if (isa_initialized)
		return;
148
	be_init_default_asm_constraint_flags();
149
	isa_if->init();
Matthias Braun's avatar
Matthias Braun committed
150
151
152
153
154
155
156
157
158
	isa_initialized = true;
}

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

161
asm_constraint_flags_t be_parse_asm_constraints(const char *constraint)
162
{
163
164
	initialize_isa();

Matthias Braun's avatar
Matthias Braun committed
165
166
	asm_constraint_flags_t flags = ASM_CONSTRAINT_FLAG_NONE;
	for (const char *c = constraint; *c != '\0'; ++c) {
167
		switch (*c) {
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
		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;
186
		case '#':
187
			/* text until comma is a comment */
188
			while (*c != 0 && *c != ',')
189
190
191
				++c;
			break;
		case '*':
192
			/* next character is a comment */
193
194
			++c;
			break;
Matthias Braun's avatar
Matthias Braun committed
195
196
		default: {
			asm_constraint_flags_t tflags = asm_constraint_flags[(int) *c];
197
198
199
			if (tflags != 0) {
				flags |= tflags;
			} else {
200
				flags |= ASM_CONSTRAINT_FLAG_INVALID;
201
202
203
			}
			break;
		}
Matthias Braun's avatar
Matthias Braun committed
204
		}
205
206
	}

207
	if ((
208
209
	        flags & ASM_CONSTRAINT_FLAG_MODIFIER_WRITE &&
	        flags & ASM_CONSTRAINT_FLAG_MODIFIER_NO_WRITE
210
	    ) || (
211
212
	        flags & ASM_CONSTRAINT_FLAG_MODIFIER_READ &&
	        flags & ASM_CONSTRAINT_FLAG_MODIFIER_NO_READ
213
	    )) {
214
215
		flags |= ASM_CONSTRAINT_FLAG_INVALID;
	}
216
217
218
219
220
	if (!(flags & (ASM_CONSTRAINT_FLAG_MODIFIER_READ     |
	               ASM_CONSTRAINT_FLAG_MODIFIER_WRITE    |
	               ASM_CONSTRAINT_FLAG_MODIFIER_NO_WRITE |
	               ASM_CONSTRAINT_FLAG_MODIFIER_NO_READ)
	    )) {
221
222
		flags |= ASM_CONSTRAINT_FLAG_MODIFIER_READ;
	}
223
224
225
226

	return flags;
}

227
int be_is_valid_clobber(const char *clobber)
228
{
229
230
	initialize_isa();

231
232
233
	/* 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)
234
		return 1;
235
236
	/* cc (condition code) is always valid */
	if (strcmp(clobber, "cc") == 0)
237
		return 1;
238

239
	return isa_if->is_valid_clobber(clobber);
240
241
}

242
243
void be_register_isa_if(const char *name, const arch_isa_if_t *isa)
{
244
	if (isa_if == NULL)
245
246
247
248
249
		isa_if = isa;

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

250
static void be_opt_register(void)
Sebastian Hack's avatar
Sebastian Hack committed
251
{
Matthias Braun's avatar
Matthias Braun committed
252
	static bool run_once = false;
253
	if (run_once)
254
		return;
Matthias Braun's avatar
Matthias Braun committed
255
	run_once = true;
256

Matthias Braun's avatar
Matthias Braun committed
257
	lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
258
	lc_opt_add_table(be_grp, be_main_options);
259
260
261

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

	be_init_modules();
264
}
Sebastian Hack's avatar
Sebastian Hack committed
265

266
/* Parse one argument. */
267
268
int be_parse_arg(const char *arg)
{
269
	lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
Michael Beck's avatar
Michael Beck committed
270
	if (strcmp(arg, "help") == 0 || (arg[0] == '?' && arg[1] == '\0')) {
271
		lc_opt_print_help_for_entry(be_grp, '-', stdout);
Michael Beck's avatar
Michael Beck committed
272
273
		return -1;
	}
274
	return lc_opt_from_single_arg(be_grp, arg);
275
276
}

Christian Würdig's avatar
Christian Würdig committed
277
/* Perform schedule verification if requested. */
278
static void be_sched_verify(ir_graph *irg, int verify_opt)
279
{
280
	if (verify_opt == BE_VERIFY_WARN) {
281
		be_verify_schedule(irg);
282
	} else if (verify_opt == BE_VERIFY_ASSERT) {
283
		assert(be_verify_schedule(irg) && "Schedule verification failed.");
Christian Würdig's avatar
Christian Würdig committed
284
285
286
	}
}

287
288
/* Initialize the Firm backend. Must be run first in init_firm()! */
void firm_be_init(void)
289
{
Sebastian Hack's avatar
Sebastian Hack committed
290
	be_opt_register();
291
	be_init_modules();
292
}
293

yb9976's avatar
yb9976 committed
294
295
296
/* Finalize the Firm backend. */
void firm_be_finish(void)
{
Matthias Braun's avatar
Matthias Braun committed
297
	finish_isa();
yb9976's avatar
yb9976 committed
298
299
300
	be_quit_modules();
}

301
302
303
/* Returns the backend parameter */
const backend_params *be_get_backend_param(void)
{
304
	initialize_isa();
305
	return isa_if->get_params();
306
307
}

Manuel Mohr's avatar
Manuel Mohr committed
308
309
310
311
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
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;
}

338
339
340
341
342
343
/**
 * 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
344
345
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
346
{
Sebastian Hack's avatar
Sebastian Hack committed
347
	memset(env, 0, sizeof(*env));
348
	env->ent_trampoline_map   = pmap_create();
349
	env->pic_trampolines_type = new_type_segment(NEW_ID("$PIC_TRAMPOLINE_TYPE"), tf_none);
350
	env->ent_pic_symbol_map   = pmap_create();
351
	env->pic_symbols_type     = new_type_segment(NEW_ID("$PIC_SYMBOLS_TYPE"), tf_none);
352
	env->cup_name             = compilation_unit_name;
353
	env->arch_env             = isa_if->begin_codegeneration();
354
355

	set_class_final(env->pic_trampolines_type, 1);
Sebastian Hack's avatar
Sebastian Hack committed
356

357
	memset(asm_constraint_flags, 0, sizeof(asm_constraint_flags));
Sebastian Hack's avatar
Sebastian Hack committed
358
359

	return env;
360
361
}

362
363
364
/**
 * Called when the be_main_env_t can be destroyed.
 */
Sebastian Hack's avatar
Sebastian Hack committed
365
static void be_done_env(be_main_env_t *env)
366
{
367
368
	pmap_destroy(env->ent_trampoline_map);
	pmap_destroy(env->ent_pic_symbol_map);
369
370
	free_type(env->pic_trampolines_type);
	free_type(env->pic_symbols_type);
Sebastian Hack's avatar
Sebastian Hack committed
371
}
Sebastian Hack's avatar
Sebastian Hack committed
372

373
374
375
376
377
378
379
380
381
/**
 * A wrapper around a firm dumper. Dumps only, if
 * flags are enabled.
 *
 * @param mask    a bitmask containing the reason what will be dumped
 * @param irg     the IR graph to dump
 * @param suffix  the suffix for the dumper
 * @param dumper  the dumper to be called
 */
382
static void dump(int mask, ir_graph *irg, const char *suffix)
Sebastian Hack's avatar
Sebastian Hack committed
383
{
384
	if (be_options.dump_flags & mask)
385
		dump_ir_graph(irg, suffix);
Sebastian Hack's avatar
Sebastian Hack committed
386
}
387

Michael Beck's avatar
Michael Beck committed
388
/**
389
 * Prepare a backend graph for code generation and initialize its irg
Michael Beck's avatar
Michael Beck committed
390
 */
391
static void initialize_birg(be_irg_t *birg, ir_graph *irg, be_main_env_t *env)
Sebastian Hack's avatar
Sebastian Hack committed
392
{
393
394
395
	/* don't duplicate locals in backend when dumping... */
	ir_remove_dump_flags(ir_dump_flag_consts_local);

396
397
	dump(DUMP_INITIAL, irg, "begin");

398
399
400
401
402
	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
403

404
405
	memset(birg, 0, sizeof(*birg));
	birg->main_env = env;
406
	obstack_init(&birg->obst);
407
	irg->be_data = birg;
Sebastian Hack's avatar
Sebastian Hack committed
408

409
	be_info_init_irg(irg);
410
	birg->lv = be_liveness_new(irg);
411

412
	dump(DUMP_INITIAL, irg, "prepared");
Sebastian Hack's avatar
Sebastian Hack committed
413
414
}

Matthias Braun's avatar
Matthias Braun committed
415
int be_timing;
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445

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];
446

447
448
void be_lower_for_target(void)
{
449
450
	initialize_isa();

451
452
	isa_if->lower_for_target();
	/* set the phase to low */
Matthias Braun's avatar
Matthias Braun committed
453
454
	for (size_t i = get_irp_n_irgs(); i-- > 0;) {
		ir_graph *irg = get_irp_irg(i);
455
456
		assert(!irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_TARGET_LOWERED));
		add_irg_constraints(irg, IR_GRAPH_CONSTRAINT_TARGET_LOWERED);
457
458
459
	}
}

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

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

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

Matthias Braun's avatar
Matthias Braun committed
482
	be_main_env_t env;
483
484
485
486
	be_init_env(&env, cup_name);

	be_emit_init(file_handle);
	be_gas_begin_compilation_unit(&env);
487

Christian Würdig's avatar
Christian Würdig committed
488
	/* we might need 1 birg more for instrumentation constructor */
Matthias Braun's avatar
Matthias Braun committed
489
490
	size_t    num_irgs = get_irp_n_irgs();
	be_irg_t *birgs    = ALLOCAN(be_irg_t, num_irgs + 1);
491

492
493
	be_info_init();

Christian Würdig's avatar
Christian Würdig committed
494
	/* First: initialize all birgs */
Matthias Braun's avatar
Matthias Braun committed
495
496
	size_t num_birgs = 0;
	for (size_t i = 0; i < num_irgs; ++i) {
497
498
499
500
501
		ir_graph  *irg    = get_irp_irg(i);
		ir_entity *entity = get_irg_entity(irg);
		if (get_entity_linkage(entity) & IR_LINKAGE_NO_CODEGEN)
			continue;
		initialize_birg(&birgs[num_birgs++], irg, &env);
502
	}
Matthias Braun's avatar
Matthias Braun committed
503
	arch_env_t *arch_env = env.arch_env;
504
	arch_env_handle_intrinsics(arch_env);
Michael Beck's avatar
Michael Beck committed
505

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

515
	bool have_profile = false;
516
517
518
519
520
	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);
521
522
523
524
		} else {
			ir_create_execfreqs_from_profile();
			ir_profile_free();
			have_profile = true;
525
526
		}
	}
527

528
	if (num_birgs > 0 && be_options.opt_profile_generate) {
529
		ir_graph *const prof_init_irg = ir_profile_instrument(prof_filename);
530
		assert(prof_init_irg->be_data == NULL);
531
532
		initialize_birg(&birgs[num_birgs], prof_init_irg, &env);
		num_birgs++;
533
534
535
536
		num_irgs++;
		assert(num_irgs == get_irp_n_irgs());
	}

Matthias Braun's avatar
Matthias Braun committed
537
538
539
	for (be_timer_id_t t = T_FIRST; t < T_LAST+1; ++t) {
		ir_timer_init_parent(be_timers[t]);
	}
540
541
	if (!have_profile) {
		be_timer_push(T_EXECFREQ);
Matthias Braun's avatar
Matthias Braun committed
542
		for (size_t i = 0; i < num_irgs; ++i) {
543
544
545
546
			ir_graph *irg = get_irp_irg(i);
			ir_estimate_execfreq(irg);
		}
		be_timer_pop(T_EXECFREQ);
547
	}
Adam Szalkowski's avatar
Adam Szalkowski committed
548

549
	/* For all graphs */
Matthias Braun's avatar
Matthias Braun committed
550
	for (size_t i = 0; i < num_irgs; ++i) {
551
552
553
554
		ir_graph  *const irg    = get_irp_irg(i);
		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
555

556
		if (stat_ev_enabled) {
Matthias Braun's avatar
Matthias Braun committed
557
558
559
			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
560
		}
561

562
		/* stop and reset timers */
563
		be_timer_push(T_OTHER);
564

565
		/* Verify the initial graph */
566
		be_timer_push(T_VERIFY);
567
568
569
570
		if (be_options.verify_option == BE_VERIFY_WARN) {
			irg_verify(irg, VERIFY_ENFORCE_SSA);
		} else if (be_options.verify_option == BE_VERIFY_ASSERT) {
			assert(irg_verify(irg, VERIFY_ENFORCE_SSA) && "irg verification failed");
571
		}
572
		be_timer_pop(T_VERIFY);
573

574
		/* get a code generator for this graph. */
575
576
		if (arch_env->impl->init_graph)
			arch_env->impl->init_graph(irg);
577

578
		dump(DUMP_PREPARED, irg, "before-code-selection");
579

580
		/* perform codeselection */
581
		be_timer_push(T_CODEGEN);
582
583
		if (arch_env->impl->prepare_graph != NULL)
			arch_env->impl->prepare_graph(irg);
584
		be_timer_pop(T_CODEGEN);
Sebastian Hack's avatar
Sebastian Hack committed
585

586
587
		dump(DUMP_PREPARED, irg, "code-selection");

588
		/* disabled for now, fails for EmptyFor.c and XXEndless.c */
589
		/* be_live_chk_compare(irg); */
590

Christian Würdig's avatar
Christian Würdig committed
591
		/* schedule the irg */
592
		be_timer_push(T_SCHED);
593
		be_schedule_graph(irg);
594
		be_timer_pop(T_SCHED);
Sebastian Hack's avatar
Sebastian Hack committed
595

596
		dump(DUMP_SCHED, irg, "sched");
Christian Würdig's avatar
Christian Würdig committed
597

Christian Würdig's avatar
Christian Würdig committed
598
		/* check schedule */
599
		be_timer_push(T_VERIFY);
600
		be_sched_verify(irg, be_options.verify_option);
601
		be_timer_pop(T_VERIFY);
602

Christian Würdig's avatar
Christian Würdig committed
603
		/* introduce patterns to assure constraints */
604
		be_timer_push(T_CONSTR);
605
		/* we switch off optimizations here, because they might cause trouble */
606
		optimization_state_t state;
607
		save_optimization_state(&state);
608
		set_optimize(0);
609
610
		set_opt_cse(0);

611
612
		/* add Keeps for should_be_different constrained nodes  */
		/* beware: needs schedule due to usage of be_ssa_constr */
613
		assure_constraints(irg);
614
		be_timer_pop(T_CONSTR);
615

616
		dump(DUMP_SCHED, irg, "assured");
Christian Würdig's avatar
Christian Würdig committed
617

618
		/* stuff needs to be done after scheduling but before register allocation */
619
		be_timer_push(T_RA_PREPARATION);
620
621
		if (arch_env->impl->before_ra != NULL)
			arch_env->impl->before_ra(irg);
622
		be_timer_pop(T_RA_PREPARATION);
623

Sebastian Hack's avatar
Sebastian Hack committed
624
		/* connect all stack modifying nodes together (see beabi.c) */
625
		be_timer_push(T_ABI);
626
		be_abi_fix_stack_nodes(irg);
627
		be_timer_pop(T_ABI);
Christian Würdig's avatar
Christian Würdig committed
628

629
		dump(DUMP_SCHED, irg, "fix_stack");
Sebastian Hack's avatar
Sebastian Hack committed
630

Christian Würdig's avatar
Christian Würdig committed
631
		/* check schedule */
632
		be_timer_push(T_VERIFY);
633
		be_sched_verify(irg, be_options.verify_option);
634
		be_timer_pop(T_VERIFY);
Sebastian Hack's avatar
Sebastian Hack committed
635

636
		if (stat_ev_enabled) {
637
			stat_ev_dbl("bemain_costs_before_ra", be_estimate_irg_costs(irg));
Matthias Braun's avatar
Matthias Braun committed
638
639
			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
640
		}
641

642
		/* Do register allocation */
643
		be_allocate_registers(irg);
644

645
		stat_ev_dbl("bemain_costs_before_ra", be_estimate_irg_costs(irg));
646

647
		dump(DUMP_RA, irg, "ra");
Christian Würdig's avatar
Christian Würdig committed
648

649
		be_timer_push(T_FINISH);
Matthias Braun's avatar
Matthias Braun committed
650
651
		if (arch_env->impl->finish_graph != NULL)
			arch_env->impl->finish_graph(irg);
652
		be_timer_pop(T_FINISH);
653

654
		dump(DUMP_FINAL, irg, "finish");
655

656
		if (stat_ev_enabled) {
Matthias Braun's avatar
Matthias Braun committed
657
658
			stat_ev_ull("bemain_insns_finish", be_count_insns(irg));
			stat_ev_ull("bemain_blocks_finish", be_count_blocks(irg));
Matthias Braun's avatar
Matthias Braun committed
659
660
		}

661
		/* check schedule and register allocation */
662
		be_timer_push(T_VERIFY);
663
664
		if (be_options.verify_option == BE_VERIFY_WARN) {
			irg_verify(irg, VERIFY_ENFORCE_SSA);
665
666
			be_verify_schedule(irg);
			be_verify_register_allocation(irg);
667
668
		} else if (be_options.verify_option == BE_VERIFY_ASSERT) {
			assert(irg_verify(irg, VERIFY_ENFORCE_SSA) && "irg verification failed");
669
670
			assert(be_verify_schedule(irg) && "Schedule verification failed");
			assert(be_verify_register_allocation(irg)
671
			       && "register allocation verification failed");
672

673
		}
674
		be_timer_pop(T_VERIFY);
675

Christian Würdig's avatar
Christian Würdig committed
676
		/* emit assembler code */
677
		be_timer_push(T_EMIT);
678
679
		if (arch_env->impl->emit != NULL)
			arch_env->impl->emit(irg);
680
		be_timer_pop(T_EMIT);
Christian Würdig's avatar
Christian Würdig committed
681

682
		dump(DUMP_FINAL, irg, "end");
Christian Würdig's avatar
Christian Würdig committed
683

684
		restore_optimization_state(&state);
685

686
687
688
689
		be_timer_pop(T_OTHER);

		if (be_timing) {
			if (stat_ev_enabled) {
Matthias Braun's avatar
Matthias Braun committed
690
				for (be_timer_id_t t = T_FIRST; t < T_LAST+1; ++t) {
691
692
693
					char buf[128];
					snprintf(buf, sizeof(buf), "bemain_time_%s",
					         get_timer_name(t));
Manuel Mohr's avatar
Manuel Mohr committed
694
					stat_ev_dbl(buf, ir_timer_elapsed_usec(be_timers[t]));
695
				}
Matthias Braun's avatar
Matthias Braun committed
696
			} else {
697
698
				printf("==>> IRG %s <<==\n",
				       get_entity_name(get_irg_entity(irg)));
Matthias Braun's avatar
Matthias Braun committed
699
				for (be_timer_id_t t = T_FIRST; t < T_LAST+1; ++t) {
700
					double val = ir_timer_elapsed_usec(be_timers[t]) / 1000.0;
701
					printf("%-20s: %10.3f msec\n", get_timer_name(t), val);
702
				}
703
			}
Matthias Braun's avatar
Matthias Braun committed
704
			for (be_timer_id_t t = T_FIRST; t < T_LAST+1; ++t) {
705
706
707
				ir_timer_reset(be_timers[t]);
			}
		}
Michael Beck's avatar
BugFix:    
Michael Beck committed
708

709
		be_free_birg(irg);
Sebastian Hack's avatar
Sebastian Hack committed
710
		stat_ev_ctx_pop("bemain_irg");
711
	}
712

713
714
715
	be_gas_end_compilation_unit(&env);
	be_emit_exit();

716
	arch_env_end_codegeneration(arch_env);
717

Sebastian Hack's avatar
Sebastian Hack committed
718
	be_done_env(&env);
719
720

	be_info_free();
721
722
}

Michael Beck's avatar
Michael Beck committed
723
/* Main interface to the frontend. */
724
void be_main(FILE *file_handle, const char *cup_name)
725
{
Matthias Braun's avatar
Matthias Braun committed
726
	ir_timer_t *t = NULL;
727

728
	if (be_options.timing == BE_TIME_ON) {
729
		t = ir_timer_new();
730

Matthias Braun's avatar
Matthias Braun committed
731
		if (ir_timer_enter_high_priority()) {
732
733
734
			fprintf(stderr, "Warning: Could not enter high priority mode.\n");
		}

Matthias Braun's avatar
Matthias Braun committed
735
		ir_timer_reset_and_start(t);
736
	}
737

738
	if (stat_ev_enabled) {
739
		const char *dot = strrchr(cup_name, '.');
Sebastian Hack's avatar
Sebastian Hack committed
740
		const char *pos = dot ? dot : cup_name + strlen(cup_name);
741
		char       *buf = ALLOCAN(char, pos - cup_name + 1);
Sebastian Hack's avatar
Sebastian Hack committed
742
		strncpy(buf, cup_name, pos - cup_name);
Sebastian Hack's avatar
Sebastian Hack committed
743
		buf[pos - cup_name] = '\0';
Sebastian Hack's avatar
Sebastian Hack committed
744

745
		stat_ev_ctx_push_str("bemain_compilation_unit", cup_name);
Sebastian Hack's avatar
Sebastian Hack committed
746
	}
747

748
	be_main_loop(file_handle, cup_name);
749
750

	if (be_options.timing == BE_TIME_ON) {
Matthias Braun's avatar
Matthias Braun committed
751
752
		ir_timer_stop(t);
		ir_timer_leave_high_priority();
753
		if (stat_ev_enabled) {
754
			stat_ev_dbl("bemain_backend_time", ir_timer_elapsed_msec(t));
755
		} else {
756
			double val = ir_timer_elapsed_usec(t) / 1000.0;
757
			printf("%-20s: %10.3f msec\n", "BEMAINLOOP", val);
758
		}
759
	}
760

761
	if (stat_ev_enabled) {
762
763
		stat_ev_ctx_pop("bemain_compilation_unit");
	}
764
}