bemain.c 25.6 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2011 University of Karlsruhe.  All right reserved.
Christian Würdig's avatar
Christian Würdig committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * This file is part of libFirm.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

20
/**
Christian Würdig's avatar
Christian Würdig committed
21
22
23
24
 * @file
 * @brief       Main Backend driver.
 * @author      Sebastian Hack
 * @date        25.11.2004
25
 */
Michael Beck's avatar
Michael Beck committed
26
#include "config.h"
27

Sebastian Hack's avatar
Sebastian Hack committed
28
#include <stdarg.h>
29
#include <stdio.h>
30

Matthias Braun's avatar
Matthias Braun committed
31
32
#include "lc_opts.h"
#include "lc_opts_enum.h"
33

Sebastian Hack's avatar
Sebastian Hack committed
34
35
#include "obst.h"
#include "bitset.h"
36
#include "statev.h"
Sebastian Hack's avatar
Sebastian Hack committed
37
#include "irprog.h"
Sebastian Hack's avatar
Sebastian Hack committed
38
#include "irgopt.h"
Sebastian Hack's avatar
Sebastian Hack committed
39
#include "irgraph.h"
Daniel Grund's avatar
Daniel Grund committed
40
#include "irdump.h"
Sebastian Hack's avatar
Sebastian Hack committed
41
42
#include "irdom_t.h"
#include "iredges_t.h"
43
#include "irloop_t.h"
Sebastian Hack's avatar
Sebastian Hack committed
44
#include "irtools.h"
45
#include "irverify.h"
46
#include "irprintf.h"
Matthias Braun's avatar
Matthias Braun committed
47
#include "iroptimize.h"
Christian Würdig's avatar
Christian Würdig committed
48
#include "firmstat.h"
49
#include "execfreq_t.h"
50
#include "irprofile.h"
51
#include "irpass_t.h"
52
#include "ircons.h"
Sebastian Hack's avatar
Sebastian Hack committed
53

54
#include "bearch.h"
Sebastian Hack's avatar
Sebastian Hack committed
55
#include "be_t.h"
56
#include "begnuas.h"
57
#include "bemodule.h"
58
#include "beutil.h"
59
#include "benode.h"
60
#include "beirgmod.h"
61
#include "besched.h"
62
63
#include "belistsched.h"
#include "belive_t.h"
64
65
66
#include "bera.h"
#include "bechordal_t.h"
#include "beifg.h"
Daniel Grund's avatar
Daniel Grund committed
67
#include "becopyopt.h"
68
#include "becopystat.h"
69
#include "bessadestr.h"
Sebastian Hack's avatar
Sebastian Hack committed
70
#include "beabi.h"
Christian Würdig's avatar
Christian Würdig committed
71
#include "belower.h"
72
#include "bestat.h"
73
#include "beverify.h"
74
#include "beirg.h"
75
#include "bestack.h"
76
#include "beemitter.h"
Sebastian Hack's avatar
Sebastian Hack committed
77

78
79
#define NEW_ID(s) new_id_from_chars(s, sizeof(s) - 1)

Sebastian Hack's avatar
Sebastian Hack committed
80
/* options visible for anyone */
81
be_options_t be_options = {
82
	DUMP_NONE,                         /* dump flags */
83
	BE_TIME_OFF,                       /* no timing */
84
85
	false,                             /* profile_generate */
	false,                             /* profile_use */
Michael Beck's avatar
Michael Beck committed
86
	0,                                 /* try to omit frame pointer */
87
	0,                                 /* create PIC code */
88
	BE_VERIFY_WARN,                    /* verification level: warn */
Sebastian Hack's avatar
Sebastian Hack committed
89
	"",                                /* ilp server */
90
	"",                                /* ilp solver */
Sebastian Hack's avatar
Sebastian Hack committed
91
	0,                                 /* enable statistic event dumping */
92
	"",                                /* print stat events */
93
	1,                                 /* verbose assembler output */
Sebastian Hack's avatar
Sebastian Hack committed
94
95
96
};

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

