+static unsigned long long count_firm_nodes(void)
+{
+ unsigned long long count = 0;
+
+ int n_irgs = get_irp_n_irgs();
+ for (int i = 0; i < n_irgs; ++i) {
+ ir_graph *irg = get_irp_irg(i);
+ irg_walk_graph(irg, node_counter, NULL, &count);
+ }
+ return count;
+}
+
+static int compilation_loop(compile_mode_t mode, compilation_unit_t *units,
+ lang_standard_t standard, FILE *out)
+{
+ int result = EXIT_SUCCESS;
+ bool already_constructed_firm = false;
+ for (compilation_unit_t *unit = units; unit != NULL; unit = unit->next) {
+ const char *const inputname = unit->name;
+
+ determine_unit_standard(unit, standard);
+ setup_cmode(unit);
+
+ stat_ev_ctx_push_str("compilation_unit", inputname);
+
+again:
+ switch (unit->type) {
+ case COMPILATION_UNIT_IR: {
+ bool res = open_input(unit);
+ if (!res) {
+ result = EXIT_FAILURE;
+ break;
+ }
+ res = !ir_import_file(unit->input, unit->name);
+ if (!res) {
+ fprintf(stderr, "Import of firm graph from '%s' failed\n",
+ inputname);
+ result = EXIT_FAILURE;
+ break;
+ }
+ unit->type = COMPILATION_UNIT_INTERMEDIATE_REPRESENTATION;
+ goto again;
+ }
+ case COMPILATION_UNIT_ASSEMBLER:
+ panic("TODO: preprocess for assembler");
+ case COMPILATION_UNIT_C:
+ case COMPILATION_UNIT_CXX:
+ if (external_preprocessor != NULL) {
+ bool res = run_external_preprocessor(unit);
+ if (!res) {
+ result = EXIT_FAILURE;
+ break;
+ }
+ goto again;
+ }
+ /* FALLTHROUGH */
+
+ case COMPILATION_UNIT_PREPROCESSED_C:
+ case COMPILATION_UNIT_PREPROCESSED_CXX: {
+ bool res = open_input(unit);
+ if (!res) {
+ result = EXIT_FAILURE;
+ break;
+ }
+ init_tokens();
+
+ if (mode == PreprocessOnly) {
+ bool res = output_preprocessor_tokens(unit, out);
+ if (!res) {
+ result = EXIT_FAILURE;
+ break;
+ }
+ break;
+ }
+
+ /* do the actual parsing */
+ do_parsing(unit);
+ goto again;
+ }
+ case COMPILATION_UNIT_AST:
+ /* prints the AST even if errors occurred */
+ if (mode == PrintAst) {
+ print_to_file(out);
+ print_ast(unit->ast);
+ }
+ if (unit->parse_errors) {
+ result = EXIT_FAILURE;
+ break;
+ }
+
+ if (mode == BenchmarkParser) {
+ break;
+ } else if (mode == PrintFluffy) {
+ write_fluffy_decls(out, unit->ast);
+ break;
+ } else if (mode == PrintJna) {
+ write_jna_decls(out, unit->ast);
+ break;
+ } else if (mode == PrintCompoundSizes) {
+ write_compoundsizes(out, unit->ast);
+ break;
+ }
+
+ /* build the firm graph */
+ ir_timer_t *t_construct = ir_timer_new();
+ timer_register(t_construct, "Frontend: Graph construction");
+ timer_start(t_construct);
+ if (already_constructed_firm) {
+ panic("compiling multiple files/translation units not possible");
+ }
+ init_implicit_optimizations();
+ translation_unit_to_firm(unit->ast);
+ already_constructed_firm = true;
+ timer_stop(t_construct);
+ if (stat_ev_enabled) {
+ stat_ev_dbl("time_graph_construction", ir_timer_elapsed_sec(t_construct));
+ stat_ev_int("size_graph_construction", count_firm_nodes());
+ }
+ unit->type = COMPILATION_UNIT_INTERMEDIATE_REPRESENTATION;
+ goto again;
+
+ case COMPILATION_UNIT_INTERMEDIATE_REPRESENTATION:
+ if (mode == ParseOnly)
+ break;
+
+ if (mode == CompileDump) {
+ /* find irg */
+ ident *id = new_id_from_str(dumpfunction);
+ ir_graph *irg = NULL;
+ int n_irgs = get_irp_n_irgs();
+ for (int i = 0; i < n_irgs; ++i) {
+ ir_graph *tirg = get_irp_irg(i);
+ ident *irg_id = get_entity_ident(get_irg_entity(tirg));
+ if (irg_id == id) {
+ irg = tirg;
+ break;
+ }
+ }
+
+ if (irg == NULL) {
+ fprintf(stderr, "No graph for function '%s' found\n",
+ dumpfunction);
+ return EXIT_FAILURE;
+ }
+
+ dump_ir_graph_file(out, irg);
+ fclose(out);
+ return EXIT_SUCCESS;
+ }
+
+ if (mode == CompileExportIR) {
+ ir_export_file(out);
+ if (ferror(out) != 0) {
+ fprintf(stderr, "Error while writing to output\n");
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+ }
+
+ FILE *asm_out;
+ if (mode == Compile) {
+ asm_out = out;
+ } else {
+ asm_out = make_temp_file("ccs", &unit->name);
+ }
+ ir_timer_t *t_opt_codegen = ir_timer_new();
+ timer_register(t_opt_codegen, "Optimization and Codegeneration");
+ timer_start(t_opt_codegen);
+ generate_code(asm_out, inputname);
+ timer_stop(t_opt_codegen);
+ if (stat_ev_enabled) {
+ stat_ev_dbl("time_opt_codegen", ir_timer_elapsed_sec(t_opt_codegen));
+ }
+ if (asm_out != out) {
+ fclose(asm_out);
+ }
+ unit->type = COMPILATION_UNIT_PREPROCESSED_ASSEMBLER;
+ goto again;
+ case COMPILATION_UNIT_PREPROCESSED_ASSEMBLER:
+ if (mode != CompileAssemble && mode != CompileAssembleLink)
+ break;
+
+ /* assemble */
+ const char *input = unit->name;
+ if (mode == CompileAssemble) {
+ fclose(out);
+ unit->name = outname;
+ } else {
+ FILE *tempf = make_temp_file("cco", &unit->name);
+ /* hackish... */
+ fclose(tempf);
+ }
+
+ assemble(unit->name, input);
+
+ unit->type = COMPILATION_UNIT_OBJECT;
+ goto again;
+ case COMPILATION_UNIT_UNKNOWN:
+ case COMPILATION_UNIT_AUTODETECT:
+ case COMPILATION_UNIT_OBJECT:
+ break;
+ }
+
+ stat_ev_ctx_pop("compilation_unit");
+ }
+ return result;
+}
+
+static int link_program(compilation_unit_t *units)
+{
+ obstack_1grow(&ldflags_obst, '\0');
+ const char *flags = obstack_finish(&ldflags_obst);
+
+ /* construct commandline */
+ const char *linker = getenv("CPARSER_LINK");
+ if (linker != NULL) {
+ obstack_printf(&file_obst, "%s ", linker);
+ } else {
+ if (target_triple != NULL)
+ obstack_printf(&file_obst, "%s-", target_triple);
+ obstack_printf(&file_obst, "%s ", LINKER);
+ }
+
+ for (compilation_unit_t *unit = units; unit != NULL; unit = unit->next) {
+ if (unit->type != COMPILATION_UNIT_OBJECT)
+ continue;
+
+ add_flag(&file_obst, "%s", unit->name);
+ }
+
+ add_flag(&file_obst, "-o");
+ add_flag(&file_obst, outname);
+ obstack_printf(&file_obst, "%s", flags);
+ obstack_1grow(&file_obst, '\0');
+
+ char *commandline = obstack_finish(&file_obst);
+
+ if (verbose) {
+ puts(commandline);
+ }
+ int err = system(commandline);
+ if (err != EXIT_SUCCESS) {
+ fprintf(stderr, "linker reported an error\n");
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+}
+
+int main(int argc, char **argv)
+{
+ const char *print_file_name_file = NULL;
+ compile_mode_t mode = CompileAssembleLink;
+ int opt_level = 1;
+ char cpu_arch[16] = "ia32";
+ compilation_unit_t *units = NULL;
+ compilation_unit_t *last_unit = NULL;
+ bool construct_dep_target = false;
+ bool produce_statev = false;
+ const char *filtev = NULL;
+ bool profile_generate = false;
+ bool profile_use = false;
+ bool do_timing = false;
+ bool print_timing = false;