bemain.c 21.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
	asm_constraint_flags_t  flags = ASM_CONSTRAINT_FLAG_NONE;
164
165
166
	const char             *c;
	asm_constraint_flags_t  tflags;

167
168
	initialize_isa();

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

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

	return flags;
}

229
int be_is_valid_clobber(const char *clobber)
230
{
231
232
	initialize_isa();

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

241
	return isa_if->is_valid_clobber(clobber);
242
243
}

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

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

252
static void be_opt_register(void)
Sebastian Hack's avatar
Sebastian Hack committed
253
{
254
	lc_opt_entry_t *be_grp;
255
256
	static int run_once = 0;

257
	if (run_once)
258
		return;
259
	run_once = 1;
260

261
262
	be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
	lc_opt_add_table(be_grp, be_main_options);
263
264
265

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

	be_init_modules();
268
}
Sebastian Hack's avatar
Sebastian Hack committed
269

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

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

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

yb9976's avatar
yb9976 committed
298
299
300
/* Finalize the Firm backend. */
void firm_be_finish(void)
{
Matthias Braun's avatar
Matthias Braun committed
301
	finish_isa();
yb9976's avatar
yb9976 committed
302
303
304
	be_quit_modules();
}

305
306
307
/* Returns the backend parameter */
const backend_params *be_get_backend_param(void)
{
308
	initialize_isa();
309
	return isa_if->get_params();
310
311
}

Manuel Mohr's avatar
Manuel Mohr committed
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
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;
}

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

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

360
	memset(asm_constraint_flags, 0, sizeof(asm_constraint_flags));
Sebastian Hack's avatar
Sebastian Hack committed
361
362

	return env;
363
364
}

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

376
377
378
379
380
381
382
383
384
/**
 * 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
 */
385
static void dump(int mask, ir_graph *irg, const char *suffix)
Sebastian Hack's avatar
Sebastian Hack committed
386
{
387
	if (be_options.dump_flags & mask)
388
		dump_ir_graph(irg, suffix);
Sebastian Hack's avatar
Sebastian Hack committed
389
}
390

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

399
400
	dump(DUMP_INITIAL, irg, "begin");

yb9976's avatar
yb9976 committed
401
402
	irg->be_data = birg;

403
404
	memset(birg, 0, sizeof(*birg));
	birg->main_env = env;
405
	obstack_init(&birg->obst);
406
	birg->lv = be_liveness_new(irg);
407

408
409
	edges_deactivate(irg);
	edges_activate(irg);
410
411
412
413

	/* set the current graph (this is important for several firm functions) */
	current_ir_graph = irg;

414
415
	/* we do this before critical edge split. As this produces less returns,
	   because sometimes (= 164.gzip) multiple returns are slower */
416
	normalize_n_returns(irg);
Sebastian Hack's avatar
Sebastian Hack committed
417

Sebastian Hack's avatar
Sebastian Hack committed
418
	/* Remove critical edges */
419
	remove_critical_cf_edges_ex(irg, /*ignore_exception_edges=*/0);
Sebastian Hack's avatar
Sebastian Hack committed
420

421
422
423
424
	/* For code generation all unreachable code and Bad nodes should be gone */
	remove_unreachable_code(irg);
	remove_bads(irg);

Sebastian Hack's avatar
Sebastian Hack committed
425
	/* Ensure, that the ir_edges are computed. */
426
	assure_edges(irg);
Sebastian Hack's avatar
Sebastian Hack committed
427

428
	be_info_init_irg(irg);
429

430
	dump(DUMP_INITIAL, irg, "prepared");
Sebastian Hack's avatar
Sebastian Hack committed
431
432
}

Matthias Braun's avatar
Matthias Braun committed
433
int be_timing;
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463

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

465
466
void be_lower_for_target(void)
{
Michael Beck's avatar
Michael Beck committed
467
	size_t i;
468

469
470
	initialize_isa();

471
472
	isa_if->lower_for_target();
	/* set the phase to low */
Michael Beck's avatar
Michael Beck committed
473
474
	for (i = get_irp_n_irgs(); i > 0;) {
		ir_graph *irg = get_irp_irg(--i);
475
476
		assert(!irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_TARGET_LOWERED));
		add_irg_constraints(irg, IR_GRAPH_CONSTRAINT_TARGET_LOWERED);
477
478
479
	}
}

Michael Beck's avatar
Michael Beck committed
480
481
482
483
/**
 * The Firm backend main loop.
 * Do architecture specific lowering for all graphs
 * and call the architecture specific code generator.
484
485
 *
 * @param file_handle   the file handle the output will be written to
486
 * @param cup_name      name of the compilation unit
Michael Beck's avatar
Michael Beck committed
487
 */