Sebastian Hack's avatar
Sebastian Hack committed
99
100
/* possible dumping options */
static const lc_opt_enum_mask_items_t dump_items[] = {
101
	{ "none",       DUMP_NONE },
Sebastian Hack's avatar
Sebastian Hack committed
102
	{ "initial",    DUMP_INITIAL },
103
	{ "abi",        DUMP_ABI    },
Sebastian Hack's avatar
Sebastian Hack committed
104
105
	{ "sched",      DUMP_SCHED  },
	{ "prepared",   DUMP_PREPARED },
106
	{ "regalloc",   DUMP_RA },
Sebastian Hack's avatar
Sebastian Hack committed
107
	{ "final",      DUMP_FINAL },
108
109
	{ "be",         DUMP_BE },
	{ "all",        2 * DUMP_BE - 1 },
Sebastian Hack's avatar
Sebastian Hack committed
110
111
112
	{ NULL,         0 }
};

Christian Würdig's avatar
Christian Würdig committed
113
/* verify options. */
114
115
116
117
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
118
	{ NULL,     0 }
Christian Würdig's avatar
Christian Würdig committed
119
};
120

Sebastian Hack's avatar
Sebastian Hack committed
121
static lc_opt_enum_mask_var_t dump_var = {
122
	&be_options.dump_flags, dump_items
123
124
};

125
126
static lc_opt_enum_int_var_t verify_var = {
	&be_options.verify_option, verify_items
Christian Würdig's avatar
Christian Würdig committed
127
128
};

Sebastian Hack's avatar
Sebastian Hack committed
129
static const lc_opt_table_entry_t be_main_options[] = {
130
131
132
	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),
133
	LC_OPT_ENT_ENUM_INT ("verify",     "verify the backend irg",                              &verify_var),
134
	LC_OPT_ENT_BOOL     ("time",       "get backend timing statistics",                       &be_options.timing),
135
136
	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),
137
	LC_OPT_ENT_BOOL     ("statev",     "dump statistic events",                               &be_options.statev),
138
	LC_OPT_ENT_STR      ("filtev",     "filter for stat events (regex if support is active",   be_options.filtev),
139
	LC_OPT_ENT_BOOL     ("verboseasm", "enable verbose assembler output",                     &be_options.verbose_asm),
140

141
142
	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),
143
	LC_OPT_LAST
Sebastian Hack's avatar
Sebastian Hack committed
144
145
};

146
147
static be_module_list_entry_t *isa_ifs         = NULL;
static bool                    isa_initialized = false;
148

149
asm_constraint_flags_t asm_constraint_flags[256];
150

151
152
153
154
155
static void initialize_isa(void)
{
	if (isa_initialized)
		return;
	isa_if->init();
Matthias Braun's avatar
Matthias Braun committed
156
157
158
159
160
161
162
163
164
	isa_initialized = true;
}

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

