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"); } diff --git a/src/all_types.hpp b/src/all_types.hpp index fbe24c918b..eb57a6e618 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1966,12 +1966,6 @@ enum CodeModel { CodeModelLarge, }; -enum EmitFileType { - EmitFileTypeBinary, - EmitFileTypeAssembly, - EmitFileTypeLLVMIr, -}; - struct LinkLib { Buf *name; Buf *path; @@ -2204,6 +2198,8 @@ 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 @@ -2236,7 +2232,6 @@ struct CodeGen { size_t version_patch; const char *linker_script; - EmitFileType emit_file_type; BuildMode build_mode; OutType out_type; const ZigTarget *zig_target; diff --git a/src/codegen.cpp b/src/codegen.cpp index 41a353ef14..84753e1053 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -121,10 +121,6 @@ void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patc g->version_patch = patch; } -void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type) { - g->emit_file_type = emit_file_type; -} - void codegen_set_each_lib_rpath(CodeGen *g, bool each_lib_rpath) { g->each_lib_rpath = each_lib_rpath; } @@ -7919,6 +7915,14 @@ 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; @@ -7927,48 +7931,40 @@ static void zig_llvm_emit_output(CodeGen *g) { Buf *output_path = &g->o_file_output_path; char *err_msg = nullptr; - switch (g->emit_file_type) { - case EmitFileTypeBinary: - if (g->disable_bin_generation) - return; - 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))) - { - zig_link_add_compiler_rt(g, g->sub_progress_node); - } - break; - - case EmitFileTypeAssembly: - 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); - break; - - case EmitFileTypeLLVMIr: - 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); - break; - - default: - zig_unreachable(); + 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))) + { + zig_link_add_compiler_rt(g, g->sub_progress_node); + } } + 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 (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); + } + LLVMDisposeModule(g->module); g->module = nullptr; LLVMDisposeTargetData(g->target_data_ref); @@ -10497,53 +10493,48 @@ static void resolve_out_paths(CodeGen *g) { Buf *out_basename = buf_create_from_buf(g->root_out_name); Buf *o_basename = buf_create_from_buf(g->root_out_name); - switch (g->emit_file_type) { - case EmitFileTypeBinary: { - 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)); - return; - } - if (need_llvm_module(g) && g->link_objects.length != 0 && !g->enable_cache && - buf_eql_buf(o_basename, out_basename)) - { - // make it not collide with main output object - buf_append_str(o_basename, ".root"); - } - buf_append_str(o_basename, target_o_file_ext(g->zig_target)); - buf_append_str(out_basename, target_o_file_ext(g->zig_target)); - break; - case OutTypeExe: - buf_append_str(o_basename, target_o_file_ext(g->zig_target)); - buf_append_str(out_basename, target_exe_file_ext(g->zig_target)); - break; - case OutTypeLib: - buf_append_str(o_basename, target_o_file_ext(g->zig_target)); - buf_resize(out_basename, 0); - buf_append_str(out_basename, target_lib_file_prefix(g->zig_target)); - buf_append_buf(out_basename, g->root_out_name); - buf_append_str(out_basename, target_lib_file_ext(g->zig_target, !g->is_dynamic, - g->version_major, g->version_minor, g->version_patch)); - break; - } - break; - } - case EmitFileTypeAssembly: { - 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); - break; - } - case EmitFileTypeLLVMIr: { - 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); - break; + if (!g->disable_bin_generation) { + 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)); + return; + } + if (need_llvm_module(g) && g->link_objects.length != 0 && !g->enable_cache && + buf_eql_buf(o_basename, out_basename)) + { + // make it not collide with main output object + buf_append_str(o_basename, ".root"); + } + buf_append_str(o_basename, target_o_file_ext(g->zig_target)); + buf_append_str(out_basename, target_o_file_ext(g->zig_target)); + break; + case OutTypeExe: + buf_append_str(o_basename, target_o_file_ext(g->zig_target)); + buf_append_str(out_basename, target_exe_file_ext(g->zig_target)); + break; + case OutTypeLib: + buf_append_str(o_basename, target_o_file_ext(g->zig_target)); + buf_resize(out_basename, 0); + buf_append_str(out_basename, target_lib_file_prefix(g->zig_target)); + buf_append_buf(out_basename, g->root_out_name); + buf_append_str(out_basename, target_lib_file_ext(g->zig_target, !g->is_dynamic, + g->version_major, g->version_minor, g->version_patch)); + break; } } + else if (g->emit_asm) { + 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); + } + else if (g->emit_llvm_ir) { + 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); + } 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); @@ -10708,7 +10699,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 && g->emit_file_type == EmitFileTypeBinary && + if (!g->disable_bin_generation && (g->out_type != OutTypeObj || g->link_objects.length > 1 || (!need_llvm_module(g) && !g->enable_cache))) { diff --git a/src/codegen.hpp b/src/codegen.hpp index f8be29494a..1e99cf220f 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -26,7 +26,9 @@ 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_file_type(CodeGen *g, EmitFileType emit_file_type); +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/main.cpp b/src/main.cpp index cbaf6aeb70..2a279e80ac 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -376,7 +376,6 @@ static int main0(int argc, char **argv) { } Cmd cmd = CmdNone; - EmitFileType emit_file_type = EmitFileTypeBinary; const char *in_file = nullptr; Buf *output_dir = nullptr; bool strip = false; @@ -425,6 +424,8 @@ static int main0(int argc, char **argv) { bool enable_dump_analysis = false; bool enable_doc_generation = false; bool disable_bin_generation = false; + bool emit_asm = false; + bool emit_llvm_ir = false; const char *cache_dir = nullptr; CliPkg *cur_pkg = heap::c_allocator.create(); BuildMode build_mode = BuildModeDebug; @@ -701,6 +702,18 @@ static int main0(int argc, char **argv) { function_sections = true; } else if (strcmp(arg, "--test-evented-io") == 0) { test_evented_io = true; + } else if (strcmp(arg, "-femit-bin") == 0) { + disable_bin_generation = false; + } else if (strcmp(arg, "-fno-emit-bin") == 0) { + disable_bin_generation = true; + } else if (strcmp(arg, "-femit-asm") == 0) { + emit_asm = true; + } else if (strcmp(arg, "-fno-emit-asm") == 0) { + emit_asm = false; + } else if (strcmp(arg, "-femit-llvm-ir") == 0) { + emit_llvm_ir = true; + } else if (strcmp(arg, "-fno-emit-llvm-ir") == 0) { + emit_llvm_ir = false; } else if (i + 1 >= argc) { fprintf(stderr, "Expected another argument after %s\n", arg); return print_error_usage(arg0); @@ -732,11 +745,11 @@ static int main0(int argc, char **argv) { } } else if (strcmp(arg, "--emit") == 0) { if (strcmp(argv[i], "asm") == 0) { - emit_file_type = EmitFileTypeAssembly; + emit_asm = true; } else if (strcmp(argv[i], "bin") == 0) { - emit_file_type = EmitFileTypeBinary; + disable_bin_generation = false; } else if (strcmp(argv[i], "llvm-ir") == 0) { - emit_file_type = EmitFileTypeLLVMIr; + emit_llvm_ir = true; } else { fprintf(stderr, "--emit options are 'asm', 'bin', or 'llvm-ir'\n"); return print_error_usage(arg0); @@ -1026,8 +1039,8 @@ static int main0(int argc, char **argv) { return print_error_usage(arg0); } - if (emit_file_type != EmitFileTypeBinary && in_file == nullptr) { - fprintf(stderr, "A root source file is required when using `--emit asm` or `--emit llvm-ir`\n"); + if ((emit_asm || emit_llvm_ir) && in_file == nullptr) { + fprintf(stderr, "A root source file is required when using `-femit-asm` or `-femit-llvm-ir`\n"); return print_error_usage(arg0); } @@ -1098,7 +1111,7 @@ static int main0(int argc, char **argv) { { fprintf(stderr, "Expected source file argument.\n"); return print_error_usage(arg0); - } else if (cmd == CmdRun && emit_file_type != EmitFileTypeBinary) { + } else if (cmd == CmdRun && disable_bin_generation) { fprintf(stderr, "Cannot run non-executable file.\n"); return print_error_usage(arg0); } @@ -1262,7 +1275,8 @@ static int main0(int argc, char **argv) { if (cmd == CmdBuild || cmd == CmdRun) { - codegen_set_emit_file_type(g, emit_file_type); + 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); @@ -1330,7 +1344,8 @@ 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_file_type(g, emit_file_type); + codegen_set_emit_asm(g, emit_asm); + codegen_set_emit_llvm_ir(g, emit_llvm_ir); ZigTarget native; get_native_target(&native); @@ -1359,7 +1374,7 @@ static int main0(int argc, char **argv) { Buf *test_exe_path = buf_alloc(); *test_exe_path = os_path_resolve(&test_exe_path_unresolved, 1); - if (emit_file_type != EmitFileTypeBinary) { + if (disable_bin_generation) { fprintf(stderr, "Created %s but skipping execution because it is non executable.\n", buf_ptr(test_exe_path)); return main_exit(root_progress_node, EXIT_SUCCESS);