488
static void be_main_loop(FILE *file_handle, const char *cup_name)
489
{
Adam Szalkowski's avatar
Adam Szalkowski committed
490
	static const char suffix[] = ".prof";
491

492
493
494
	size_t        i;
	size_t        num_irgs;
	size_t        num_birgs;
495
496
497
498
	be_main_env_t env;
	char          prof_filename[256];
	be_irg_t      *birgs;
	arch_env_t    *arch_env;
499

Matthias Braun's avatar
Matthias Braun committed
500
501
	be_timing = (be_options.timing == BE_TIME_ON);

502
	/* perform target lowering if it didn't happen yet */
503
	if (get_irp_n_irgs() > 0 && !irg_is_constrained(get_irp_irg(0), IR_GRAPH_CONSTRAINT_TARGET_LOWERED))
504
505
		be_lower_for_target();

Matthias Braun's avatar
Matthias Braun committed
506
	if (be_timing) {
507
508
509
		for (i = 0; i < T_LAST+1; ++i) {
			be_timers[i] = ir_timer_new();
		}
510
	}
511

512
513
514
515
	be_init_env(&env, cup_name);

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

517
518
	arch_env = env.arch_env;

Christian Würdig's avatar
Christian Würdig committed
519
	/* we might need 1 birg more for instrumentation constructor */
520
521
	num_irgs = get_irp_n_irgs();
	birgs    = ALLOCAN(be_irg_t, num_irgs + 1);
522

523
524
	be_info_init();

Christian Würdig's avatar
Christian Würdig committed
525
	/* First: initialize all birgs */
526
527
528
529
530
531
532
	num_birgs = 0;
	for (i = 0; i < num_irgs; ++i) {
		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);
533
	}
534
	arch_env_handle_intrinsics(arch_env);
Michael Beck's avatar
Michael Beck committed
535

Christian Würdig's avatar
Christian Würdig committed
536
537
538
539
	/*
		Get the filename for the profiling data.
		Beware: '\0' is already included in sizeof(suffix)
	*/
540
541
542
	sprintf(prof_filename, "%.*s%s",
	        (int)(sizeof(prof_filename) - sizeof(suffix)), cup_name, suffix);

543
	bool have_profile = false;
544
545
546
547
548
	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);
549
550
551
552
		} else {
			ir_create_execfreqs_from_profile();
			ir_profile_free();
			have_profile = true;
553
554
		}
	}
555

556
	if (num_birgs > 0 && be_options.opt_profile_generate) {
557
		ir_graph *const prof_init_irg = ir_profile_instrument(prof_filename);
558
		assert(prof_init_irg->be_data == NULL);
559
560
		initialize_birg(&birgs[num_birgs], prof_init_irg, &env);
		num_birgs++;
561
562
563
564
		num_irgs++;
		assert(num_irgs == get_irp_n_irgs());
	}

Matthias Braun's avatar
Matthias Braun committed
565
566
567
	for (be_timer_id_t t = T_FIRST; t < T_LAST+1; ++t) {
		ir_timer_init_parent(be_timers[t]);
	}
568
569
570
571
572
573
574
	if (!have_profile) {
		be_timer_push(T_EXECFREQ);
		for (i = 0; i < num_irgs; ++i) {
			ir_graph *irg = get_irp_irg(i);
			ir_estimate_execfreq(irg);
		}
		be_timer_pop(T_EXECFREQ);
575
	}
Adam Szalkowski's avatar
Adam Szalkowski committed
576

577
	/* For all graphs */
578
579
580
581
582
	for (i = 0; i < num_irgs; ++i) {
		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
583

584
585
586
		/* set the current graph (this is important for several firm functions) */
		current_ir_graph = irg;

587
		if (stat_ev_enabled) {
Matthias Braun's avatar
Matthias Braun committed
588
589
590
			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
591
		}
592

593
		/* stop and reset timers */
594
		be_timer_push(T_OTHER);
595

596
		/* Verify the initial graph */
597
		be_timer_push(T_VERIFY);
598
599
600
601
		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");
602
		}
603
		be_timer_pop(T_VERIFY);
604

605
		/* get a code generator for this graph. */
606
607
		if (arch_env->impl->init_graph)
			arch_env->impl->init_graph(irg);
608

Andreas Zwinkau's avatar
Andreas Zwinkau committed
609
610
611
		/* We can't have Bad-blocks or critical edges in the backend.
		 * Before removing Bads, we remove unreachable code. */
		optimize_graph_df(irg);
