+ memset(env, 0, sizeof(*env));
+ obstack_init(&env->obst);
+ env->arch_env = obstack_alloc(&env->obst, sizeof(env->arch_env[0]));
+ env->options = &be_options;
+ FIRM_DBG_REGISTER(env->dbg, "be.main");
+
+ arch_env_init(env->arch_env, isa_if, file_handle, env);
+
+ /* Register the irn handler of the architecture */
+ if (arch_isa_get_irn_handler(env->arch_env->isa))
+ arch_env_push_irn_handler(env->arch_env, arch_isa_get_irn_handler(env->arch_env->isa));
+
+ /*
+ * Register the node handler of the back end infrastructure.
+ * This irn handler takes care of the platform independent
+ * spill, reload and perm nodes.
+ */
+ arch_env_push_irn_handler(env->arch_env, &be_node_irn_handler);
+ env->phi_handler = be_phi_handler_new(env->arch_env);
+ arch_env_push_irn_handler(env->arch_env, env->phi_handler);
+
+ env->db_handle = be_options.stabs_debug_support ? be_stabs_open(file_handle) : be_nulldbg_open();
+ return env;
+}
+
+static void be_done_env(be_main_env_t *env)
+{
+ env->arch_env->isa->impl->done(env->arch_env->isa);
+ be_dbg_close(env->db_handle);
+ be_phi_handler_free(env->phi_handler);
+ obstack_free(&env->obst, NULL);
+}
+
+/**
+ * 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
+ */
+static void dump(int mask, ir_graph *irg, const char *suffix,
+ void (*dumper)(ir_graph *, const char *))
+{
+ if(be_options.dump_flags & mask)
+ be_dump(irg, suffix, dumper);
+}
+
+/**
+ * Prepare a backend graph for code generation and initialize its birg
+ */
+static void initialize_birg(be_irg_t *birg, ir_graph *irg, be_main_env_t *env)
+{
+ memset(birg, 0, sizeof(*birg));
+ birg->irg = irg;
+ birg->main_env = env;
+
+ edges_deactivate_kind(irg, EDGE_KIND_DEP);
+ edges_activate_kind(irg, EDGE_KIND_DEP);
+
+ DBG((env->dbg, LEVEL_2, "====> IRG: %F\n", irg));
+ dump(DUMP_INITIAL, irg, "-begin", dump_ir_block_graph);
+
+ be_stat_init_irg(env->arch_env, irg);
+ be_do_stat_nodes(irg, "01 Begin");
+
+ /* set the current graph (this is important for several firm functions) */
+ current_ir_graph = irg;
+
+ /* Normalize proj nodes. */
+ normalize_proj_nodes(irg);
+
+ /* Make just one return node. */
+ normalize_one_return(irg);
+
+ /* Remove critical edges */
+ remove_critical_cf_edges(irg);
+
+ /* Ensure, that the ir_edges are computed. */
+ edges_assure(irg);
+
+ /* reset the phi handler. */
+ be_phi_handler_reset(env->phi_handler);
+
+ set_irg_phase_state(irg, phase_backend);
+}
+
+#ifdef WITH_LIBCORE
+
+#define BE_TIMER_PUSH(timer) \
+ if (be_options.timing == BE_TIME_ON) { \
+ int res = lc_timer_push(timer); \
+ if (be_options.vrfy_option == BE_VRFY_ASSERT) \
+ assert(res && "Timer already on stack, cannot be pushed twice."); \
+ else if (be_options.vrfy_option == BE_VRFY_WARN && ! res) \
+ fprintf(stderr, "Timer %s already on stack, cannot be pushed twice.\n", \
+ lc_timer_get_name(timer)); \
+ }
+#define BE_TIMER_POP(timer) \
+ if (be_options.timing == BE_TIME_ON) { \
+ lc_timer_t *tmp = lc_timer_pop(); \
+ if (be_options.vrfy_option == BE_VRFY_ASSERT) \
+ assert(tmp == timer && "Attempt to pop wrong timer."); \
+ else if (be_options.vrfy_option == BE_VRFY_WARN && tmp != timer) \
+ fprintf(stderr, "Attempt to pop wrong timer. %s is on stack, trying to pop %s.\n", \
+ lc_timer_get_name(tmp), lc_timer_get_name(timer)); \
+ timer = tmp; \
+ }
+
+#define BE_TIMER_ONLY(code) do { if (be_options.timing == BE_TIME_ON) { code; } } while(0)
+
+#else
+
+#define BE_TIMER_PUSH(timer)
+#define BE_TIMER_POP(timer)
+#define BE_TIMER_ONLY(code)
+
+#endif /* WITH_LIBCORE */
+
+
+/**
+ * The Firm backend main loop.
+ * Do architecture specific lowering for all graphs
+ * and call the architecture specific code generator.
+ *
+ * @param file_handle the file handle the output will be written to
+ * @param cup_name name of the compilation unit
+ */
+static void be_main_loop(FILE *file_handle, const char *cup_name)
+{
+ int i;
+ arch_isa_t *isa;
+ be_main_env_t env;
+ unsigned num_nodes_b = 0;
+ unsigned num_nodes_a = 0;
+ unsigned num_nodes_r = 0;
+ char prof_filename[256];
+ static const char suffix[] = ".prof";
+ be_irg_t *birgs;
+ unsigned num_birgs;
+ ir_graph **irg_list, **backend_irg_list;
+
+ be_ra_timer_t *ra_timer;
+
+#ifdef WITH_LIBCORE
+ lc_timer_t *t_abi = NULL;
+ lc_timer_t *t_codegen = NULL;
+ lc_timer_t *t_sched = NULL;
+ lc_timer_t *t_constr = NULL;
+ lc_timer_t *t_regalloc = NULL;
+ lc_timer_t *t_finish = NULL;
+ lc_timer_t *t_emit = NULL;
+ lc_timer_t *t_other = NULL;
+ lc_timer_t *t_verify = NULL;
+
+ if (be_options.timing == BE_TIME_ON) {
+ t_abi = lc_timer_register("beabi", "be abi introduction");
+ t_codegen = lc_timer_register("codegen", "codegeneration");
+ t_sched = lc_timer_register("sched", "scheduling");
+ t_constr = lc_timer_register("constr", "assure constraints");
+ t_regalloc = lc_timer_register("regalloc", "register allocation");
+ t_finish = lc_timer_register("finish", "graph finish");
+ t_emit = lc_timer_register("emiter", "code emiter");
+ t_verify = lc_timer_register("verify", "graph verification");
+ t_other = lc_timer_register("other", "other");
+ }
+#endif /* WITH_LIBCORE */
+
+ be_init_env(&env, file_handle);
+
+ isa = arch_env_get_isa(env.arch_env);
+
+ be_dbg_so(env.db_handle, cup_name);
+ be_dbg_types(env.db_handle);
+
+ /* backend may provide an ordered list of irgs where code should be generated for */
+ irg_list = NEW_ARR_F(ir_graph *, 0);
+ backend_irg_list = arch_isa_get_backend_irg_list(isa, irg_list);
+
+ /* we might need 1 birg more for instrumentation constructor */
+ num_birgs = backend_irg_list ? ARR_LEN(backend_irg_list) : get_irp_n_irgs();
+ birgs = alloca(sizeof(birgs[0]) * (num_birgs + 1));
+
+ /* First: initialize all birgs */
+ for(i = 0; i < num_birgs; ++i) {
+ ir_graph *irg = backend_irg_list ? backend_irg_list[i] : get_irp_irg(i);
+ initialize_birg(&birgs[i], irg, &env);
+ }
+ /* TODO: DEL_ARR_F(irg_list) will break, if list was modified by Backend ?!?! */
+ if (backend_irg_list)
+ DEL_ARR_F(backend_irg_list);
+ else
+ DEL_ARR_F(irg_list);
+
+ /*
+ Get the filename for the profiling data.
+ Beware: '\0' is already included in sizeof(suffix)
+ */
+ memset(prof_filename, 0, sizeof(prof_filename));
+ strncpy(prof_filename, cup_name, sizeof(prof_filename) - sizeof(suffix));
+ strcat(prof_filename, suffix);