167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
void be_init_default_asm_constraint_flags(void)
{
	asm_constraint_flags['?'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
	asm_constraint_flags['!'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
	asm_constraint_flags['&'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT
		| ASM_CONSTRAINT_FLAG_MODIFIER_EARLYCLOBBER;
	asm_constraint_flags['%'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT
		| ASM_CONSTRAINT_FLAG_MODIFIER_COMMUTATIVE;
	asm_constraint_flags['!'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;

	asm_constraint_flags['='] = ASM_CONSTRAINT_FLAG_MODIFIER_WRITE
		| ASM_CONSTRAINT_FLAG_MODIFIER_NO_READ;
	asm_constraint_flags['+'] = ASM_CONSTRAINT_FLAG_MODIFIER_READ
		| ASM_CONSTRAINT_FLAG_MODIFIER_WRITE;

	asm_constraint_flags['i'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['s'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['E'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['F'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['G'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['H'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['I'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['J'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['K'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['L'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['M'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['N'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['O'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['P'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;

	asm_constraint_flags['m'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;
	asm_constraint_flags['o'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;
	asm_constraint_flags['V'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;
	asm_constraint_flags['<'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;
	asm_constraint_flags['>'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;

	asm_constraint_flags['p'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
	asm_constraint_flags['0'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
	asm_constraint_flags['1'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
	asm_constraint_flags['2'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
	asm_constraint_flags['3'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
	asm_constraint_flags['4'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
	asm_constraint_flags['5'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
	asm_constraint_flags['6'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
	asm_constraint_flags['7'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
	asm_constraint_flags['8'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
	asm_constraint_flags['9'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;

	asm_constraint_flags['X'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER
		| ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP
		| ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;

	/* these should have been catched by the parsing code already */
	asm_constraint_flags['#']  = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
	asm_constraint_flags['*']  = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
	asm_constraint_flags[' ']  = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
	asm_constraint_flags['\t'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
	asm_constraint_flags['\n'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
	asm_constraint_flags['\r'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
}

228
asm_constraint_flags_t be_parse_asm_constraints(const char *constraint)
229
{
230
	asm_constraint_flags_t  flags = ASM_CONSTRAINT_FLAG_NONE;
231
232
233
	const char             *c;
	asm_constraint_flags_t  tflags;

234
235
	initialize_isa();

236
237
238
239
	for (c = constraint; *c != '\0'; ++c) {
		switch (*c) {
		case '#':
			/* 'comment' stuff */
240
			while (*c != 0 && *c != ',')
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
				++c;
			break;
		case '*':
			/* 'comment' character */
			++c;
			break;
		case ' ':
		case '\t':
		case '\n':
		case '\r':
			break;
		default:
			tflags = asm_constraint_flags[(int) *c];
			if (tflags != 0) {
				flags |= tflags;
			} else {
257
				flags |= isa_if->parse_asm_constraint(&c);
258
259
260
261
262
			}
			break;
		}
	}

263
	if ((
264
265
	        flags & ASM_CONSTRAINT_FLAG_MODIFIER_WRITE &&
	        flags & ASM_CONSTRAINT_FLAG_MODIFIER_NO_WRITE
266
	    ) || (
267
268
	        flags & ASM_CONSTRAINT_FLAG_MODIFIER_READ &&
	        flags & ASM_CONSTRAINT_FLAG_MODIFIER_NO_READ
269
	    )) {
270
271
		flags |= ASM_CONSTRAINT_FLAG_INVALID;
	}
272
273
274
275
276
	if (!(flags & (ASM_CONSTRAINT_FLAG_MODIFIER_READ     |
	               ASM_CONSTRAINT_FLAG_MODIFIER_WRITE    |
	               ASM_CONSTRAINT_FLAG_MODIFIER_NO_WRITE |
	               ASM_CONSTRAINT_FLAG_MODIFIER_NO_READ)
	    )) {
277
278
		flags |= ASM_CONSTRAINT_FLAG_MODIFIER_READ;
	}
279
280
281
282

	return flags;
}

283
int be_is_valid_clobber(const char *clobber)
284
{
285
286
	initialize_isa();

287
288
289
	/* 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)
290
		return 1;
291
292
	/* cc (condition code) is always valid */
	if (strcmp(clobber, "cc") == 0)
293
		return 1;
294

295
	return isa_if->is_valid_clobber(clobber);
296
297
}

298
299
void be_register_isa_if(const char *name, const arch_isa_if_t *isa)
{
300
	if (isa_if == NULL)
301
302
303
304
305
		isa_if = isa;

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

306
static void be_opt_register(void)
Sebastian Hack's avatar
Sebastian Hack committed
307
{
308
	lc_opt_entry_t *be_grp;
309
310
	static int run_once = 0;

311
	if (run_once)
312
		return;
313
	run_once = 1;
314

315
316
	be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
	lc_opt_add_table(be_grp, be_main_options);
317
318
319

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

	be_init_modules();
322
}
Sebastian Hack's avatar
Sebastian Hack committed
323

324
/* Parse one argument. */
325
326
int be_parse_arg(const char *arg)
{
327
	lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
Michael Beck's avatar
Michael Beck committed
328
	if (strcmp(arg, "help") == 0 || (arg[0] == '?' && arg[1] == '\0')) {
329
		lc_opt_print_help_for_entry(be_grp, '-', stdout);
Michael Beck's avatar
Michael Beck committed
330
331
		return -1;
	}
332
	return lc_opt_from_single_arg(be_grp, NULL, arg, NULL);
333
334
}

Christian Würdig's avatar
Christian Würdig committed
335
/* Perform schedule verification if requested. */
336
static void be_sched_verify(ir_graph *irg, int verify_opt)
337
{
338
	if (verify_opt == BE_VERIFY_WARN) {
339
		be_verify_schedule(irg);
340
	} else if (verify_opt == BE_VERIFY_ASSERT) {
341
		assert(be_verify_schedule(irg) && "Schedule verification failed.");
Christian Würdig's avatar
Christian Würdig committed
342
343
344
	}
}

345
346
/* Initialize the Firm backend. Must be run first in init_firm()! */
void firm_be_init(void)
347
{
Sebastian Hack's avatar
Sebastian Hack committed
348
	be_opt_register();
349
	be_init_modules();
350
}
351

yb9976's avatar
yb9976 committed
352
353
354
/* Finalize the Firm backend. */
void firm_be_finish(void)
{
Matthias Braun's avatar
Matthias Braun committed
355
	finish_isa();
yb9976's avatar
yb9976 committed
356
357
358
	be_quit_modules();
}

359
360
361
/* Returns the backend parameter */
const backend_params *be_get_backend_param(void)
{
362
	initialize_isa();
363
	return isa_if->get_params();
364
365
}

Manuel Mohr's avatar
Manuel Mohr committed
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
392
393
394
395
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;
}

396
397
398
399
400
401
/**
 * 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
 */
402
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
403
{
Sebastian Hack's avatar
Sebastian Hack committed
404
	memset(env, 0, sizeof(*env));
405
406
407
408
	env->ent_trampoline_map   = pmap_create();
	env->pic_trampolines_type = new_type_class(NEW_ID("$PIC_TRAMPOLINE_TYPE"));
	env->ent_pic_symbol_map   = pmap_create();
	env->pic_symbols_type     = new_type_struct(NEW_ID("$PIC_SYMBOLS_TYPE"));
409
	env->cup_name             = compilation_unit_name;
410
	env->arch_env             = isa_if->begin_codegeneration();
411
412

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

414
	memset(asm_constraint_flags, 0, sizeof(asm_constraint_flags));
Sebastian Hack's avatar
Sebastian Hack committed
415
416

	return env;
417
418
}

419
420
421
/**
 * Called when the be_main_env_t can be destroyed.
 */
Sebastian Hack's avatar
Sebastian Hack committed
422
static void be_done_env(be_main_env_t *env)
423
{
424
425
	pmap_destroy(env->ent_trampoline_map);
	pmap_destroy(env->ent_pic_symbol_map);
426
427
	free_type(env->pic_trampolines_type);
	free_type(env->pic_symbols_type);
Sebastian Hack's avatar
Sebastian Hack committed
428
}
Sebastian Hack's avatar
Sebastian Hack committed
429

430
431
432
433
434
435
436
437
438
/**
 * 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
 */
439
static void dump(int mask, ir_graph *irg, const char *suffix)
Sebastian Hack's avatar
Sebastian Hack committed
440
{
441
	if (be_options.dump_flags & mask)
442
		dump_ir_graph(irg, suffix);
Sebastian Hack's avatar
Sebastian Hack committed
443
}
444

Michael Beck's avatar
Michael Beck committed
445
/**
446
 * Prepare a backend graph for code generation and initialize its irg
Michael Beck's avatar
Michael Beck committed
447
 */
448
static void initialize_birg(be_irg_t *birg, ir_graph *irg, be_main_env_t *env)
Sebastian Hack's avatar
Sebastian Hack committed
449
{
450
451
452
	/* don't duplicate locals in backend when dumping... */
	ir_remove_dump_flags(ir_dump_flag_consts_local);

453
454
	dump(DUMP_INITIAL, irg, "begin");

yb9976's avatar
yb9976 committed
455
456
	irg->be_data = birg;

457
458
	memset(birg, 0, sizeof(*birg));
	birg->main_env = env;
459
	obstack_init(&birg->obst);
460
	birg->lv = be_liveness_new(irg);
461

462
463
	edges_deactivate(irg);
	edges_activate(irg);
464
465
466
467

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

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

Sebastian Hack's avatar
Sebastian Hack committed
472
	/* Remove critical edges */
473
	remove_critical_cf_edges_ex(irg, /*ignore_exception_edges=*/0);
Sebastian Hack's avatar
Sebastian Hack committed
474

475
476
477
478
	/* 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
479
	/* Ensure, that the ir_edges are computed. */
480
	assure_edges(irg);
Sebastian Hack's avatar
Sebastian Hack committed
481

482
	be_info_init_irg(irg);
483

484
	dump(DUMP_INITIAL, irg, "prepared");
Sebastian Hack's avatar
Sebastian Hack committed
485
486
}

Matthias Braun's avatar
Matthias Braun committed
487
int be_timing;
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517

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

519
520
void be_lower_for_target(void)
{
Michael Beck's avatar
Michael Beck committed
521
	size_t i;
522

523
524
	initialize_isa();

525
526
	isa_if->lower_for_target();
	/* set the phase to low */
Michael Beck's avatar
Michael Beck committed
527
528
	for (i = get_irp_n_irgs(); i > 0;) {
		ir_graph *irg = get_irp_irg(--i);
529
530
		assert(!irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_TARGET_LOWERED));
		add_irg_constraints(irg, IR_GRAPH_CONSTRAINT_TARGET_LOWERED);
531
532
533
	}
}

Michael Beck's avatar
Michael Beck committed
534
535
536
537
/**
 * The Firm backend main loop.
 * Do architecture specific lowering for all graphs
 * and call the architecture specific code generator.
538
539
 *
 * @param file_handle   the file handle the output will be written to
540
 * @param cup_name      name of the compilation unit
Michael Beck's avatar
Michael Beck committed
541
 */
542
static void be_main_loop(FILE *file_handle, const char *cup_name)
543
{
Adam Szalkowski's avatar
Adam Szalkowski committed
544
	static const char suffix[] = ".prof";
545

546
547
548
	size_t        i;
	size_t        num_irgs;
	size_t        num_birgs;
549
550
551
552
	be_main_env_t env;
	char          prof_filename[256];
	be_irg_t      *birgs;
	arch_env_t    *arch_env;
553

Matthias Braun's avatar
Matthias Braun committed
554
555
	be_timing = (be_options.timing == BE_TIME_ON);

556
	/* perform target lowering if it didn't happen yet */
557
	if (get_irp_n_irgs() > 0 && !irg_is_constrained(get_irp_irg(0), IR_GRAPH_CONSTRAINT_TARGET_LOWERED))
558
559
		be_lower_for_target();

Matthias Braun's avatar
Matthias Braun committed
560
	if (be_timing) {
561
562
563
		for (i = 0; i < T_LAST+1; ++i) {
			be_timers[i] = ir_timer_new();
		}
564
	}
565

566
567
568
569
	be_init_env(&env, cup_name);

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

571
572
	arch_env = env.arch_env;

Christian Würdig's avatar
Christian Würdig committed
573
	/* we might need 1 birg more for instrumentation constructor */
574
575
	num_irgs = get_irp_n_irgs();
	birgs    = ALLOCAN(be_irg_t, num_irgs + 1);
576

577
578
	be_info_init();

Christian Würdig's avatar
Christian Würdig committed
579
	/* First: initialize all birgs */
580
581
582
583
584
585
586
	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);
587
	}
588
	arch_env_handle_intrinsics(arch_env);
Michael Beck's avatar
Michael Beck committed
589

Christian Würdig's avatar
Christian Würdig committed
590
591
592
593
	/*
		Get the filename for the profiling data.
		Beware: '\0' is already included in sizeof(suffix)
	*/
594
595
596
	sprintf(prof_filename, "%.*s%s",
	        (int)(sizeof(prof_filename) - sizeof(suffix)), cup_name, suffix);

597
	bool have_profile = false;
598
599
600
601
602
	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);
603
604
605
606
		} else {
			ir_create_execfreqs_from_profile();
			ir_profile_free();
			have_profile = true;
607
608
		}
	}
609

610
	if (num_birgs > 0 && be_options.opt_profile_generate) {
611
		ir_graph *const prof_init_irg = ir_profile_instrument(prof_filename);
612
		assert(prof_init_irg->be_data == NULL);
613
614
		initialize_birg(&birgs[num_birgs], prof_init_irg, &env);
		num_birgs++;
615
616
617
618
		num_irgs++;
		assert(num_irgs == get_irp_n_irgs());
	}

Matthias Braun's avatar
Matthias Braun committed
619
620
621
	for (be_timer_id_t t = T_FIRST; t < T_LAST+1; ++t) {
		ir_timer_init_parent(be_timers[t]);
	}
622
623
624
625
626
627
628
	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);
629
	}
Adam Szalkowski's avatar
Adam Szalkowski committed
630

631
	/* For all graphs */
632
633
634
635
636
	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
637

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

641
		if (stat_ev_enabled) {
Matthias Braun's avatar
Matthias Braun committed
642
643
644
			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
645
		}
646

647
		/* stop and reset timers */
648
		be_timer_push(T_OTHER);
649

650
		/* Verify the initial graph */
651
		be_timer_push(T_VERIFY);
652
653
654
655
		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");
656
		}
657
		be_timer_pop(T_VERIFY);
658

659
		/* get a code generator for this graph. */
660
661
		if (arch_env->impl->init_graph)
			arch_env->impl->init_graph(irg);
662
663

		/* some transformations need to be done before abi introduce */
664
665
		if (arch_env->impl->before_abi != NULL)
			arch_env->impl->before_abi(irg);
666

Sebastian Hack's avatar
Sebastian Hack committed
667
		/* implement the ABI conventions. */
668
		if (!arch_env->custom_abi) {
669
670
671
			be_timer_push(T_ABI);
			be_abi_introduce(irg);
			be_timer_pop(T_ABI);
672
673
			dump(DUMP_ABI, irg, "abi");
		}
674

Andreas Zwinkau's avatar
Andreas Zwinkau committed
675
676
677
		/* We can't have Bad-blocks or critical edges in the backend.
		 * Before removing Bads, we remove unreachable code. */
		optimize_graph_df(irg);
678
		remove_critical_cf_edges(irg);
Andreas Zwinkau's avatar
Andreas Zwinkau committed
679
		remove_bads(irg);
680

681
682
683
		/* 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) */
684
685
686
		edges_deactivate(irg);
		edges_activate(irg);

687
		dump(DUMP_PREPARED, irg, "before-code-selection");
688

689
		/* perform codeselection */
690
		be_timer_push(T_CODEGEN);
691
692
		if (arch_env->impl->prepare_graph != NULL)
			arch_env->impl->prepare_graph(irg);
693
		be_timer_pop(T_CODEGEN);
Sebastian Hack's avatar
Sebastian Hack committed
694

695
696
		dump(DUMP_PREPARED, irg, "code-selection");

697
		/* disabled for now, fails for EmptyFor.c and XXEndless.c */
698
		/* be_live_chk_compare(irg); */
699

Christian Würdig's avatar
Christian Würdig committed
700
		/* schedule the irg */
701
		be_timer_push(T_SCHED);
702
		be_schedule_graph(irg);
703
		be_timer_pop(T_SCHED);
Sebastian Hack's avatar
Sebastian Hack committed
704

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

Christian Würdig's avatar
Christian Würdig committed
707
		/* check schedule */
708
		be_timer_push(T_VERIFY);
709
		be_sched_verify(irg, be_options.verify_option);
710
		be_timer_pop(T_VERIFY);
711

Christian Würdig's avatar
Christian Würdig committed
712
		/* introduce patterns to assure constraints */
713
		be_timer_push(T_CONSTR);
714
		/* we switch off optimizations here, because they might cause trouble */
715
		optimization_state_t state;
716
		save_optimization_state(&state);
717
		set_optimize(0);
718
719
		set_opt_cse(0);

720
721
		/* add Keeps for should_be_different constrained nodes  */
		/* beware: needs schedule due to usage of be_ssa_constr */
722
		assure_constraints(irg);
723
		be_timer_pop(T_CONSTR);
724

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

727
		/* stuff needs to be done after scheduling but before register allocation */
728
		be_timer_push(T_RA_PREPARATION);
729
730
		if (arch_env->impl->before_ra != NULL)
			arch_env->impl->before_ra(irg);
731
		be_timer_pop(T_RA_PREPARATION);
732

Sebastian Hack's avatar
Sebastian Hack committed
733
		/* connect all stack modifying nodes together (see beabi.c) */
734
		be_timer_push(T_ABI);
735
		be_abi_fix_stack_nodes(irg);
736
		be_timer_pop(T_ABI);
Christian Würdig's avatar
Christian Würdig committed
737

738
		dump(DUMP_SCHED, irg, "fix_stack");
Sebastian Hack's avatar
Sebastian Hack committed
739

Christian Würdig's avatar
Christian Würdig committed
740
		/* check schedule */
741
		be_timer_push(T_VERIFY);
742
		be_sched_verify(irg, be_options.verify_option);
743
		be_timer_pop(T_VERIFY);
Sebastian Hack's avatar
Sebastian Hack committed
744

745
		if (stat_ev_enabled) {
746
			stat_ev_dbl("bemain_costs_before_ra", be_estimate_irg_costs(irg));
Matthias Braun's avatar
Matthias Braun committed
747
748
			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
749
		}
750

751
		/* Do register allocation */
752
		be_allocate_registers(irg);
753

754
		stat_ev_dbl("bemain_costs_before_ra", be_estimate_irg_costs(irg));
755

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

758
		be_timer_push(T_FINISH);
Matthias Braun's avatar
Matthias Braun committed
759
760
		if (arch_env->impl->finish_graph != NULL)
			arch_env->impl->finish_graph(irg);
761
		be_timer_pop(T_FINISH);
762

763
		dump(DUMP_FINAL, irg, "finish");
764

765
		if (stat_ev_enabled) {
Matthias Braun's avatar
Matthias Braun committed
766
767
			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
768
769
		}

770
		/* check schedule and register allocation */
771
		be_timer_push(T_VERIFY);
772
773
		if (be_options.verify_option == BE_VERIFY_WARN) {
			irg_verify(irg, VERIFY_ENFORCE_SSA);
774
775
			be_verify_schedule(irg);
			be_verify_register_allocation(irg);
776
777
		} else if (be_options.verify_option == BE_VERIFY_ASSERT) {
			assert(irg_verify(irg, VERIFY_ENFORCE_SSA) && "irg verification failed");
778
779
			assert(be_verify_schedule(irg) && "Schedule verification failed");
			assert(be_verify_register_allocation(irg)
780
			       && "register allocation verification failed");
781

782
		}
783
		be_timer_pop(T_VERIFY);
784

Christian Würdig's avatar
Christian Würdig committed
785
		/* emit assembler code */
786
		be_timer_push(T_EMIT);
787
788
		if (arch_env->impl->emit != NULL)
			arch_env->impl->emit(irg);
789
		be_timer_pop(T_EMIT);
Christian Würdig's avatar
Christian Würdig committed
790

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

793
		restore_optimization_state(&state);
794

795
796
797
		be_timer_pop(T_OTHER);

		if (be_timing) {
798
			be_timer_id_t t;
799
			if (stat_ev_enabled) {
800
				for (t = T_FIRST; t < T_LAST+1; ++t) {
801
802
803
804
805
					char buf[128];
					snprintf(buf, sizeof(buf), "bemain_time_%s",
					         get_timer_name(t));
					stat_ev_dbl(buf, ir_timer_elapsed_usec(be_timers[i]));
				}
Matthias Braun's avatar
Matthias Braun committed
806
			} else {
807
808
				printf("==>> IRG %s <<==\n",
				       get_entity_name(get_irg_entity(irg)));
809
				for (t = T_FIRST; t < T_LAST+1; ++t) {
810
					double val = ir_timer_elapsed_usec(be_timers[t]) / 1000.0;
811
					printf("%-20s: %10.3f msec\n", get_timer_name(t), val);
812
				}
813
			}
814
			for (t = T_FIRST; t < T_LAST+1; ++t) {
815
816
817
				ir_timer_reset(be_timers[t]);
			}
		}
Michael Beck's avatar
BugFix:    
Michael Beck committed
818

819
		be_free_birg(irg);
Sebastian Hack's avatar
Sebastian Hack committed
820
		stat_ev_ctx_pop("bemain_irg");
821
	}
822

823
824
825
	be_gas_end_compilation_unit(&env);
	be_emit_exit();

826
	arch_env_end_codegeneration(arch_env);
827

Sebastian Hack's avatar
Sebastian Hack committed
828
	be_done_env(&env);
829
830

	be_info_free();
831
832
}

Michael Beck's avatar
Michael Beck committed
833
/* Main interface to the frontend. */
834
void be_main(FILE *file_handle, const char *cup_name)
835
{
Matthias Braun's avatar
Matthias Braun committed
836
	ir_timer_t *t = NULL;
837

838
	if (be_options.timing == BE_TIME_ON) {
839
		t = ir_timer_new();
840

Matthias Braun's avatar
Matthias Braun committed
841
		if (ir_timer_enter_high_priority()) {
842
843
844
			fprintf(stderr, "Warning: Could not enter high priority mode.\n");
		}

Matthias Braun's avatar
Matthias Braun committed
845
		ir_timer_reset_and_start(t);
846
	}
847

Sebastian Hack's avatar
Sebastian Hack committed
848
	if (be_options.statev) {
849
		const char *dot = strrchr(cup_name, '.');
Sebastian Hack's avatar
Sebastian Hack committed
850
		const char *pos = dot ? dot : cup_name + strlen(cup_name);
851
		char       *buf = ALLOCAN(char, pos - cup_name + 1);
Sebastian Hack's avatar
Sebastian Hack committed
852
		strncpy(buf, cup_name, pos - cup_name);
Sebastian Hack's avatar
Sebastian Hack committed
853
		buf[pos - cup_name] = '\0';
Sebastian Hack's avatar
Sebastian Hack committed
854

Sebastian Hack's avatar
Sebastian Hack committed
855
		be_options.statev = 1;