612
		remove_critical_cf_edges(irg);
Andreas Zwinkau's avatar
Andreas Zwinkau committed
613
		remove_bads(irg);
614

615
616
617
		/* We often have dead code reachable through out-edges here. So for
		 * now we rebuild edges (as we need correct user count for code
		 * selection) */
618
619
620
		edges_deactivate(irg);
		edges_activate(irg);

621
		dump(DUMP_PREPARED, irg, "before-code-selection");
622

623
		/* perform codeselection */
624
		be_timer_push(T_CODEGEN);
625
626
		if (arch_env->impl->prepare_graph != NULL)
			arch_env->impl->prepare_graph(irg);
627
		be_timer_pop(T_CODEGEN);
Sebastian Hack's avatar
Sebastian Hack committed
628

629
630
		dump(DUMP_PREPARED, irg, "code-selection");

631
		/* disabled for now, fails for EmptyFor.c and XXEndless.c */
632
		/* be_live_chk_compare(irg); */
633

Christian Würdig's avatar
Christian Würdig committed
634
		/* schedule the irg */
635
		be_timer_push(T_SCHED);
636
		be_schedule_graph(irg);
637
		be_timer_pop(T_SCHED);
Sebastian Hack's avatar
Sebastian Hack committed
638

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

Christian Würdig's avatar
Christian Würdig committed
641
		/* check schedule */
642
		be_timer_push(T_VERIFY);
643
		be_sched_verify(irg, be_options.verify_option);
644
		be_timer_pop(T_VERIFY);
645

Christian Würdig's avatar
Christian Würdig committed
646
		/* introduce patterns to assure constraints */
647
		be_timer_push(T_CONSTR);
648
		/* we switch off optimizations here, because they might cause trouble */
649
		optimization_state_t state;
650
		save_optimization_state(&state);
651
		set_optimize(0);
652
653
		set_opt_cse(0);

654
655
		/* add Keeps for should_be_different constrained nodes  */
		/* beware: needs schedule due to usage of be_ssa_constr */
656
		assure_constraints(irg);
657
		be_timer_pop(T_CONSTR);
658

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

661
		/* stuff needs to be done after scheduling but before register allocation */
662
		be_timer_push(T_RA_PREPARATION);
663
664
		if (arch_env->impl->before_ra != NULL)
			arch_env->impl->before_ra(irg);
665
		be_timer_pop(T_RA_PREPARATION);
666

Sebastian Hack's avatar
Sebastian Hack committed
667
		/* connect all stack modifying nodes together (see beabi.c) */
668
		be_timer_push(T_ABI);
669
		be_abi_fix_stack_nodes(irg);
670
		be_timer_pop(T_ABI);
Christian Würdig's avatar
Christian Würdig committed
671

672
		dump(DUMP_SCHED, irg, "fix_stack");
Sebastian Hack's avatar
Sebastian Hack committed
673

Christian Würdig's avatar
Christian Würdig committed
674
		/* check schedule */
675
		be_timer_push(T_VERIFY);
676
		be_sched_verify(irg, be_options.verify_option);
677
		be_timer_pop(T_VERIFY);
Sebastian Hack's avatar
Sebastian Hack committed
678

679
		if (stat_ev_enabled) {
680
			stat_ev_dbl("bemain_costs_before_ra", be_estimate_irg_costs(irg));
Matthias Braun's avatar
Matthias Braun committed
681
682
			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
683
		}
684

685
		/* Do register allocation */
686
		be_allocate_registers(irg);
687

688
		stat_ev_dbl("bemain_costs_before_ra", be_estimate_irg_costs(irg));
689

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

692
		be_timer_push(T_FINISH);
Matthias Braun's avatar
Matthias Braun committed
693
694
		if (arch_env->impl->finish_graph != NULL)
			arch_env->impl->finish_graph(irg);
695
		be_timer_pop(T_FINISH);
696

697
		dump(DUMP_FINAL, irg, "finish");
698

699
		if (stat_ev_enabled) {
Matthias Braun's avatar
Matthias Braun committed
700
701
			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
702
703
		}

704
		/* check schedule and register allocation */
705
		be_timer_push(T_VERIFY);
706
707
		if (be_options.verify_option == BE_VERIFY_WARN) {
			irg_verify(irg, VERIFY_ENFORCE_SSA);
708
709
			be_verify_schedule(irg);
			be_verify_register_allocation(irg);
710
711
		} else if (be_options.verify_option == BE_VERIFY_ASSERT) {
			assert(irg_verify(irg, VERIFY_ENFORCE_SSA) && "irg verification failed");
712
713
			assert(be_verify_schedule(irg) && "Schedule verification failed");
			assert(be_verify_register_allocation(irg)
714
			       && "register allocation verification failed");
715

716
		}
