authorgravatar for noam@pixelhero.devNoam Preil <noam@pixelhero.dev> 2020-02-09 19:52:50-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-18 18:59:45-05:00
log2502cb242a0da5112c2cf9b0974ffd68aa27ecc8
tree6bb374c66974e22e020e6f3d4999d1934d2c1286
parentcbc4e59e6805d27f0e889c0a9ff8488376cea5c0
signaturelock-open Commit is signed but in an unrecognized format.

Improve support for generating LLVM IR/asm files


5 files changed, 122 insertions(+), 109 deletions(-)

lib/std/build.zig+10
......@@ -1155,6 +1155,9 @@ pub const LibExeObjStep = struct {
11551155 frameworks: BufSet,
11561156 verbose_link: bool,
11571157 verbose_cc: bool,
1158 produce_ir: bool,
1159 produce_asm: bool,
1160 produce_bin: bool,
11581161 disable_gen_h: bool,
11591162 bundle_compiler_rt: bool,
11601163 disable_stack_probing: bool,
......@@ -1285,6 +1288,9 @@ pub const LibExeObjStep = struct {
12851288 .builder = builder,
12861289 .verbose_link = false,
12871290 .verbose_cc = false,
1291 .produce_ir = false,
1292 .produce_asm = false,
1293 .produce_bin = true,
12881294 .build_mode = builtin.Mode.Debug,
12891295 .is_dynamic = is_dynamic,
12901296 .kind = kind,
......@@ -1941,6 +1947,10 @@ pub const LibExeObjStep = struct {
19411947 if (builder.verbose_link or self.verbose_link) zig_args.append("--verbose-link") catch unreachable;
19421948 if (builder.verbose_cc or self.verbose_cc) zig_args.append("--verbose-cc") catch unreachable;
19431949
1950 try zig_args.append(if (self.produce_ir) "-femit-llvm-ir" else "-fno-emit-llvm-ir");
1951 try zig_args.append(if (self.produce_asm) "-femit-asm" else "-fno-emit-asm");
1952 try zig_args.append(if (self.produce_bin) "-femit-bin" else "-fno-emit-bin");
1953
19441954 if (self.strip) {
19451955 try zig_args.append("--strip");
19461956 }
src/all_types.hpp+2-7
......@@ -1966,12 +1966,6 @@ enum CodeModel {
19661966 CodeModelLarge,
19671967};
19681968
1969enum EmitFileType {
1970 EmitFileTypeBinary,
1971 EmitFileTypeAssembly,
1972 EmitFileTypeLLVMIr,
1973};
1974
19751969struct LinkLib {
19761970 Buf *name;
19771971 Buf *path;
......@@ -2204,6 +2198,8 @@ struct CodeGen {
22042198 bool verbose_cimport;
22052199 bool verbose_cc;
22062200 bool verbose_llvm_cpu_features;
2201 bool emit_asm;
2202 bool emit_llvm_ir;
22072203 bool error_during_imports;
22082204 bool generate_error_name_table;
22092205 bool enable_cache; // mutually exclusive with output_dir
......@@ -2236,7 +2232,6 @@ struct CodeGen {
22362232 size_t version_patch;
22372233 const char *linker_script;
22382234
2239 EmitFileType emit_file_type;
22402235 BuildMode build_mode;
22412236 OutType out_type;
22422237 const ZigTarget *zig_target;
src/codegen.cpp+82-91
......@@ -121,10 +121,6 @@ void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patc
121121 g->version_patch = patch;
122122}
123123
124void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type) {
125 g->emit_file_type = emit_file_type;
126}
127
128124void codegen_set_each_lib_rpath(CodeGen *g, bool each_lib_rpath) {
129125 g->each_lib_rpath = each_lib_rpath;
130126}
......@@ -7919,6 +7915,14 @@ static void do_code_gen(CodeGen *g) {
79197915 }
79207916}
79217917
7918void codegen_set_emit_asm(CodeGen *g, bool emit) {
7919 g->emit_asm = emit;
7920}
7921
7922void codegen_set_emit_llvm_ir(CodeGen *g, bool emit) {
7923 g->emit_llvm_ir = emit;
7924}
7925
79227926static void zig_llvm_emit_output(CodeGen *g) {
79237927 g->pass1_arena->destruct(&heap::c_allocator);
79247928 g->pass1_arena = nullptr;
......@@ -7927,48 +7931,40 @@ static void zig_llvm_emit_output(CodeGen *g) {
79277931
79287932 Buf *output_path = &g->o_file_output_path;
79297933 char *err_msg = nullptr;
7930 switch (g->emit_file_type) {
7931 case EmitFileTypeBinary:
7932 if (g->disable_bin_generation)
7933 return;
7934 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
7935 ZigLLVM_EmitBinary, &err_msg, g->build_mode == BuildModeDebug, is_small,
7936 g->enable_time_report))
7937 {
7938 zig_panic("unable to write object file %s: %s", buf_ptr(output_path), err_msg);
7939 }
7940 validate_inline_fns(g);
7941 g->link_objects.append(output_path);
7942 if (g->bundle_compiler_rt && (g->out_type == OutTypeObj ||
7943 (g->out_type == OutTypeLib && !g->is_dynamic)))
7944 {
7945 zig_link_add_compiler_rt(g, g->sub_progress_node);
7946 }
7947 break;
7948
7949 case EmitFileTypeAssembly:
7950 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
7951 ZigLLVM_EmitAssembly, &err_msg, g->build_mode == BuildModeDebug, is_small,
7952 g->enable_time_report))
7953 {
7954 zig_panic("unable to write assembly file %s: %s", buf_ptr(output_path), err_msg);
7955 }
7956 validate_inline_fns(g);
7957 break;
7958
7959 case EmitFileTypeLLVMIr:
7960 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
7961 ZigLLVM_EmitLLVMIr, &err_msg, g->build_mode == BuildModeDebug, is_small,
7962 g->enable_time_report))
7963 {
7964 zig_panic("unable to write llvm-ir file %s: %s", buf_ptr(output_path), err_msg);
7965 }
7966 validate_inline_fns(g);
7967 break;
7968
7969 default:
7970 zig_unreachable();
7934 if (!g->disable_bin_generation) {
7935 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
7936 ZigLLVM_EmitBinary, &err_msg, g->build_mode == BuildModeDebug, is_small,
7937 g->enable_time_report))
7938 {
7939 zig_panic("unable to write object file %s: %s", buf_ptr(output_path), err_msg);
7940 }
7941 validate_inline_fns(g);
7942 g->link_objects.append(output_path);
7943 if (g->bundle_compiler_rt && (g->out_type == OutTypeObj ||
7944 (g->out_type == OutTypeLib && !g->is_dynamic)))
7945 {
7946 zig_link_add_compiler_rt(g, g->sub_progress_node);
7947 }
79717948 }
7949 if (g->emit_asm) {
7950 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
7951 ZigLLVM_EmitAssembly, &err_msg, g->build_mode == BuildModeDebug, is_small,
7952 g->enable_time_report))
7953 {
7954 zig_panic("unable to write assembly file %s: %s", buf_ptr(output_path), err_msg);
7955 }
7956 validate_inline_fns(g);
7957 }
7958 if (g->emit_llvm_ir) {
7959 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
7960 ZigLLVM_EmitLLVMIr, &err_msg, g->build_mode == BuildModeDebug, is_small,
7961 g->enable_time_report))
7962 {
7963 zig_panic("unable to write llvm-ir file %s: %s", buf_ptr(output_path), err_msg);
7964 }
7965 validate_inline_fns(g);
7966 }
7967
79727968 LLVMDisposeModule(g->module);
79737969 g->module = nullptr;
79747970 LLVMDisposeTargetData(g->target_data_ref);
......@@ -10497,53 +10493,48 @@ static void resolve_out_paths(CodeGen *g) {
1049710493
1049810494 Buf *out_basename = buf_create_from_buf(g->root_out_name);
1049910495 Buf *o_basename = buf_create_from_buf(g->root_out_name);
10500 switch (g->emit_file_type) {
10501 case EmitFileTypeBinary: {
10502 switch (g->out_type) {
10503 case OutTypeUnknown:
10504 zig_unreachable();
10505 case OutTypeObj:
10506 if (g->enable_cache && g->link_objects.length == 1 && !need_llvm_module(g)) {
10507 buf_init_from_buf(&g->output_file_path, g->link_objects.at(0));
10508 return;
10509 }
10510 if (need_llvm_module(g) && g->link_objects.length != 0 && !g->enable_cache &&
10511 buf_eql_buf(o_basename, out_basename))
10512 {
10513 // make it not collide with main output object
10514 buf_append_str(o_basename, ".root");
10515 }
10516 buf_append_str(o_basename, target_o_file_ext(g->zig_target));
10517 buf_append_str(out_basename, target_o_file_ext(g->zig_target));
10518 break;
10519 case OutTypeExe:
10520 buf_append_str(o_basename, target_o_file_ext(g->zig_target));
10521 buf_append_str(out_basename, target_exe_file_ext(g->zig_target));
10522 break;
10523 case OutTypeLib:
10524 buf_append_str(o_basename, target_o_file_ext(g->zig_target));
10525 buf_resize(out_basename, 0);
10526 buf_append_str(out_basename, target_lib_file_prefix(g->zig_target));
10527 buf_append_buf(out_basename, g->root_out_name);
10528 buf_append_str(out_basename, target_lib_file_ext(g->zig_target, !g->is_dynamic,
10529 g->version_major, g->version_minor, g->version_patch));
10530 break;
10531 }
10532 break;
10533 }
10534 case EmitFileTypeAssembly: {
10535 const char *asm_ext = target_asm_file_ext(g->zig_target);
10536 buf_append_str(o_basename, asm_ext);
10537 buf_append_str(out_basename, asm_ext);
10538 break;
10539 }
10540 case EmitFileTypeLLVMIr: {
10541 const char *llvm_ir_ext = target_llvm_ir_file_ext(g->zig_target);
10542 buf_append_str(o_basename, llvm_ir_ext);
10543 buf_append_str(out_basename, llvm_ir_ext);
10544 break;
10496 if (!g->disable_bin_generation) {
10497 switch (g->out_type) {
10498 case OutTypeUnknown:
10499 zig_unreachable();
10500 case OutTypeObj:
10501 if (g->enable_cache && g->link_objects.length == 1 && !need_llvm_module(g)) {
10502 buf_init_from_buf(&g->output_file_path, g->link_objects.at(0));
10503 return;
10504 }
10505 if (need_llvm_module(g) && g->link_objects.length != 0 && !g->enable_cache &&
10506 buf_eql_buf(o_basename, out_basename))
10507 {
10508 // make it not collide with main output object
10509 buf_append_str(o_basename, ".root");
10510 }
10511 buf_append_str(o_basename, target_o_file_ext(g->zig_target));
10512 buf_append_str(out_basename, target_o_file_ext(g->zig_target));
10513 break;
10514 case OutTypeExe:
10515 buf_append_str(o_basename, target_o_file_ext(g->zig_target));
10516 buf_append_str(out_basename, target_exe_file_ext(g->zig_target));
10517 break;
10518 case OutTypeLib:
10519 buf_append_str(o_basename, target_o_file_ext(g->zig_target));
10520 buf_resize(out_basename, 0);
10521 buf_append_str(out_basename, target_lib_file_prefix(g->zig_target));
10522 buf_append_buf(out_basename, g->root_out_name);
10523 buf_append_str(out_basename, target_lib_file_ext(g->zig_target, !g->is_dynamic,
10524 g->version_major, g->version_minor, g->version_patch));
10525 break;
1054510526 }
1054610527 }
10528 else if (g->emit_asm) {
10529 const char *asm_ext = target_asm_file_ext(g->zig_target);
10530 buf_append_str(o_basename, asm_ext);
10531 buf_append_str(out_basename, asm_ext);
10532 }
10533 else if (g->emit_llvm_ir) {
10534 const char *llvm_ir_ext = target_llvm_ir_file_ext(g->zig_target);
10535 buf_append_str(o_basename, llvm_ir_ext);
10536 buf_append_str(out_basename, llvm_ir_ext);
10537 }
1054710538
1054810539 os_path_join(g->output_dir, o_basename, &g->o_file_output_path);
1054910540 os_path_join(g->output_dir, out_basename, &g->output_file_path);
......@@ -10708,7 +10699,7 @@ void codegen_build_and_link(CodeGen *g) {
1070810699 // If there is more than one object, we have to link them (with -r).
1070910700 // Finally, if we didn't make an object from zig source, and we don't have caching enabled,
1071010701 // then we have an object from C source that we must copy to the output dir which we do with a -r link.
10711 if (!g->disable_bin_generation && g->emit_file_type == EmitFileTypeBinary &&
10702 if (!g->disable_bin_generation &&
1071210703 (g->out_type != OutTypeObj || g->link_objects.length > 1 ||
1071310704 (!need_llvm_module(g) && !g->enable_cache)))
1071410705 {
src/codegen.hpp+3-1
......@@ -26,7 +26,9 @@ void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
2626void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len);
2727void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath);
2828
29void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type);
29void codegen_set_emit_asm(CodeGen *codegen, bool emit);
30void codegen_set_emit_llvm_ir(CodeGen *codegen, bool emit);
31
3032void codegen_set_strip(CodeGen *codegen, bool strip);
3133void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);
3234void codegen_set_out_name(CodeGen *codegen, Buf *out_name);
src/main.cpp+25-10
......@@ -376,7 +376,6 @@ static int main0(int argc, char **argv) {
376376 }
377377
378378 Cmd cmd = CmdNone;
379 EmitFileType emit_file_type = EmitFileTypeBinary;
380379 const char *in_file = nullptr;
381380 Buf *output_dir = nullptr;
382381 bool strip = false;
......@@ -425,6 +424,8 @@ static int main0(int argc, char **argv) {
425424 bool enable_dump_analysis = false;
426425 bool enable_doc_generation = false;
427426 bool disable_bin_generation = false;
427 bool emit_asm = false;
428 bool emit_llvm_ir = false;
428429 const char *cache_dir = nullptr;
429430 CliPkg *cur_pkg = heap::c_allocator.create<CliPkg>();
430431 BuildMode build_mode = BuildModeDebug;
......@@ -701,6 +702,18 @@ static int main0(int argc, char **argv) {
701702 function_sections = true;
702703 } else if (strcmp(arg, "--test-evented-io") == 0) {
703704 test_evented_io = true;
705 } else if (strcmp(arg, "-femit-bin") == 0) {
706 disable_bin_generation = false;
707 } else if (strcmp(arg, "-fno-emit-bin") == 0) {
708 disable_bin_generation = true;
709 } else if (strcmp(arg, "-femit-asm") == 0) {
710 emit_asm = true;
711 } else if (strcmp(arg, "-fno-emit-asm") == 0) {
712 emit_asm = false;
713 } else if (strcmp(arg, "-femit-llvm-ir") == 0) {
714 emit_llvm_ir = true;
715 } else if (strcmp(arg, "-fno-emit-llvm-ir") == 0) {
716 emit_llvm_ir = false;
704717 } else if (i + 1 >= argc) {
705718 fprintf(stderr, "Expected another argument after %s\n", arg);
706719 return print_error_usage(arg0);
......@@ -732,11 +745,11 @@ static int main0(int argc, char **argv) {
732745 }
733746 } else if (strcmp(arg, "--emit") == 0) {
734747 if (strcmp(argv[i], "asm") == 0) {
735 emit_file_type = EmitFileTypeAssembly;
748 emit_asm = true;
736749 } else if (strcmp(argv[i], "bin") == 0) {
737 emit_file_type = EmitFileTypeBinary;
750 disable_bin_generation = false;
738751 } else if (strcmp(argv[i], "llvm-ir") == 0) {
739 emit_file_type = EmitFileTypeLLVMIr;
752 emit_llvm_ir = true;
740753 } else {
741754 fprintf(stderr, "--emit options are 'asm', 'bin', or 'llvm-ir'\n");
742755 return print_error_usage(arg0);
......@@ -1026,8 +1039,8 @@ static int main0(int argc, char **argv) {
10261039 return print_error_usage(arg0);
10271040 }
10281041
1029 if (emit_file_type != EmitFileTypeBinary && in_file == nullptr) {
1030 fprintf(stderr, "A root source file is required when using `--emit asm` or `--emit llvm-ir`\n");
1042 if ((emit_asm || emit_llvm_ir) && in_file == nullptr) {
1043 fprintf(stderr, "A root source file is required when using `-femit-asm` or `-femit-llvm-ir`\n");
10311044 return print_error_usage(arg0);
10321045 }
10331046
......@@ -1098,7 +1111,7 @@ static int main0(int argc, char **argv) {
10981111 {
10991112 fprintf(stderr, "Expected source file argument.\n");
11001113 return print_error_usage(arg0);
1101 } else if (cmd == CmdRun && emit_file_type != EmitFileTypeBinary) {
1114 } else if (cmd == CmdRun && disable_bin_generation) {
11021115 fprintf(stderr, "Cannot run non-executable file.\n");
11031116 return print_error_usage(arg0);
11041117 }
......@@ -1262,7 +1275,8 @@ static int main0(int argc, char **argv) {
12621275
12631276
12641277 if (cmd == CmdBuild || cmd == CmdRun) {
1265 codegen_set_emit_file_type(g, emit_file_type);
1278 codegen_set_emit_asm(g, emit_asm);
1279 codegen_set_emit_llvm_ir(g, emit_llvm_ir);
12661280
12671281 g->enable_cache = get_cache_opt(enable_cache, cmd == CmdRun);
12681282 codegen_build_and_link(g);
......@@ -1330,7 +1344,8 @@ static int main0(int argc, char **argv) {
13301344 codegen_print_timing_report(g, stderr);
13311345 return main_exit(root_progress_node, EXIT_SUCCESS);
13321346 } else if (cmd == CmdTest) {
1333 codegen_set_emit_file_type(g, emit_file_type);
1347 codegen_set_emit_asm(g, emit_asm);
1348 codegen_set_emit_llvm_ir(g, emit_llvm_ir);
13341349
13351350 ZigTarget native;
13361351 get_native_target(&native);
......@@ -1359,7 +1374,7 @@ static int main0(int argc, char **argv) {
13591374 Buf *test_exe_path = buf_alloc();
13601375 *test_exe_path = os_path_resolve(&test_exe_path_unresolved, 1);
13611376
1362 if (emit_file_type != EmitFileTypeBinary) {
1377 if (disable_bin_generation) {
13631378 fprintf(stderr, "Created %s but skipping execution because it is non executable.\n",
13641379 buf_ptr(test_exe_path));
13651380 return main_exit(root_progress_node, EXIT_SUCCESS);