From 2502cb242a0da5112c2cf9b0974ffd68aa27ecc8 Mon Sep 17 00:00:00 2001 From: Noam Preil Date: Sun, 9 Feb 2020 19:52:50 -0500 Subject: Improve support for generating LLVM IR/asm files --- lib/std/build.zig | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'lib/std') diff --git a/lib/std/build.zig b/lib/std/build.zig index 6cab29eb41..d81b660a5b 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1155,6 +1155,9 @@ pub const LibExeObjStep = struct { frameworks: BufSet, verbose_link: bool, verbose_cc: bool, + produce_ir: bool, + produce_asm: bool, + produce_bin: bool, disable_gen_h: bool, bundle_compiler_rt: bool, disable_stack_probing: bool, @@ -1285,6 +1288,9 @@ pub const LibExeObjStep = struct { .builder = builder, .verbose_link = false, .verbose_cc = false, + .produce_ir = false, + .produce_asm = false, + .produce_bin = true, .build_mode = builtin.Mode.Debug, .is_dynamic = is_dynamic, .kind = kind, @@ -1941,6 +1947,10 @@ pub const LibExeObjStep = struct { if (builder.verbose_link or self.verbose_link) zig_args.append("--verbose-link") catch unreachable; if (builder.verbose_cc or self.verbose_cc) zig_args.append("--verbose-cc") catch unreachable; + try zig_args.append(if (self.produce_ir) "-femit-llvm-ir" else "-fno-emit-llvm-ir"); + try zig_args.append(if (self.produce_asm) "-femit-asm" else "-fno-emit-asm"); + try zig_args.append(if (self.produce_bin) "-femit-bin" else "-fno-emit-bin"); + if (self.strip) { try zig_args.append("--strip"); } -- cgit v1.2.3 From dba12cd693495009ae624393337a04e80b0ea565 Mon Sep 17 00:00:00 2001 From: Noam Preil Date: Mon, 10 Feb 2020 00:23:10 -0500 Subject: Rename produce_* bools to emit_* to match CLI --- lib/std/build.zig | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'lib/std') diff --git a/lib/std/build.zig b/lib/std/build.zig index d81b660a5b..38031e2672 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1155,9 +1155,9 @@ pub const LibExeObjStep = struct { frameworks: BufSet, verbose_link: bool, verbose_cc: bool, - produce_ir: bool, - produce_asm: bool, - produce_bin: bool, + emit_ir: bool, + emit_asm: bool, + emit_bin: bool, disable_gen_h: bool, bundle_compiler_rt: bool, disable_stack_probing: bool, @@ -1288,9 +1288,9 @@ pub const LibExeObjStep = struct { .builder = builder, .verbose_link = false, .verbose_cc = false, - .produce_ir = false, - .produce_asm = false, - .produce_bin = true, + .emit_ir = false, + .emit_asm = false, + .emit_bin = true, .build_mode = builtin.Mode.Debug, .is_dynamic = is_dynamic, .kind = kind, @@ -1947,9 +1947,9 @@ pub const LibExeObjStep = struct { if (builder.verbose_link or self.verbose_link) zig_args.append("--verbose-link") catch unreachable; if (builder.verbose_cc or self.verbose_cc) zig_args.append("--verbose-cc") catch unreachable; - try zig_args.append(if (self.produce_ir) "-femit-llvm-ir" else "-fno-emit-llvm-ir"); - try zig_args.append(if (self.produce_asm) "-femit-asm" else "-fno-emit-asm"); - try zig_args.append(if (self.produce_bin) "-femit-bin" else "-fno-emit-bin"); + try zig_args.append(if (self.emit_ir) "-femit-llvm-ir" else "-fno-emit-llvm-ir"); + try zig_args.append(if (self.emit_asm) "-femit-asm" else "-fno-emit-asm"); + try zig_args.append(if (self.emit_bin) "-femit-bin" else "-fno-emit-bin"); if (self.strip) { try zig_args.append("--strip"); -- cgit v1.2.3 From d7968c6d33b054a8293edd89ce248f385e108469 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 18 Feb 2020 21:59:43 -0500 Subject: improvements which allow zig to emit multiple things at once example: zig build-obj test.zig -femit-llvm-ir -femit-asm this will generate all three: test.o test.s test.ll --- lib/std/build.zig | 15 ++++---- src/all_types.hpp | 10 +++--- src/codegen.cpp | 100 ++++++++++++++++++++++++++--------------------------- src/codegen.hpp | 3 -- src/link.cpp | 38 ++++++++++---------- src/main.cpp | 63 +++++++++++++++++----------------- src/zig_llvm.cpp | 101 +++++++++++++++++++++++++++++++----------------------- src/zig_llvm.h | 13 ++----- 8 files changed, 173 insertions(+), 170 deletions(-) (limited to 'lib/std') diff --git a/lib/std/build.zig b/lib/std/build.zig index 38031e2672..5d13a9923a 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1155,9 +1155,9 @@ pub const LibExeObjStep = struct { frameworks: BufSet, verbose_link: bool, verbose_cc: bool, - emit_ir: bool, - emit_asm: bool, - emit_bin: bool, + emit_llvm_ir: bool = false, + emit_asm: bool = false, + emit_bin: bool = true, disable_gen_h: bool, bundle_compiler_rt: bool, disable_stack_probing: bool, @@ -1288,9 +1288,6 @@ pub const LibExeObjStep = struct { .builder = builder, .verbose_link = false, .verbose_cc = false, - .emit_ir = false, - .emit_asm = false, - .emit_bin = true, .build_mode = builtin.Mode.Debug, .is_dynamic = is_dynamic, .kind = kind, @@ -1947,9 +1944,9 @@ pub const LibExeObjStep = struct { if (builder.verbose_link or self.verbose_link) zig_args.append("--verbose-link") catch unreachable; if (builder.verbose_cc or self.verbose_cc) zig_args.append("--verbose-cc") catch unreachable; - try zig_args.append(if (self.emit_ir) "-femit-llvm-ir" else "-fno-emit-llvm-ir"); - try zig_args.append(if (self.emit_asm) "-femit-asm" else "-fno-emit-asm"); - try zig_args.append(if (self.emit_bin) "-femit-bin" else "-fno-emit-bin"); + if (self.emit_llvm_ir) try zig_args.append("-femit-llvm-ir"); + if (self.emit_asm) try zig_args.append("-femit-asm"); + if (!self.emit_bin) try zig_args.append("-fno-emit-bin"); if (self.strip) { try zig_args.append("--strip"); diff --git a/src/all_types.hpp b/src/all_types.hpp index eb57a6e618..c1348d3abd 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -2136,8 +2136,10 @@ struct CodeGen { Buf llvm_triple_str; Buf global_asm; - Buf output_file_path; Buf o_file_output_path; + Buf bin_file_output_path; + Buf asm_file_output_path; + Buf llvm_ir_file_output_path; Buf *cache_dir; // As an input parameter, mutually exclusive with enable_cache. But it gets // populated in codegen_build_and_link. @@ -2198,8 +2200,6 @@ struct CodeGen { bool verbose_cimport; bool verbose_cc; bool verbose_llvm_cpu_features; - bool emit_asm; - bool emit_llvm_ir; bool error_during_imports; bool generate_error_name_table; bool enable_cache; // mutually exclusive with output_dir @@ -2253,7 +2253,9 @@ struct CodeGen { bool function_sections; bool enable_dump_analysis; bool enable_doc_generation; - bool disable_bin_generation; + bool emit_bin; + bool emit_asm; + bool emit_llvm_ir; bool test_is_evented; CodeModel code_model; diff --git a/src/codegen.cpp b/src/codegen.cpp index 84753e1053..a28d2d469d 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -7915,54 +7915,48 @@ static void do_code_gen(CodeGen *g) { } } -void codegen_set_emit_asm(CodeGen *g, bool emit) { - g->emit_asm = emit; -} - -void codegen_set_emit_llvm_ir(CodeGen *g, bool emit) { - g->emit_llvm_ir = emit; -} - static void zig_llvm_emit_output(CodeGen *g) { g->pass1_arena->destruct(&heap::c_allocator); g->pass1_arena = nullptr; bool is_small = g->build_mode == BuildModeSmallRelease; - Buf *output_path = &g->o_file_output_path; char *err_msg = nullptr; - if (!g->disable_bin_generation) { - if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), - ZigLLVM_EmitBinary, &err_msg, g->build_mode == BuildModeDebug, is_small, - g->enable_time_report)) - { - zig_panic("unable to write object file %s: %s", buf_ptr(output_path), err_msg); - } - validate_inline_fns(g); - g->link_objects.append(output_path); - if (g->bundle_compiler_rt && (g->out_type == OutTypeObj || - (g->out_type == OutTypeLib && !g->is_dynamic))) + const char *asm_filename = nullptr; + const char *bin_filename = nullptr; + const char *llvm_ir_filename = nullptr; + + if (g->emit_bin) bin_filename = buf_ptr(&g->o_file_output_path); + if (g->emit_asm) asm_filename = buf_ptr(&g->asm_file_output_path); + if (g->emit_llvm_ir) llvm_ir_filename = buf_ptr(&g->llvm_ir_file_output_path); + + // Unfortunately, LLVM shits the bed when we ask for both binary and assembly. So we call the entire + // pipeline multiple times if this is requested. + if (asm_filename != nullptr && bin_filename != nullptr) { + if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, &err_msg, g->build_mode == BuildModeDebug, + is_small, g->enable_time_report, nullptr, bin_filename, llvm_ir_filename)) { - zig_link_add_compiler_rt(g, g->sub_progress_node); + fprintf(stderr, "LLVM failed to emit file: %s\n", err_msg); + exit(1); } + bin_filename = nullptr; + llvm_ir_filename = nullptr; } - if (g->emit_asm) { - if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), - ZigLLVM_EmitAssembly, &err_msg, g->build_mode == BuildModeDebug, is_small, - g->enable_time_report)) - { - zig_panic("unable to write assembly file %s: %s", buf_ptr(output_path), err_msg); - } - validate_inline_fns(g); + + if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, &err_msg, g->build_mode == BuildModeDebug, + is_small, g->enable_time_report, asm_filename, bin_filename, llvm_ir_filename)) + { + fprintf(stderr, "LLVM failed to emit file: %s\n", err_msg); + exit(1); } - if (g->emit_llvm_ir) { - if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), - ZigLLVM_EmitLLVMIr, &err_msg, g->build_mode == BuildModeDebug, is_small, - g->enable_time_report)) - { - zig_panic("unable to write llvm-ir file %s: %s", buf_ptr(output_path), err_msg); + + validate_inline_fns(g); + + if (g->emit_bin) { + g->link_objects.append(&g->o_file_output_path); + if (g->bundle_compiler_rt && (g->out_type == OutTypeObj || (g->out_type == OutTypeLib && !g->is_dynamic))) { + zig_link_add_compiler_rt(g, g->sub_progress_node); } - validate_inline_fns(g); } LLVMDisposeModule(g->module); @@ -10446,7 +10440,9 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { cache_bool(ch, g->function_sections); cache_bool(ch, g->enable_dump_analysis); cache_bool(ch, g->enable_doc_generation); - cache_bool(ch, g->disable_bin_generation); + cache_bool(ch, g->emit_bin); + cache_bool(ch, g->emit_llvm_ir); + cache_bool(ch, g->emit_asm); cache_buf_opt(ch, g->mmacosx_version_min); cache_buf_opt(ch, g->mios_version_min); cache_usize(ch, g->version_major); @@ -10491,15 +10487,15 @@ static void resolve_out_paths(CodeGen *g) { assert(g->output_dir != nullptr); assert(g->root_out_name != nullptr); - Buf *out_basename = buf_create_from_buf(g->root_out_name); - Buf *o_basename = buf_create_from_buf(g->root_out_name); - if (!g->disable_bin_generation) { + if (g->emit_bin) { + Buf *out_basename = buf_create_from_buf(g->root_out_name); + Buf *o_basename = buf_create_from_buf(g->root_out_name); switch (g->out_type) { case OutTypeUnknown: zig_unreachable(); case OutTypeObj: if (g->enable_cache && g->link_objects.length == 1 && !need_llvm_module(g)) { - buf_init_from_buf(&g->output_file_path, g->link_objects.at(0)); + buf_init_from_buf(&g->bin_file_output_path, g->link_objects.at(0)); return; } if (need_llvm_module(g) && g->link_objects.length != 0 && !g->enable_cache && @@ -10524,20 +10520,21 @@ static void resolve_out_paths(CodeGen *g) { g->version_major, g->version_minor, g->version_patch)); break; } + os_path_join(g->output_dir, o_basename, &g->o_file_output_path); + os_path_join(g->output_dir, out_basename, &g->bin_file_output_path); } - else if (g->emit_asm) { + if (g->emit_asm) { + Buf *asm_basename = buf_create_from_buf(g->root_out_name); const char *asm_ext = target_asm_file_ext(g->zig_target); - buf_append_str(o_basename, asm_ext); - buf_append_str(out_basename, asm_ext); + buf_append_str(asm_basename, asm_ext); + os_path_join(g->output_dir, asm_basename, &g->asm_file_output_path); } - else if (g->emit_llvm_ir) { + if (g->emit_llvm_ir) { + Buf *llvm_ir_basename = buf_create_from_buf(g->root_out_name); const char *llvm_ir_ext = target_llvm_ir_file_ext(g->zig_target); - buf_append_str(o_basename, llvm_ir_ext); - buf_append_str(out_basename, llvm_ir_ext); + buf_append_str(llvm_ir_basename, llvm_ir_ext); + os_path_join(g->output_dir, llvm_ir_basename, &g->llvm_ir_file_output_path); } - - os_path_join(g->output_dir, o_basename, &g->o_file_output_path); - os_path_join(g->output_dir, out_basename, &g->output_file_path); } void codegen_build_and_link(CodeGen *g) { @@ -10699,7 +10696,7 @@ void codegen_build_and_link(CodeGen *g) { // If there is more than one object, we have to link them (with -r). // Finally, if we didn't make an object from zig source, and we don't have caching enabled, // then we have an object from C source that we must copy to the output dir which we do with a -r link. - if (!g->disable_bin_generation && + if (g->emit_bin && (g->out_type != OutTypeObj || g->link_objects.length > 1 || (!need_llvm_module(g) && !g->enable_cache))) { @@ -10777,6 +10774,7 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget Stage2LibCInstallation *libc, Buf *cache_dir, bool is_test_build, Stage2ProgressNode *progress_node) { CodeGen *g = heap::c_allocator.create(); + g->emit_bin = true; g->pass1_arena = heap::ArenaAllocator::construct(&heap::c_allocator, &heap::c_allocator, "pass1"); g->main_progress_node = progress_node; diff --git a/src/codegen.hpp b/src/codegen.hpp index 1e99cf220f..6329c59a5e 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -26,9 +26,6 @@ void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len); void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len); void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath); -void codegen_set_emit_asm(CodeGen *codegen, bool emit); -void codegen_set_emit_llvm_ir(CodeGen *codegen, bool emit); - void codegen_set_strip(CodeGen *codegen, bool strip); void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color); void codegen_set_out_name(CodeGen *codegen, Buf *out_name); diff --git a/src/link.cpp b/src/link.cpp index 8b31b2519e..901390feae 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -605,7 +605,7 @@ static const char *build_libc_object(CodeGen *parent_gen, const char *name, CFil c_source_files.append(c_file); child_gen->c_source_files = c_source_files; codegen_build_and_link(child_gen); - return buf_ptr(&child_gen->output_file_path); + return buf_ptr(&child_gen->bin_file_output_path); } static const char *path_from_zig_lib(CodeGen *g, const char *dir, const char *subpath) { @@ -682,7 +682,7 @@ static const char *build_libunwind(CodeGen *parent, Stage2ProgressNode *progress } child_gen->c_source_files = c_source_files; codegen_build_and_link(child_gen); - return buf_ptr(&child_gen->output_file_path); + return buf_ptr(&child_gen->bin_file_output_path); } static void mingw_add_cc_args(CodeGen *parent, CFile *c_file) { @@ -1123,7 +1123,7 @@ static const char *build_musl(CodeGen *parent, Stage2ProgressNode *progress_node child_gen->c_source_files = c_source_files; codegen_build_and_link(child_gen); - return buf_ptr(&child_gen->output_file_path); + return buf_ptr(&child_gen->bin_file_output_path); } static void add_msvcrt_os_dep(CodeGen *parent, CodeGen *child_gen, const char *src_path) { @@ -1253,7 +1253,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr child_gen->c_source_files.append(c_file); } codegen_build_and_link(child_gen); - return buf_ptr(&child_gen->output_file_path); + return buf_ptr(&child_gen->bin_file_output_path); } else if (strcmp(file, "msvcrt-os.lib") == 0) { CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "msvcrt-os", progress_node); @@ -1270,7 +1270,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr } } codegen_build_and_link(child_gen); - return buf_ptr(&child_gen->output_file_path); + return buf_ptr(&child_gen->bin_file_output_path); } else if (strcmp(file, "mingwex.lib") == 0) { CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "mingwex", progress_node); @@ -1295,7 +1295,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr zig_unreachable(); } codegen_build_and_link(child_gen); - return buf_ptr(&child_gen->output_file_path); + return buf_ptr(&child_gen->bin_file_output_path); } else { zig_unreachable(); } @@ -1365,7 +1365,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr codegen_add_object(child_gen, buf_create_from_str(start_os)); codegen_add_object(child_gen, buf_create_from_str(abi_note_o)); codegen_build_and_link(child_gen); - return buf_ptr(&child_gen->output_file_path); + return buf_ptr(&child_gen->bin_file_output_path); } else if (strcmp(file, "libc_nonshared.a") == 0) { CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "c_nonshared", progress_node); { @@ -1445,7 +1445,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr build_libc_object(parent, deps[i].name, c_file, progress_node))); } codegen_build_and_link(child_gen); - return buf_ptr(&child_gen->output_file_path); + return buf_ptr(&child_gen->bin_file_output_path); } else { zig_unreachable(); } @@ -1519,7 +1519,7 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path, child_gen->want_stack_check = WantStackCheckDisabled; codegen_build_and_link(child_gen); - return &child_gen->output_file_path; + return &child_gen->bin_file_output_path; } static Buf *build_compiler_rt(CodeGen *parent_gen, OutType child_out_type, Stage2ProgressNode *progress_node) { @@ -1681,7 +1681,7 @@ static void construct_linker_job_elf(LinkJob *lj) { } else if (is_dyn_lib) { lj->args.append("-shared"); - assert(buf_len(&g->output_file_path) != 0); + assert(buf_len(&g->bin_file_output_path) != 0); soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize, buf_ptr(g->root_out_name), g->version_major); } @@ -1690,7 +1690,7 @@ static void construct_linker_job_elf(LinkJob *lj) { } lj->args.append("-o"); - lj->args.append(buf_ptr(&g->output_file_path)); + lj->args.append(buf_ptr(&g->bin_file_output_path)); if (lj->link_in_crt) { const char *crt1o; @@ -1872,7 +1872,7 @@ static void construct_linker_job_wasm(LinkJob *lj) { } lj->args.append("--allow-undefined"); lj->args.append("-o"); - lj->args.append(buf_ptr(&g->output_file_path)); + lj->args.append(buf_ptr(&g->bin_file_output_path)); // .o files for (size_t i = 0; i < g->link_objects.length; i += 1) { @@ -2248,7 +2248,7 @@ static void construct_linker_job_coff(LinkJob *lj) { lj->args.append("-DLL"); } - lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path)))); + lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->bin_file_output_path)))); if (g->libc_link_lib != nullptr && g->libc != nullptr) { lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->crt_dir))); @@ -2501,7 +2501,7 @@ static void construct_linker_job_macho(LinkJob *lj) { //lj->args.append("-install_name"); //lj->args.append(buf_ptr(dylib_install_name)); - assert(buf_len(&g->output_file_path) != 0); + assert(buf_len(&g->bin_file_output_path) != 0); } lj->args.append("-arch"); @@ -2532,14 +2532,14 @@ static void construct_linker_job_macho(LinkJob *lj) { } lj->args.append("-o"); - lj->args.append(buf_ptr(&g->output_file_path)); + lj->args.append(buf_ptr(&g->bin_file_output_path)); for (size_t i = 0; i < g->rpath_list.length; i += 1) { Buf *rpath = g->rpath_list.at(i); add_rpath(lj, rpath); } if (is_dyn_lib) { - add_rpath(lj, &g->output_file_path); + add_rpath(lj, &g->bin_file_output_path); } if (is_dyn_lib) { @@ -2659,14 +2659,14 @@ void codegen_link(CodeGen *g) { progress_name, strlen(progress_name), 0)); } if (g->verbose_link) { - fprintf(stderr, "ar rcs %s", buf_ptr(&g->output_file_path)); + fprintf(stderr, "ar rcs %s", buf_ptr(&g->bin_file_output_path)); for (size_t i = 0; i < file_names.length; i += 1) { fprintf(stderr, " %s", file_names.at(i)); } fprintf(stderr, "\n"); } - if (ZigLLVMWriteArchive(buf_ptr(&g->output_file_path), file_names.items, file_names.length, os_type)) { - fprintf(stderr, "Unable to write archive '%s'\n", buf_ptr(&g->output_file_path)); + if (ZigLLVMWriteArchive(buf_ptr(&g->bin_file_output_path), file_names.items, file_names.length, os_type)) { + fprintf(stderr, "Unable to write archive '%s'\n", buf_ptr(&g->bin_file_output_path)); exit(1); } return; diff --git a/src/main.cpp b/src/main.cpp index c8c2f1b4a2..5117348e34 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -62,17 +62,21 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { " -fno-stack-check disable stack probing in safe builds\n" " -fsanitize-c enable C undefined behavior detection in unsafe builds\n" " -fno-sanitize-c disable C undefined behavior detection in safe builds\n" - " --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n" + " --emit [asm|bin|llvm-ir] (deprecated) emit a specific file format as compilation output\n" " -fPIC enable Position Independent Code\n" " -fno-PIC disable Position Independent Code\n" " -ftime-report print timing diagnostics\n" " -fstack-report print stack size diagnostics\n" -#ifdef ZIG_ENABLE_MEM_PROFILE " -fmem-report print memory usage diagnostics\n" -#endif " -fdump-analysis write analysis.json file with type information\n" " -femit-docs create a docs/ dir with html documentation\n" - " -fno-emit-bin skip emitting machine code\n" + " -fno-emit-docs do not produce docs/ dir with html documentation\n" + " -femit-bin (default) output machine code\n" + " -fno-emit-bin do not output machine code\n" + " -femit-asm output .s (assembly code)\n" + " -fno-emit-asm (default) do not output .s (assembly code)\n" + " -femit-llvm-ir produce a .ll file with LLVM IR\n" + " -fno-emit-llvm-ir (default) do not produce a .ll file with LLVM IR\n" " --libc [file] Provide a file which specifies libc paths\n" " --name [name] override output name\n" " --output-dir [dir] override output directory (defaults to cwd)\n" @@ -423,7 +427,7 @@ static int main0(int argc, char **argv) { bool stack_report = false; bool enable_dump_analysis = false; bool enable_doc_generation = false; - bool disable_bin_generation = false; + bool emit_bin = true; bool emit_asm = false; bool emit_llvm_ir = false; const char *cache_dir = nullptr; @@ -553,7 +557,7 @@ static int main0(int argc, char **argv) { } Termination term; - args.items[0] = buf_ptr(&g->output_file_path); + args.items[0] = buf_ptr(&g->bin_file_output_path); os_spawn_process(args, &term); if (term.how != TerminationIdClean || term.code != 0) { fprintf(stderr, "\nBuild failed. The following command failed:\n"); @@ -632,8 +636,6 @@ static int main0(int argc, char **argv) { enable_dump_analysis = true; } else if (strcmp(arg, "-femit-docs") == 0) { enable_doc_generation = true; - } else if (strcmp(arg, "-fno-emit-bin") == 0) { - disable_bin_generation = true; } else if (strcmp(arg, "--enable-valgrind") == 0) { valgrind_support = ValgrindSupportEnabled; } else if (strcmp(arg, "--disable-valgrind") == 0) { @@ -703,9 +705,9 @@ static int main0(int argc, char **argv) { } else if (strcmp(arg, "--test-evented-io") == 0) { test_evented_io = true; } else if (strcmp(arg, "-femit-bin") == 0) { - disable_bin_generation = false; + emit_bin = true; } else if (strcmp(arg, "-fno-emit-bin") == 0) { - disable_bin_generation = true; + emit_bin = false; } else if (strcmp(arg, "-femit-asm") == 0) { emit_asm = true; } else if (strcmp(arg, "-fno-emit-asm") == 0) { @@ -746,12 +748,12 @@ static int main0(int argc, char **argv) { } else if (strcmp(arg, "--emit") == 0) { if (strcmp(argv[i], "asm") == 0) { emit_asm = true; - disable_bin_generation = true; + emit_bin = false; } else if (strcmp(argv[i], "bin") == 0) { - disable_bin_generation = false; + emit_bin = true; } else if (strcmp(argv[i], "llvm-ir") == 0) { emit_llvm_ir = true; - disable_bin_generation = true; + emit_bin = false; } else { fprintf(stderr, "--emit options are 'asm', 'bin', or 'llvm-ir'\n"); return print_error_usage(arg0); @@ -1113,8 +1115,8 @@ static int main0(int argc, char **argv) { { fprintf(stderr, "Expected source file argument.\n"); return print_error_usage(arg0); - } else if (cmd == CmdRun && disable_bin_generation) { - fprintf(stderr, "Cannot run non-executable file.\n"); + } else if (cmd == CmdRun && !emit_bin) { + fprintf(stderr, "Cannot run without emitting a binary file.\n"); return print_error_usage(arg0); } @@ -1191,7 +1193,10 @@ static int main0(int argc, char **argv) { g->enable_stack_report = stack_report; g->enable_dump_analysis = enable_dump_analysis; g->enable_doc_generation = enable_doc_generation; - g->disable_bin_generation = disable_bin_generation; + g->emit_bin = emit_bin; + g->emit_asm = emit_asm; + g->emit_llvm_ir = emit_llvm_ir; + codegen_set_out_name(g, buf_out_name); codegen_set_lib_version(g, ver_major, ver_minor, ver_patch); g->want_single_threaded = want_single_threaded; @@ -1277,9 +1282,6 @@ static int main0(int argc, char **argv) { if (cmd == CmdBuild || cmd == CmdRun) { - codegen_set_emit_asm(g, emit_asm); - codegen_set_emit_llvm_ir(g, emit_llvm_ir); - g->enable_cache = get_cache_opt(enable_cache, cmd == CmdRun); codegen_build_and_link(g); if (root_progress_node != nullptr) { @@ -1297,7 +1299,7 @@ static int main0(int argc, char **argv) { mem::print_report(); #endif - const char *exec_path = buf_ptr(&g->output_file_path); + const char *exec_path = buf_ptr(&g->bin_file_output_path); ZigList args = {0}; args.append(exec_path); @@ -1317,21 +1319,21 @@ static int main0(int argc, char **argv) { } else if (cmd == CmdBuild) { if (g->enable_cache) { #if defined(ZIG_OS_WINDOWS) - buf_replace(&g->output_file_path, '/', '\\'); + buf_replace(&g->bin_file_output_path, '/', '\\'); #endif if (final_output_dir_step != nullptr) { Buf *dest_basename = buf_alloc(); - os_path_split(&g->output_file_path, nullptr, dest_basename); + os_path_split(&g->bin_file_output_path, nullptr, dest_basename); Buf *dest_path = buf_alloc(); os_path_join(final_output_dir_step, dest_basename, dest_path); - if ((err = os_update_file(&g->output_file_path, dest_path))) { - fprintf(stderr, "unable to copy %s to %s: %s\n", buf_ptr(&g->output_file_path), + if ((err = os_update_file(&g->bin_file_output_path, dest_path))) { + fprintf(stderr, "unable to copy %s to %s: %s\n", buf_ptr(&g->bin_file_output_path), buf_ptr(dest_path), err_str(err)); return main_exit(root_progress_node, EXIT_FAILURE); } } else { - if (printf("%s\n", buf_ptr(&g->output_file_path)) < 0) + if (printf("%s\n", buf_ptr(&g->bin_file_output_path)) < 0) return main_exit(root_progress_node, EXIT_FAILURE); } } @@ -1346,9 +1348,6 @@ static int main0(int argc, char **argv) { codegen_print_timing_report(g, stderr); return main_exit(root_progress_node, EXIT_SUCCESS); } else if (cmd == CmdTest) { - codegen_set_emit_asm(g, emit_asm); - codegen_set_emit_llvm_ir(g, emit_llvm_ir); - ZigTarget native; get_native_target(&native); @@ -1367,17 +1366,17 @@ static int main0(int argc, char **argv) { zig_print_stack_report(g, stdout); } - if (g->disable_bin_generation) { + if (!g->emit_bin) { fprintf(stderr, "Semantic analysis complete. No binary produced due to -fno-emit-bin.\n"); return main_exit(root_progress_node, EXIT_SUCCESS); } - Buf *test_exe_path_unresolved = &g->output_file_path; + Buf *test_exe_path_unresolved = &g->bin_file_output_path; Buf *test_exe_path = buf_alloc(); *test_exe_path = os_path_resolve(&test_exe_path_unresolved, 1); - if (disable_bin_generation) { - fprintf(stderr, "Created %s but skipping execution because it is non executable.\n", + if (!g->emit_bin) { + fprintf(stderr, "Created %s but skipping execution because no binary generated.\n", buf_ptr(test_exe_path)); return main_exit(root_progress_node, EXIT_SUCCESS); } diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index 614d31dc5a..64706500d5 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -161,17 +161,32 @@ unsigned ZigLLVMDataLayoutGetProgramAddressSpace(LLVMTargetDataRef TD) { } bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref, - const char *filename, ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug, - bool is_small, bool time_report) + char **error_message, bool is_debug, + bool is_small, bool time_report, + const char *asm_filename, const char *bin_filename, const char *llvm_ir_filename) { TimePassesIsEnabled = time_report; - std::error_code EC; - raw_fd_ostream dest(filename, EC, sys::fs::F_None); - if (EC) { - *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin()); - return true; + raw_fd_ostream *dest_asm = nullptr; + raw_fd_ostream *dest_bin = nullptr; + + if (asm_filename) { + std::error_code EC; + dest_asm = new(std::nothrow) raw_fd_ostream(asm_filename, EC, sys::fs::F_None); + if (EC) { + *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin()); + return true; + } } + if (bin_filename) { + std::error_code EC; + dest_bin = new(std::nothrow) raw_fd_ostream(bin_filename, EC, sys::fs::F_None); + if (EC) { + *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin()); + return true; + } + } + TargetMachine* target_machine = reinterpret_cast(targ_machine_ref); target_machine->setO0WantsFastISel(true); @@ -222,49 +237,51 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM } PMBuilder->populateFunctionPassManager(FPM); - // Set up the per-module pass manager. - legacy::PassManager MPM; - MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis())); - PMBuilder->populateModulePassManager(MPM); - - // Set output pass. - TargetMachine::CodeGenFileType ft; - if (output_type != ZigLLVM_EmitLLVMIr) { - switch (output_type) { - case ZigLLVM_EmitAssembly: - ft = TargetMachine::CGFT_AssemblyFile; - break; - case ZigLLVM_EmitBinary: - ft = TargetMachine::CGFT_ObjectFile; - break; - default: - abort(); + { + // Set up the per-module pass manager. + legacy::PassManager MPM; + MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis())); + PMBuilder->populateModulePassManager(MPM); + + // Set output passes. + if (dest_bin) { + if (target_machine->addPassesToEmitFile(MPM, *dest_bin, nullptr, TargetMachine::CGFT_ObjectFile)) { + *error_message = strdup("TargetMachine can't emit an object file"); + return true; + } } - - if (target_machine->addPassesToEmitFile(MPM, dest, nullptr, ft)) { - *error_message = strdup("TargetMachine can't emit a file of this type"); - return true; + if (dest_asm) { + if (target_machine->addPassesToEmitFile(MPM, *dest_asm, nullptr, TargetMachine::CGFT_AssemblyFile)) { + *error_message = strdup("TargetMachine can't emit an assembly file"); + return true; + } } - } - // run per function optimization passes - FPM.doInitialization(); - for (Function &F : *module) - if (!F.isDeclaration()) - FPM.run(F); - FPM.doFinalization(); + // run per function optimization passes + FPM.doInitialization(); + for (Function &F : *module) + if (!F.isDeclaration()) + FPM.run(F); + FPM.doFinalization(); - MPM.run(*module); + MPM.run(*module); - if (output_type == ZigLLVM_EmitLLVMIr) { - if (LLVMPrintModuleToFile(module_ref, filename, error_message)) { - return true; + if (llvm_ir_filename) { + if (LLVMPrintModuleToFile(module_ref, llvm_ir_filename, error_message)) { + return true; + } } - } - if (time_report) { - TimerGroup::printAll(errs()); + if (time_report) { + TimerGroup::printAll(errs()); + } + + // MPM goes out of scope and writes to the out streams } + + delete dest_asm; + delete dest_bin; + return false; } diff --git a/src/zig_llvm.h b/src/zig_llvm.h index ba9816b4f8..95751cd08a 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -46,17 +46,10 @@ ZIG_EXTERN_C void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R); ZIG_EXTERN_C char *ZigLLVMGetHostCPUName(void); ZIG_EXTERN_C char *ZigLLVMGetNativeFeatures(void); -// We use a custom enum here since LLVM does not expose LLVMIr as an emit -// output through the same mechanism as assembly/binary. -enum ZigLLVM_EmitOutputType { - ZigLLVM_EmitAssembly, - ZigLLVM_EmitBinary, - ZigLLVM_EmitLLVMIr, -}; - ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref, - const char *filename, enum ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug, - bool is_small, bool time_report); + char **error_message, bool is_debug, + bool is_small, bool time_report, + const char *asm_filename, const char *bin_filename, const char *llvm_ir_filename); ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Triple, const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, -- cgit v1.2.3