717
		be_timer_pop(T_VERIFY);
718

Christian Würdig's avatar
Christian Würdig committed
719
		/* emit assembler code */
720
		be_timer_push(T_EMIT);
721
722
		if (arch_env->impl->emit != NULL)
			arch_env->impl->emit(irg);
723
		be_timer_pop(T_EMIT);
Christian Würdig's avatar
Christian Würdig committed
724

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

727
		restore_optimization_state(&state);
728

729
730
731
		be_timer_pop(T_OTHER);

		if (be_timing) {
732
			be_timer_id_t t;
733
			if (stat_ev_enabled) {
734
				for (t = T_FIRST; t < T_LAST+1; ++t) {
735
736
737
					char buf[128];
					snprintf(buf, sizeof(buf), "bemain_time_%s",
					         get_timer_name(t));
Manuel Mohr's avatar
Manuel Mohr committed
738
					stat_ev_dbl(buf, ir_timer_elapsed_usec(be_timers[t]));
739
				}
Matthias Braun's avatar
Matthias Braun committed
740
			} else {
741
742
				printf("==>> IRG %s <<==\n",
				       get_entity_name(get_irg_entity(irg)));
743
				for (t = T_FIRST; t < T_LAST+1; ++t) {
744
					double val = ir_timer_elapsed_usec(be_timers[t]) / 1000.0;
745
					printf("%-20s: %10.3f msec\n", get_timer_name(t), val);
746
				}
747
			}
748
			for (t = T_FIRST; t < T_LAST+1; ++t) {
749
750
751
				ir_timer_reset(be_timers[t]);
			}
		}
Michael Beck's avatar
BugFix:    
Michael Beck committed
752

753
		be_free_birg(irg);
Sebastian Hack's avatar
Sebastian Hack committed
754
		stat_ev_ctx_pop("bemain_irg");
755
	}
756

757
758
759
	be_gas_end_compilation_unit(&env);
	be_emit_exit();

760
	arch_env_end_codegeneration(arch_env);
761

Sebastian Hack's avatar
Sebastian Hack committed
762
	be_done_env(&env);
763
764

	be_info_free();
765
766
}

Michael Beck's avatar
Michael Beck committed
767
/* Main interface to the frontend. */
768
void be_main(FILE *file_handle, const char *cup_name)
769
{
Matthias Braun's avatar
Matthias Braun committed
770
	ir_timer_t *t = NULL;
771

772
	if (be_options.timing == BE_TIME_ON) {
773
		t = ir_timer_new();
774

Matthias Braun's avatar
Matthias Braun committed
775
		if (ir_timer_enter_high_priority()) {
776
777
778
			fprintf(stderr, "Warning: Could not enter high priority mode.\n");
		}

Matthias Braun's avatar
Matthias Braun committed
779
		ir_timer_reset_and_start(t);
780
	}
781

782
	if (stat_ev_enabled) {
783
		const char *dot = strrchr(cup_name, '.');
Sebastian Hack's avatar
Sebastian Hack committed
784
		const char *pos = dot ? dot : cup_name + strlen(cup_name);
785
		char       *buf = ALLOCAN(char, pos - cup_name + 1);
Sebastian Hack's avatar
Sebastian Hack committed
786
		strncpy(buf, cup_name, pos - cup_name);
Sebastian Hack's avatar
Sebastian Hack committed
787
		buf[pos - cup_name] = '\0';
Sebastian Hack's avatar
Sebastian Hack committed
788

789
		stat_ev_ctx_push_str("bemain_compilation_unit", cup_name);
Sebastian Hack's avatar
Sebastian Hack committed
790
	}
791

792
	be_main_loop(file_handle, cup_name);
793
794

	if (be_options.timing == BE_TIME_ON) {
Matthias Braun's avatar
Matthias Braun committed
795
796
		ir_timer_stop(t);
		ir_timer_leave_high_priority();
797
		if (stat_ev_enabled) {
798
			stat_ev_dbl("bemain_backend_time", ir_timer_elapsed_msec(t));
799
		} else {
800
			double val = ir_timer_elapsed_usec(t) / 1000.0;
801
			printf("%-20s: %10.3f msec\n", "BEMAINLOOP", val);
802
		}
803
	}
804

805
	if (stat_ev_enabled) {
806
807
		stat_ev_ctx_pop("bemain_compilation_unit");
	}