authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-18 22:01:08-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-18 22:01:08-05:00
logc5ca0fe237e105b95c8edb7f80da899012e573f8
tree6f8120d2bb3187a90ba5e855c87332386141bf63
parentcbc4e59e6805d27f0e889c0a9ff8488376cea5c0
parentd7968c6d33b054a8293edd89ce248f385e108469
signaturelock-open Commit is signed but in an unrecognized format.

Merge branch 'pixelherodev-emit'

Closes #4418

8 files changed, 225 insertions(+), 207 deletions(-)

lib/std/build.zig+7
......@@ -1155,6 +1155,9 @@ pub const LibExeObjStep = struct {
11551155 frameworks: BufSet,
11561156 verbose_link: bool,
11571157 verbose_cc: bool,
1158 emit_llvm_ir: bool = false,
1159 emit_asm: bool = false,
1160 emit_bin: bool = true,
11581161 disable_gen_h: bool,
11591162 bundle_compiler_rt: bool,
11601163 disable_stack_probing: bool,
......@@ -1941,6 +1944,10 @@ pub const LibExeObjStep = struct {
19411944 if (builder.verbose_link or self.verbose_link) zig_args.append("--verbose-link") catch unreachable;
19421945 if (builder.verbose_cc or self.verbose_cc) zig_args.append("--verbose-cc") catch unreachable;
19431946
1947 if (self.emit_llvm_ir) try zig_args.append("-femit-llvm-ir");
1948 if (self.emit_asm) try zig_args.append("-femit-asm");
1949 if (!self.emit_bin) try zig_args.append("-fno-emit-bin");
1950
19441951 if (self.strip) {
19451952 try zig_args.append("--strip");
19461953 }
src/all_types.hpp+6-9
......@@ -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;
......@@ -2142,8 +2136,10 @@ struct CodeGen {
21422136
21432137 Buf llvm_triple_str;
21442138 Buf global_asm;
2145 Buf output_file_path;
21462139 Buf o_file_output_path;
2140 Buf bin_file_output_path;
2141 Buf asm_file_output_path;
2142 Buf llvm_ir_file_output_path;
21472143 Buf *cache_dir;
21482144 // As an input parameter, mutually exclusive with enable_cache. But it gets
21492145 // populated in codegen_build_and_link.
......@@ -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;
......@@ -2258,7 +2253,9 @@ struct CodeGen {
22582253 bool function_sections;
22592254 bool enable_dump_analysis;
22602255 bool enable_doc_generation;
2261 bool disable_bin_generation;
2256 bool emit_bin;
2257 bool emit_asm;
2258 bool emit_llvm_ir;
22622259 bool test_is_evented;
22632260 CodeModel code_model;
22642261
src/codegen.cpp+84-95
......@@ -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}
......@@ -7925,50 +7921,44 @@ static void zig_llvm_emit_output(CodeGen *g) {
79257921
79267922 bool is_small = g->build_mode == BuildModeSmallRelease;
79277923
7928 Buf *output_path = &g->o_file_output_path;
79297924 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;
7925 const char *asm_filename = nullptr;
7926 const char *bin_filename = nullptr;
7927 const char *llvm_ir_filename = nullptr;
7928
7929 if (g->emit_bin) bin_filename = buf_ptr(&g->o_file_output_path);
7930 if (g->emit_asm) asm_filename = buf_ptr(&g->asm_file_output_path);
7931 if (g->emit_llvm_ir) llvm_ir_filename = buf_ptr(&g->llvm_ir_file_output_path);
7932
7933 // Unfortunately, LLVM shits the bed when we ask for both binary and assembly. So we call the entire
7934 // pipeline multiple times if this is requested.
7935 if (asm_filename != nullptr && bin_filename != nullptr) {
7936 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, &err_msg, g->build_mode == BuildModeDebug,
7937 is_small, g->enable_time_report, nullptr, bin_filename, llvm_ir_filename))
7938 {
7939 fprintf(stderr, "LLVM failed to emit file: %s\n", err_msg);
7940 exit(1);
7941 }
7942 bin_filename = nullptr;
7943 llvm_ir_filename = nullptr;
7944 }
79487945
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;
7946 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, &err_msg, g->build_mode == BuildModeDebug,
7947 is_small, g->enable_time_report, asm_filename, bin_filename, llvm_ir_filename))
7948 {
7949 fprintf(stderr, "LLVM failed to emit file: %s\n", err_msg);
7950 exit(1);
7951 }
79587952
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;
7953 validate_inline_fns(g);
79687954
7969 default:
7970 zig_unreachable();
7955 if (g->emit_bin) {
7956 g->link_objects.append(&g->o_file_output_path);
7957 if (g->bundle_compiler_rt && (g->out_type == OutTypeObj || (g->out_type == OutTypeLib && !g->is_dynamic))) {
7958 zig_link_add_compiler_rt(g, g->sub_progress_node);
7959 }
79717960 }
7961
79727962 LLVMDisposeModule(g->module);
79737963 g->module = nullptr;
79747964 LLVMDisposeTargetData(g->target_data_ref);
......@@ -10450,7 +10440,9 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
1045010440 cache_bool(ch, g->function_sections);
1045110441 cache_bool(ch, g->enable_dump_analysis);
1045210442 cache_bool(ch, g->enable_doc_generation);
10453 cache_bool(ch, g->disable_bin_generation);
10443 cache_bool(ch, g->emit_bin);
10444 cache_bool(ch, g->emit_llvm_ir);
10445 cache_bool(ch, g->emit_asm);
1045410446 cache_buf_opt(ch, g->mmacosx_version_min);
1045510447 cache_buf_opt(ch, g->mios_version_min);
1045610448 cache_usize(ch, g->version_major);
......@@ -10495,58 +10487,54 @@ static void resolve_out_paths(CodeGen *g) {
1049510487 assert(g->output_dir != nullptr);
1049610488 assert(g->root_out_name != nullptr);
1049710489
10498 Buf *out_basename = buf_create_from_buf(g->root_out_name);
10499 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;
10490 if (g->emit_bin) {
10491 Buf *out_basename = buf_create_from_buf(g->root_out_name);
10492 Buf *o_basename = buf_create_from_buf(g->root_out_name);
10493 switch (g->out_type) {
10494 case OutTypeUnknown:
10495 zig_unreachable();
10496 case OutTypeObj:
10497 if (g->enable_cache && g->link_objects.length == 1 && !need_llvm_module(g)) {
10498 buf_init_from_buf(&g->bin_file_output_path, g->link_objects.at(0));
10499 return;
10500 }
10501 if (need_llvm_module(g) && g->link_objects.length != 0 && !g->enable_cache &&
10502 buf_eql_buf(o_basename, out_basename))
10503 {
10504 // make it not collide with main output object
10505 buf_append_str(o_basename, ".root");
10506 }
10507 buf_append_str(o_basename, target_o_file_ext(g->zig_target));
10508 buf_append_str(out_basename, target_o_file_ext(g->zig_target));
10509 break;
10510 case OutTypeExe:
10511 buf_append_str(o_basename, target_o_file_ext(g->zig_target));
10512 buf_append_str(out_basename, target_exe_file_ext(g->zig_target));
10513 break;
10514 case OutTypeLib:
10515 buf_append_str(o_basename, target_o_file_ext(g->zig_target));
10516 buf_resize(out_basename, 0);
10517 buf_append_str(out_basename, target_lib_file_prefix(g->zig_target));
10518 buf_append_buf(out_basename, g->root_out_name);
10519 buf_append_str(out_basename, target_lib_file_ext(g->zig_target, !g->is_dynamic,
10520 g->version_major, g->version_minor, g->version_patch));
10521 break;
1054510522 }
10523 os_path_join(g->output_dir, o_basename, &g->o_file_output_path);
10524 os_path_join(g->output_dir, out_basename, &g->bin_file_output_path);
10525 }
10526 if (g->emit_asm) {
10527 Buf *asm_basename = buf_create_from_buf(g->root_out_name);
10528 const char *asm_ext = target_asm_file_ext(g->zig_target);
10529 buf_append_str(asm_basename, asm_ext);
10530 os_path_join(g->output_dir, asm_basename, &g->asm_file_output_path);
10531 }
10532 if (g->emit_llvm_ir) {
10533 Buf *llvm_ir_basename = buf_create_from_buf(g->root_out_name);
10534 const char *llvm_ir_ext = target_llvm_ir_file_ext(g->zig_target);
10535 buf_append_str(llvm_ir_basename, llvm_ir_ext);
10536 os_path_join(g->output_dir, llvm_ir_basename, &g->llvm_ir_file_output_path);
1054610537 }
10547
10548 os_path_join(g->output_dir, o_basename, &g->o_file_output_path);
10549 os_path_join(g->output_dir, out_basename, &g->output_file_path);
1055010538}
1055110539
1055210540void codegen_build_and_link(CodeGen *g) {
......@@ -10708,7 +10696,7 @@ void codegen_build_and_link(CodeGen *g) {
1070810696 // If there is more than one object, we have to link them (with -r).
1070910697 // Finally, if we didn't make an object from zig source, and we don't have caching enabled,
1071010698 // 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 &&
10699 if (g->emit_bin &&
1071210700 (g->out_type != OutTypeObj || g->link_objects.length > 1 ||
1071310701 (!need_llvm_module(g) && !g->enable_cache)))
1071410702 {
......@@ -10786,6 +10774,7 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
1078610774 Stage2LibCInstallation *libc, Buf *cache_dir, bool is_test_build, Stage2ProgressNode *progress_node)
1078710775{
1078810776 CodeGen *g = heap::c_allocator.create<CodeGen>();
10777 g->emit_bin = true;
1078910778 g->pass1_arena = heap::ArenaAllocator::construct(&heap::c_allocator, &heap::c_allocator, "pass1");
1079010779 g->main_progress_node = progress_node;
1079110780
src/codegen.hpp-1
......@@ -26,7 +26,6 @@ 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);
3029void codegen_set_strip(CodeGen *codegen, bool strip);
3130void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);
3231void codegen_set_out_name(CodeGen *codegen, Buf *out_name);
src/link.cpp+19-19
......@@ -605,7 +605,7 @@ static const char *build_libc_object(CodeGen *parent_gen, const char *name, CFil
605605 c_source_files.append(c_file);
606606 child_gen->c_source_files = c_source_files;
607607 codegen_build_and_link(child_gen);
608 return buf_ptr(&child_gen->output_file_path);
608 return buf_ptr(&child_gen->bin_file_output_path);
609609}
610610
611611static 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
682682 }
683683 child_gen->c_source_files = c_source_files;
684684 codegen_build_and_link(child_gen);
685 return buf_ptr(&child_gen->output_file_path);
685 return buf_ptr(&child_gen->bin_file_output_path);
686686}
687687
688688static void mingw_add_cc_args(CodeGen *parent, CFile *c_file) {
......@@ -1123,7 +1123,7 @@ static const char *build_musl(CodeGen *parent, Stage2ProgressNode *progress_node
11231123
11241124 child_gen->c_source_files = c_source_files;
11251125 codegen_build_and_link(child_gen);
1126 return buf_ptr(&child_gen->output_file_path);
1126 return buf_ptr(&child_gen->bin_file_output_path);
11271127}
11281128
11291129static 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
12531253 child_gen->c_source_files.append(c_file);
12541254 }
12551255 codegen_build_and_link(child_gen);
1256 return buf_ptr(&child_gen->output_file_path);
1256 return buf_ptr(&child_gen->bin_file_output_path);
12571257 } else if (strcmp(file, "msvcrt-os.lib") == 0) {
12581258 CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "msvcrt-os", progress_node);
12591259
......@@ -1270,7 +1270,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr
12701270 }
12711271 }
12721272 codegen_build_and_link(child_gen);
1273 return buf_ptr(&child_gen->output_file_path);
1273 return buf_ptr(&child_gen->bin_file_output_path);
12741274 } else if (strcmp(file, "mingwex.lib") == 0) {
12751275 CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "mingwex", progress_node);
12761276
......@@ -1295,7 +1295,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr
12951295 zig_unreachable();
12961296 }
12971297 codegen_build_and_link(child_gen);
1298 return buf_ptr(&child_gen->output_file_path);
1298 return buf_ptr(&child_gen->bin_file_output_path);
12991299 } else {
13001300 zig_unreachable();
13011301 }
......@@ -1365,7 +1365,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr
13651365 codegen_add_object(child_gen, buf_create_from_str(start_os));
13661366 codegen_add_object(child_gen, buf_create_from_str(abi_note_o));
13671367 codegen_build_and_link(child_gen);
1368 return buf_ptr(&child_gen->output_file_path);
1368 return buf_ptr(&child_gen->bin_file_output_path);
13691369 } else if (strcmp(file, "libc_nonshared.a") == 0) {
13701370 CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "c_nonshared", progress_node);
13711371 {
......@@ -1445,7 +1445,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr
14451445 build_libc_object(parent, deps[i].name, c_file, progress_node)));
14461446 }
14471447 codegen_build_and_link(child_gen);
1448 return buf_ptr(&child_gen->output_file_path);
1448 return buf_ptr(&child_gen->bin_file_output_path);
14491449 } else {
14501450 zig_unreachable();
14511451 }
......@@ -1519,7 +1519,7 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path,
15191519 child_gen->want_stack_check = WantStackCheckDisabled;
15201520
15211521 codegen_build_and_link(child_gen);
1522 return &child_gen->output_file_path;
1522 return &child_gen->bin_file_output_path;
15231523}
15241524
15251525static 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) {
16811681 } else if (is_dyn_lib) {
16821682 lj->args.append("-shared");
16831683
1684 assert(buf_len(&g->output_file_path) != 0);
1684 assert(buf_len(&g->bin_file_output_path) != 0);
16851685 soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize, buf_ptr(g->root_out_name), g->version_major);
16861686 }
16871687
......@@ -1690,7 +1690,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
16901690 }
16911691
16921692 lj->args.append("-o");
1693 lj->args.append(buf_ptr(&g->output_file_path));
1693 lj->args.append(buf_ptr(&g->bin_file_output_path));
16941694
16951695 if (lj->link_in_crt) {
16961696 const char *crt1o;
......@@ -1872,7 +1872,7 @@ static void construct_linker_job_wasm(LinkJob *lj) {
18721872 }
18731873 lj->args.append("--allow-undefined");
18741874 lj->args.append("-o");
1875 lj->args.append(buf_ptr(&g->output_file_path));
1875 lj->args.append(buf_ptr(&g->bin_file_output_path));
18761876
18771877 // .o files
18781878 for (size_t i = 0; i < g->link_objects.length; i += 1) {
......@@ -2248,7 +2248,7 @@ static void construct_linker_job_coff(LinkJob *lj) {
22482248 lj->args.append("-DLL");
22492249 }
22502250
2251 lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));
2251 lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->bin_file_output_path))));
22522252
22532253 if (g->libc_link_lib != nullptr && g->libc != nullptr) {
22542254 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) {
25012501 //lj->args.append("-install_name");
25022502 //lj->args.append(buf_ptr(dylib_install_name));
25032503
2504 assert(buf_len(&g->output_file_path) != 0);
2504 assert(buf_len(&g->bin_file_output_path) != 0);
25052505 }
25062506
25072507 lj->args.append("-arch");
......@@ -2532,14 +2532,14 @@ static void construct_linker_job_macho(LinkJob *lj) {
25322532 }
25332533
25342534 lj->args.append("-o");
2535 lj->args.append(buf_ptr(&g->output_file_path));
2535 lj->args.append(buf_ptr(&g->bin_file_output_path));
25362536
25372537 for (size_t i = 0; i < g->rpath_list.length; i += 1) {
25382538 Buf *rpath = g->rpath_list.at(i);
25392539 add_rpath(lj, rpath);
25402540 }
25412541 if (is_dyn_lib) {
2542 add_rpath(lj, &g->output_file_path);
2542 add_rpath(lj, &g->bin_file_output_path);
25432543 }
25442544
25452545 if (is_dyn_lib) {
......@@ -2659,14 +2659,14 @@ void codegen_link(CodeGen *g) {
26592659 progress_name, strlen(progress_name), 0));
26602660 }
26612661 if (g->verbose_link) {
2662 fprintf(stderr, "ar rcs %s", buf_ptr(&g->output_file_path));
2662 fprintf(stderr, "ar rcs %s", buf_ptr(&g->bin_file_output_path));
26632663 for (size_t i = 0; i < file_names.length; i += 1) {
26642664 fprintf(stderr, " %s", file_names.at(i));
26652665 }
26662666 fprintf(stderr, "\n");
26672667 }
2668 if (ZigLLVMWriteArchive(buf_ptr(&g->output_file_path), file_names.items, file_names.length, os_type)) {
2669 fprintf(stderr, "Unable to write archive '%s'\n", buf_ptr(&g->output_file_path));
2668 if (ZigLLVMWriteArchive(buf_ptr(&g->bin_file_output_path), file_names.items, file_names.length, os_type)) {
2669 fprintf(stderr, "Unable to write archive '%s'\n", buf_ptr(&g->bin_file_output_path));
26702670 exit(1);
26712671 }
26722672 return;
src/main.cpp+47-31
......@@ -62,17 +62,21 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
6262 " -fno-stack-check disable stack probing in safe builds\n"
6363 " -fsanitize-c enable C undefined behavior detection in unsafe builds\n"
6464 " -fno-sanitize-c disable C undefined behavior detection in safe builds\n"
65 " --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"
65 " --emit [asm|bin|llvm-ir] (deprecated) emit a specific file format as compilation output\n"
6666 " -fPIC enable Position Independent Code\n"
6767 " -fno-PIC disable Position Independent Code\n"
6868 " -ftime-report print timing diagnostics\n"
6969 " -fstack-report print stack size diagnostics\n"
70#ifdef ZIG_ENABLE_MEM_PROFILE
7170 " -fmem-report print memory usage diagnostics\n"
72#endif
7371 " -fdump-analysis write analysis.json file with type information\n"
7472 " -femit-docs create a docs/ dir with html documentation\n"
75 " -fno-emit-bin skip emitting machine code\n"
73 " -fno-emit-docs do not produce docs/ dir with html documentation\n"
74 " -femit-bin (default) output machine code\n"
75 " -fno-emit-bin do not output machine code\n"
76 " -femit-asm output .s (assembly code)\n"
77 " -fno-emit-asm (default) do not output .s (assembly code)\n"
78 " -femit-llvm-ir produce a .ll file with LLVM IR\n"
79 " -fno-emit-llvm-ir (default) do not produce a .ll file with LLVM IR\n"
7680 " --libc [file] Provide a file which specifies libc paths\n"
7781 " --name [name] override output name\n"
7882 " --output-dir [dir] override output directory (defaults to cwd)\n"
......@@ -376,7 +380,6 @@ static int main0(int argc, char **argv) {
376380 }
377381
378382 Cmd cmd = CmdNone;
379 EmitFileType emit_file_type = EmitFileTypeBinary;
380383 const char *in_file = nullptr;
381384 Buf *output_dir = nullptr;
382385 bool strip = false;
......@@ -424,7 +427,9 @@ static int main0(int argc, char **argv) {
424427 bool stack_report = false;
425428 bool enable_dump_analysis = false;
426429 bool enable_doc_generation = false;
427 bool disable_bin_generation = false;
430 bool emit_bin = true;
431 bool emit_asm = false;
432 bool emit_llvm_ir = false;
428433 const char *cache_dir = nullptr;
429434 CliPkg *cur_pkg = heap::c_allocator.create<CliPkg>();
430435 BuildMode build_mode = BuildModeDebug;
......@@ -552,7 +557,7 @@ static int main0(int argc, char **argv) {
552557 }
553558
554559 Termination term;
555 args.items[0] = buf_ptr(&g->output_file_path);
560 args.items[0] = buf_ptr(&g->bin_file_output_path);
556561 os_spawn_process(args, &term);
557562 if (term.how != TerminationIdClean || term.code != 0) {
558563 fprintf(stderr, "\nBuild failed. The following command failed:\n");
......@@ -631,8 +636,6 @@ static int main0(int argc, char **argv) {
631636 enable_dump_analysis = true;
632637 } else if (strcmp(arg, "-femit-docs") == 0) {
633638 enable_doc_generation = true;
634 } else if (strcmp(arg, "-fno-emit-bin") == 0) {
635 disable_bin_generation = true;
636639 } else if (strcmp(arg, "--enable-valgrind") == 0) {
637640 valgrind_support = ValgrindSupportEnabled;
638641 } else if (strcmp(arg, "--disable-valgrind") == 0) {
......@@ -701,6 +704,18 @@ static int main0(int argc, char **argv) {
701704 function_sections = true;
702705 } else if (strcmp(arg, "--test-evented-io") == 0) {
703706 test_evented_io = true;
707 } else if (strcmp(arg, "-femit-bin") == 0) {
708 emit_bin = true;
709 } else if (strcmp(arg, "-fno-emit-bin") == 0) {
710 emit_bin = false;
711 } else if (strcmp(arg, "-femit-asm") == 0) {
712 emit_asm = true;
713 } else if (strcmp(arg, "-fno-emit-asm") == 0) {
714 emit_asm = false;
715 } else if (strcmp(arg, "-femit-llvm-ir") == 0) {
716 emit_llvm_ir = true;
717 } else if (strcmp(arg, "-fno-emit-llvm-ir") == 0) {
718 emit_llvm_ir = false;
704719 } else if (i + 1 >= argc) {
705720 fprintf(stderr, "Expected another argument after %s\n", arg);
706721 return print_error_usage(arg0);
......@@ -732,11 +747,13 @@ static int main0(int argc, char **argv) {
732747 }
733748 } else if (strcmp(arg, "--emit") == 0) {
734749 if (strcmp(argv[i], "asm") == 0) {
735 emit_file_type = EmitFileTypeAssembly;
750 emit_asm = true;
751 emit_bin = false;
736752 } else if (strcmp(argv[i], "bin") == 0) {
737 emit_file_type = EmitFileTypeBinary;
753 emit_bin = true;
738754 } else if (strcmp(argv[i], "llvm-ir") == 0) {
739 emit_file_type = EmitFileTypeLLVMIr;
755 emit_llvm_ir = true;
756 emit_bin = false;
740757 } else {
741758 fprintf(stderr, "--emit options are 'asm', 'bin', or 'llvm-ir'\n");
742759 return print_error_usage(arg0);
......@@ -1026,8 +1043,8 @@ static int main0(int argc, char **argv) {
10261043 return print_error_usage(arg0);
10271044 }
10281045
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");
1046 if ((emit_asm || emit_llvm_ir) && in_file == nullptr) {
1047 fprintf(stderr, "A root source file is required when using `-femit-asm` or `-femit-llvm-ir`\n");
10311048 return print_error_usage(arg0);
10321049 }
10331050
......@@ -1098,8 +1115,8 @@ static int main0(int argc, char **argv) {
10981115 {
10991116 fprintf(stderr, "Expected source file argument.\n");
11001117 return print_error_usage(arg0);
1101 } else if (cmd == CmdRun && emit_file_type != EmitFileTypeBinary) {
1102 fprintf(stderr, "Cannot run non-executable file.\n");
1118 } else if (cmd == CmdRun && !emit_bin) {
1119 fprintf(stderr, "Cannot run without emitting a binary file.\n");
11031120 return print_error_usage(arg0);
11041121 }
11051122
......@@ -1176,7 +1193,10 @@ static int main0(int argc, char **argv) {
11761193 g->enable_stack_report = stack_report;
11771194 g->enable_dump_analysis = enable_dump_analysis;
11781195 g->enable_doc_generation = enable_doc_generation;
1179 g->disable_bin_generation = disable_bin_generation;
1196 g->emit_bin = emit_bin;
1197 g->emit_asm = emit_asm;
1198 g->emit_llvm_ir = emit_llvm_ir;
1199
11801200 codegen_set_out_name(g, buf_out_name);
11811201 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
11821202 g->want_single_threaded = want_single_threaded;
......@@ -1262,8 +1282,6 @@ static int main0(int argc, char **argv) {
12621282
12631283
12641284 if (cmd == CmdBuild || cmd == CmdRun) {
1265 codegen_set_emit_file_type(g, emit_file_type);
1266
12671285 g->enable_cache = get_cache_opt(enable_cache, cmd == CmdRun);
12681286 codegen_build_and_link(g);
12691287 if (root_progress_node != nullptr) {
......@@ -1281,7 +1299,7 @@ static int main0(int argc, char **argv) {
12811299 mem::print_report();
12821300#endif
12831301
1284 const char *exec_path = buf_ptr(&g->output_file_path);
1302 const char *exec_path = buf_ptr(&g->bin_file_output_path);
12851303 ZigList<const char*> args = {0};
12861304
12871305 args.append(exec_path);
......@@ -1301,21 +1319,21 @@ static int main0(int argc, char **argv) {
13011319 } else if (cmd == CmdBuild) {
13021320 if (g->enable_cache) {
13031321#if defined(ZIG_OS_WINDOWS)
1304 buf_replace(&g->output_file_path, '/', '\\');
1322 buf_replace(&g->bin_file_output_path, '/', '\\');
13051323#endif
13061324 if (final_output_dir_step != nullptr) {
13071325 Buf *dest_basename = buf_alloc();
1308 os_path_split(&g->output_file_path, nullptr, dest_basename);
1326 os_path_split(&g->bin_file_output_path, nullptr, dest_basename);
13091327 Buf *dest_path = buf_alloc();
13101328 os_path_join(final_output_dir_step, dest_basename, dest_path);
13111329
1312 if ((err = os_update_file(&g->output_file_path, dest_path))) {
1313 fprintf(stderr, "unable to copy %s to %s: %s\n", buf_ptr(&g->output_file_path),
1330 if ((err = os_update_file(&g->bin_file_output_path, dest_path))) {
1331 fprintf(stderr, "unable to copy %s to %s: %s\n", buf_ptr(&g->bin_file_output_path),
13141332 buf_ptr(dest_path), err_str(err));
13151333 return main_exit(root_progress_node, EXIT_FAILURE);
13161334 }
13171335 } else {
1318 if (printf("%s\n", buf_ptr(&g->output_file_path)) < 0)
1336 if (printf("%s\n", buf_ptr(&g->bin_file_output_path)) < 0)
13191337 return main_exit(root_progress_node, EXIT_FAILURE);
13201338 }
13211339 }
......@@ -1330,8 +1348,6 @@ static int main0(int argc, char **argv) {
13301348 codegen_print_timing_report(g, stderr);
13311349 return main_exit(root_progress_node, EXIT_SUCCESS);
13321350 } else if (cmd == CmdTest) {
1333 codegen_set_emit_file_type(g, emit_file_type);
1334
13351351 ZigTarget native;
13361352 get_native_target(&native);
13371353
......@@ -1350,17 +1366,17 @@ static int main0(int argc, char **argv) {
13501366 zig_print_stack_report(g, stdout);
13511367 }
13521368
1353 if (g->disable_bin_generation) {
1369 if (!g->emit_bin) {
13541370 fprintf(stderr, "Semantic analysis complete. No binary produced due to -fno-emit-bin.\n");
13551371 return main_exit(root_progress_node, EXIT_SUCCESS);
13561372 }
13571373
1358 Buf *test_exe_path_unresolved = &g->output_file_path;
1374 Buf *test_exe_path_unresolved = &g->bin_file_output_path;
13591375 Buf *test_exe_path = buf_alloc();
13601376 *test_exe_path = os_path_resolve(&test_exe_path_unresolved, 1);
13611377
1362 if (emit_file_type != EmitFileTypeBinary) {
1363 fprintf(stderr, "Created %s but skipping execution because it is non executable.\n",
1378 if (!g->emit_bin) {
1379 fprintf(stderr, "Created %s but skipping execution because no binary generated.\n",
13641380 buf_ptr(test_exe_path));
13651381 return main_exit(root_progress_node, EXIT_SUCCESS);
13661382 }
src/zig_llvm.cpp+59-42
......@@ -161,17 +161,32 @@ unsigned ZigLLVMDataLayoutGetProgramAddressSpace(LLVMTargetDataRef TD) {
161161}
162162
163163bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
164 const char *filename, ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug,
165 bool is_small, bool time_report)
164 char **error_message, bool is_debug,
165 bool is_small, bool time_report,
166 const char *asm_filename, const char *bin_filename, const char *llvm_ir_filename)
166167{
167168 TimePassesIsEnabled = time_report;
168169
169 std::error_code EC;
170 raw_fd_ostream dest(filename, EC, sys::fs::F_None);
171 if (EC) {
172 *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());
173 return true;
170 raw_fd_ostream *dest_asm = nullptr;
171 raw_fd_ostream *dest_bin = nullptr;
172
173 if (asm_filename) {
174 std::error_code EC;
175 dest_asm = new(std::nothrow) raw_fd_ostream(asm_filename, EC, sys::fs::F_None);
176 if (EC) {
177 *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());
178 return true;
179 }
174180 }
181 if (bin_filename) {
182 std::error_code EC;
183 dest_bin = new(std::nothrow) raw_fd_ostream(bin_filename, EC, sys::fs::F_None);
184 if (EC) {
185 *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());
186 return true;
187 }
188 }
189
175190 TargetMachine* target_machine = reinterpret_cast<TargetMachine*>(targ_machine_ref);
176191 target_machine->setO0WantsFastISel(true);
177192
......@@ -222,49 +237,51 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
222237 }
223238 PMBuilder->populateFunctionPassManager(FPM);
224239
225 // Set up the per-module pass manager.
226 legacy::PassManager MPM;
227 MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));
228 PMBuilder->populateModulePassManager(MPM);
229
230 // Set output pass.
231 TargetMachine::CodeGenFileType ft;
232 if (output_type != ZigLLVM_EmitLLVMIr) {
233 switch (output_type) {
234 case ZigLLVM_EmitAssembly:
235 ft = TargetMachine::CGFT_AssemblyFile;
236 break;
237 case ZigLLVM_EmitBinary:
238 ft = TargetMachine::CGFT_ObjectFile;
239 break;
240 default:
241 abort();
240 {
241 // Set up the per-module pass manager.
242 legacy::PassManager MPM;
243 MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));
244 PMBuilder->populateModulePassManager(MPM);
245
246 // Set output passes.
247 if (dest_bin) {
248 if (target_machine->addPassesToEmitFile(MPM, *dest_bin, nullptr, TargetMachine::CGFT_ObjectFile)) {
249 *error_message = strdup("TargetMachine can't emit an object file");
250 return true;
251 }
242252 }
243
244 if (target_machine->addPassesToEmitFile(MPM, dest, nullptr, ft)) {
245 *error_message = strdup("TargetMachine can't emit a file of this type");
246 return true;
253 if (dest_asm) {
254 if (target_machine->addPassesToEmitFile(MPM, *dest_asm, nullptr, TargetMachine::CGFT_AssemblyFile)) {
255 *error_message = strdup("TargetMachine can't emit an assembly file");
256 return true;
257 }
247258 }
248 }
249259
250 // run per function optimization passes
251 FPM.doInitialization();
252 for (Function &F : *module)
253 if (!F.isDeclaration())
254 FPM.run(F);
255 FPM.doFinalization();
260 // run per function optimization passes
261 FPM.doInitialization();
262 for (Function &F : *module)
263 if (!F.isDeclaration())
264 FPM.run(F);
265 FPM.doFinalization();
256266
257 MPM.run(*module);
267 MPM.run(*module);
258268
259 if (output_type == ZigLLVM_EmitLLVMIr) {
260 if (LLVMPrintModuleToFile(module_ref, filename, error_message)) {
261 return true;
269 if (llvm_ir_filename) {
270 if (LLVMPrintModuleToFile(module_ref, llvm_ir_filename, error_message)) {
271 return true;
272 }
262273 }
263 }
264274
265 if (time_report) {
266 TimerGroup::printAll(errs());
275 if (time_report) {
276 TimerGroup::printAll(errs());
277 }
278
279 // MPM goes out of scope and writes to the out streams
267280 }
281
282 delete dest_asm;
283 delete dest_bin;
284
268285 return false;
269286}
270287
src/zig_llvm.h+3-10
......@@ -46,17 +46,10 @@ ZIG_EXTERN_C void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R);
4646ZIG_EXTERN_C char *ZigLLVMGetHostCPUName(void);
4747ZIG_EXTERN_C char *ZigLLVMGetNativeFeatures(void);
4848
49// We use a custom enum here since LLVM does not expose LLVMIr as an emit
50// output through the same mechanism as assembly/binary.
51enum ZigLLVM_EmitOutputType {
52 ZigLLVM_EmitAssembly,
53 ZigLLVM_EmitBinary,
54 ZigLLVM_EmitLLVMIr,
55};
56
5749ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
58 const char *filename, enum ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug,
59 bool is_small, bool time_report);
50 char **error_message, bool is_debug,
51 bool is_small, bool time_report,
52 const char *asm_filename, const char *bin_filename, const char *llvm_ir_filename);
6053
6154ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Triple,
6255 const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc,