| author | |
| committer | |
| log | d7968c6d33b054a8293edd89ce248f385e108469 |
| tree | 6f8120d2bb3187a90ba5e855c87332386141bf63 |
| parent | dba12cd693495009ae624393337a04e80b0ea565 |
| signature |
example: zig build-obj test.zig -femit-llvm-ir -femit-asm
this will generate all three: test.o test.s test.ll8 files changed, 173 insertions(+), 170 deletions(-)
lib/std/build.zig+6-9| ... | @@ -1155,9 +1155,9 @@ pub const LibExeObjStep = struct { | ... | @@ -1155,9 +1155,9 @@ pub const LibExeObjStep = struct { |
| 1155 | frameworks: BufSet, | 1155 | frameworks: BufSet, |
| 1156 | verbose_link: bool, | 1156 | verbose_link: bool, |
| 1157 | verbose_cc: bool, | 1157 | verbose_cc: bool, |
| 1158 | emit_ir: bool, | 1158 | emit_llvm_ir: bool = false, |
| 1159 | emit_asm: bool, | 1159 | emit_asm: bool = false, |
| 1160 | emit_bin: bool, | 1160 | emit_bin: bool = true, |
| 1161 | disable_gen_h: bool, | 1161 | disable_gen_h: bool, |
| 1162 | bundle_compiler_rt: bool, | 1162 | bundle_compiler_rt: bool, |
| 1163 | disable_stack_probing: bool, | 1163 | disable_stack_probing: bool, |
| ... | @@ -1288,9 +1288,6 @@ pub const LibExeObjStep = struct { | ... | @@ -1288,9 +1288,6 @@ pub const LibExeObjStep = struct { |
| 1288 | .builder = builder, | 1288 | .builder = builder, |
| 1289 | .verbose_link = false, | 1289 | .verbose_link = false, |
| 1290 | .verbose_cc = false, | 1290 | .verbose_cc = false, |
| 1291 | .emit_ir = false, | ||
| 1292 | .emit_asm = false, | ||
| 1293 | .emit_bin = true, | ||
| 1294 | .build_mode = builtin.Mode.Debug, | 1291 | .build_mode = builtin.Mode.Debug, |
| 1295 | .is_dynamic = is_dynamic, | 1292 | .is_dynamic = is_dynamic, |
| 1296 | .kind = kind, | 1293 | .kind = kind, |
| ... | @@ -1947,9 +1944,9 @@ pub const LibExeObjStep = struct { | ... | @@ -1947,9 +1944,9 @@ pub const LibExeObjStep = struct { |
| 1947 | if (builder.verbose_link or self.verbose_link) zig_args.append("--verbose-link") catch unreachable; | 1944 | if (builder.verbose_link or self.verbose_link) zig_args.append("--verbose-link") catch unreachable; |
| 1948 | if (builder.verbose_cc or self.verbose_cc) zig_args.append("--verbose-cc") catch unreachable; | 1945 | if (builder.verbose_cc or self.verbose_cc) zig_args.append("--verbose-cc") catch unreachable; |
| 1949 | 1946 | ||
| 1950 | try zig_args.append(if (self.emit_ir) "-femit-llvm-ir" else "-fno-emit-llvm-ir"); | 1947 | if (self.emit_llvm_ir) try zig_args.append("-femit-llvm-ir"); |
| 1951 | try zig_args.append(if (self.emit_asm) "-femit-asm" else "-fno-emit-asm"); | 1948 | if (self.emit_asm) try zig_args.append("-femit-asm"); |
| 1952 | try zig_args.append(if (self.emit_bin) "-femit-bin" else "-fno-emit-bin"); | 1949 | if (!self.emit_bin) try zig_args.append("-fno-emit-bin"); |
| 1953 | 1950 | ||
| 1954 | if (self.strip) { | 1951 | if (self.strip) { |
| 1955 | try zig_args.append("--strip"); | 1952 | try zig_args.append("--strip"); |
src/all_types.hpp+6-4| ... | @@ -2136,8 +2136,10 @@ struct CodeGen { | ... | @@ -2136,8 +2136,10 @@ struct CodeGen { |
| 2136 | 2136 | ||
| 2137 | Buf llvm_triple_str; | 2137 | Buf llvm_triple_str; |
| 2138 | Buf global_asm; | 2138 | Buf global_asm; |
| 2139 | Buf output_file_path; | ||
| 2140 | Buf o_file_output_path; | 2139 | Buf o_file_output_path; |
| 2140 | Buf bin_file_output_path; | ||
| 2141 | Buf asm_file_output_path; | ||
| 2142 | Buf llvm_ir_file_output_path; | ||
| 2141 | Buf *cache_dir; | 2143 | Buf *cache_dir; |
| 2142 | // As an input parameter, mutually exclusive with enable_cache. But it gets | 2144 | // As an input parameter, mutually exclusive with enable_cache. But it gets |
| 2143 | // populated in codegen_build_and_link. | 2145 | // populated in codegen_build_and_link. |
| ... | @@ -2198,8 +2200,6 @@ struct CodeGen { | ... | @@ -2198,8 +2200,6 @@ struct CodeGen { |
| 2198 | bool verbose_cimport; | 2200 | bool verbose_cimport; |
| 2199 | bool verbose_cc; | 2201 | bool verbose_cc; |
| 2200 | bool verbose_llvm_cpu_features; | 2202 | bool verbose_llvm_cpu_features; |
| 2201 | bool emit_asm; | ||
| 2202 | bool emit_llvm_ir; | ||
| 2203 | bool error_during_imports; | 2203 | bool error_during_imports; |
| 2204 | bool generate_error_name_table; | 2204 | bool generate_error_name_table; |
| 2205 | bool enable_cache; // mutually exclusive with output_dir | 2205 | bool enable_cache; // mutually exclusive with output_dir |
| ... | @@ -2253,7 +2253,9 @@ struct CodeGen { | ... | @@ -2253,7 +2253,9 @@ struct CodeGen { |
| 2253 | bool function_sections; | 2253 | bool function_sections; |
| 2254 | bool enable_dump_analysis; | 2254 | bool enable_dump_analysis; |
| 2255 | bool enable_doc_generation; | 2255 | bool enable_doc_generation; |
| 2256 | bool disable_bin_generation; | 2256 | bool emit_bin; |
| 2257 | bool emit_asm; | ||
| 2258 | bool emit_llvm_ir; | ||
| 2257 | bool test_is_evented; | 2259 | bool test_is_evented; |
| 2258 | CodeModel code_model; | 2260 | CodeModel code_model; |
| 2259 | 2261 |
src/codegen.cpp+49-51| ... | @@ -7915,54 +7915,48 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -7915,54 +7915,48 @@ static void do_code_gen(CodeGen *g) { |
| 7915 | } | 7915 | } |
| 7916 | } | 7916 | } |
| 7917 | 7917 | ||
| 7918 | void codegen_set_emit_asm(CodeGen *g, bool emit) { | ||
| 7919 | g->emit_asm = emit; | ||
| 7920 | } | ||
| 7921 | |||
| 7922 | void codegen_set_emit_llvm_ir(CodeGen *g, bool emit) { | ||
| 7923 | g->emit_llvm_ir = emit; | ||
| 7924 | } | ||
| 7925 | |||
| 7926 | static void zig_llvm_emit_output(CodeGen *g) { | 7918 | static void zig_llvm_emit_output(CodeGen *g) { |
| 7927 | g->pass1_arena->destruct(&heap::c_allocator); | 7919 | g->pass1_arena->destruct(&heap::c_allocator); |
| 7928 | g->pass1_arena = nullptr; | 7920 | g->pass1_arena = nullptr; |
| 7929 | 7921 | ||
| 7930 | bool is_small = g->build_mode == BuildModeSmallRelease; | 7922 | bool is_small = g->build_mode == BuildModeSmallRelease; |
| 7931 | 7923 | ||
| 7932 | Buf *output_path = &g->o_file_output_path; | ||
| 7933 | char *err_msg = nullptr; | 7924 | char *err_msg = nullptr; |
| 7934 | if (!g->disable_bin_generation) { | 7925 | const char *asm_filename = nullptr; |
| 7935 | if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), | 7926 | const char *bin_filename = nullptr; |
| 7936 | ZigLLVM_EmitBinary, &err_msg, g->build_mode == BuildModeDebug, is_small, | 7927 | const char *llvm_ir_filename = nullptr; |
| 7937 | g->enable_time_report)) | 7928 | |
| 7938 | { | 7929 | if (g->emit_bin) bin_filename = buf_ptr(&g->o_file_output_path); |
| 7939 | zig_panic("unable to write object file %s: %s", buf_ptr(output_path), err_msg); | 7930 | if (g->emit_asm) asm_filename = buf_ptr(&g->asm_file_output_path); |
| 7940 | } | 7931 | if (g->emit_llvm_ir) llvm_ir_filename = buf_ptr(&g->llvm_ir_file_output_path); |
| 7941 | validate_inline_fns(g); | 7932 | |
| 7942 | g->link_objects.append(output_path); | 7933 | // Unfortunately, LLVM shits the bed when we ask for both binary and assembly. So we call the entire |
| 7943 | if (g->bundle_compiler_rt && (g->out_type == OutTypeObj || | 7934 | // pipeline multiple times if this is requested. |
| 7944 | (g->out_type == OutTypeLib && !g->is_dynamic))) | 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)) | ||
| 7945 | { | 7938 | { |
| 7946 | zig_link_add_compiler_rt(g, g->sub_progress_node); | 7939 | fprintf(stderr, "LLVM failed to emit file: %s\n", err_msg); |
| 7940 | exit(1); | ||
| 7947 | } | 7941 | } |
| 7942 | bin_filename = nullptr; | ||
| 7943 | llvm_ir_filename = nullptr; | ||
| 7948 | } | 7944 | } |
| 7949 | if (g->emit_asm) { | 7945 | |
| 7950 | if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), | 7946 | if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, &err_msg, g->build_mode == BuildModeDebug, |
| 7951 | ZigLLVM_EmitAssembly, &err_msg, g->build_mode == BuildModeDebug, is_small, | 7947 | is_small, g->enable_time_report, asm_filename, bin_filename, llvm_ir_filename)) |
| 7952 | g->enable_time_report)) | 7948 | { |
| 7953 | { | 7949 | fprintf(stderr, "LLVM failed to emit file: %s\n", err_msg); |
| 7954 | zig_panic("unable to write assembly file %s: %s", buf_ptr(output_path), err_msg); | 7950 | exit(1); |
| 7955 | } | ||
| 7956 | validate_inline_fns(g); | ||
| 7957 | } | 7951 | } |
| 7958 | if (g->emit_llvm_ir) { | 7952 | |
| 7959 | if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), | 7953 | validate_inline_fns(g); |
| 7960 | ZigLLVM_EmitLLVMIr, &err_msg, g->build_mode == BuildModeDebug, is_small, | 7954 | |
| 7961 | g->enable_time_report)) | 7955 | if (g->emit_bin) { |
| 7962 | { | 7956 | g->link_objects.append(&g->o_file_output_path); |
| 7963 | zig_panic("unable to write llvm-ir file %s: %s", buf_ptr(output_path), err_msg); | 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); | ||
| 7964 | } | 7959 | } |
| 7965 | validate_inline_fns(g); | ||
| 7966 | } | 7960 | } |
| 7967 | 7961 | ||
| 7968 | LLVMDisposeModule(g->module); | 7962 | LLVMDisposeModule(g->module); |
| ... | @@ -10446,7 +10440,9 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { | ... | @@ -10446,7 +10440,9 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { |
| 10446 | cache_bool(ch, g->function_sections); | 10440 | cache_bool(ch, g->function_sections); |
| 10447 | cache_bool(ch, g->enable_dump_analysis); | 10441 | cache_bool(ch, g->enable_dump_analysis); |
| 10448 | cache_bool(ch, g->enable_doc_generation); | 10442 | cache_bool(ch, g->enable_doc_generation); |
| 10449 | 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); | ||
| 10450 | cache_buf_opt(ch, g->mmacosx_version_min); | 10446 | cache_buf_opt(ch, g->mmacosx_version_min); |
| 10451 | cache_buf_opt(ch, g->mios_version_min); | 10447 | cache_buf_opt(ch, g->mios_version_min); |
| 10452 | cache_usize(ch, g->version_major); | 10448 | cache_usize(ch, g->version_major); |
| ... | @@ -10491,15 +10487,15 @@ static void resolve_out_paths(CodeGen *g) { | ... | @@ -10491,15 +10487,15 @@ static void resolve_out_paths(CodeGen *g) { |
| 10491 | assert(g->output_dir != nullptr); | 10487 | assert(g->output_dir != nullptr); |
| 10492 | assert(g->root_out_name != nullptr); | 10488 | assert(g->root_out_name != nullptr); |
| 10493 | 10489 | ||
| 10494 | Buf *out_basename = buf_create_from_buf(g->root_out_name); | 10490 | if (g->emit_bin) { |
| 10495 | Buf *o_basename = buf_create_from_buf(g->root_out_name); | 10491 | Buf *out_basename = buf_create_from_buf(g->root_out_name); |
| 10496 | if (!g->disable_bin_generation) { | 10492 | Buf *o_basename = buf_create_from_buf(g->root_out_name); |
| 10497 | switch (g->out_type) { | 10493 | switch (g->out_type) { |
| 10498 | case OutTypeUnknown: | 10494 | case OutTypeUnknown: |
| 10499 | zig_unreachable(); | 10495 | zig_unreachable(); |
| 10500 | case OutTypeObj: | 10496 | case OutTypeObj: |
| 10501 | if (g->enable_cache && g->link_objects.length == 1 && !need_llvm_module(g)) { | 10497 | 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)); | 10498 | buf_init_from_buf(&g->bin_file_output_path, g->link_objects.at(0)); |
| 10503 | return; | 10499 | return; |
| 10504 | } | 10500 | } |
| 10505 | if (need_llvm_module(g) && g->link_objects.length != 0 && !g->enable_cache && | 10501 | if (need_llvm_module(g) && g->link_objects.length != 0 && !g->enable_cache && |
| ... | @@ -10524,20 +10520,21 @@ static void resolve_out_paths(CodeGen *g) { | ... | @@ -10524,20 +10520,21 @@ static void resolve_out_paths(CodeGen *g) { |
| 10524 | g->version_major, g->version_minor, g->version_patch)); | 10520 | g->version_major, g->version_minor, g->version_patch)); |
| 10525 | break; | 10521 | break; |
| 10526 | } | 10522 | } |
| 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); | ||
| 10527 | } | 10525 | } |
| 10528 | else if (g->emit_asm) { | 10526 | if (g->emit_asm) { |
| 10527 | Buf *asm_basename = buf_create_from_buf(g->root_out_name); | ||
| 10529 | const char *asm_ext = target_asm_file_ext(g->zig_target); | 10528 | const char *asm_ext = target_asm_file_ext(g->zig_target); |
| 10530 | buf_append_str(o_basename, asm_ext); | 10529 | buf_append_str(asm_basename, asm_ext); |
| 10531 | buf_append_str(out_basename, asm_ext); | 10530 | os_path_join(g->output_dir, asm_basename, &g->asm_file_output_path); |
| 10532 | } | 10531 | } |
| 10533 | else if (g->emit_llvm_ir) { | 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); | 10534 | const char *llvm_ir_ext = target_llvm_ir_file_ext(g->zig_target); |
| 10535 | buf_append_str(o_basename, llvm_ir_ext); | 10535 | buf_append_str(llvm_ir_basename, llvm_ir_ext); |
| 10536 | buf_append_str(out_basename, llvm_ir_ext); | 10536 | os_path_join(g->output_dir, llvm_ir_basename, &g->llvm_ir_file_output_path); |
| 10537 | } | 10537 | } |
| 10538 | |||
| 10539 | os_path_join(g->output_dir, o_basename, &g->o_file_output_path); | ||
| 10540 | os_path_join(g->output_dir, out_basename, &g->output_file_path); | ||
| 10541 | } | 10538 | } |
| 10542 | 10539 | ||
| 10543 | void codegen_build_and_link(CodeGen *g) { | 10540 | void codegen_build_and_link(CodeGen *g) { |
| ... | @@ -10699,7 +10696,7 @@ void codegen_build_and_link(CodeGen *g) { | ... | @@ -10699,7 +10696,7 @@ void codegen_build_and_link(CodeGen *g) { |
| 10699 | // If there is more than one object, we have to link them (with -r). | 10696 | // If there is more than one object, we have to link them (with -r). |
| 10700 | // Finally, if we didn't make an object from zig source, and we don't have caching enabled, | 10697 | // Finally, if we didn't make an object from zig source, and we don't have caching enabled, |
| 10701 | // then we have an object from C source that we must copy to the output dir which we do with a -r link. | 10698 | // then we have an object from C source that we must copy to the output dir which we do with a -r link. |
| 10702 | if (!g->disable_bin_generation && | 10699 | if (g->emit_bin && |
| 10703 | (g->out_type != OutTypeObj || g->link_objects.length > 1 || | 10700 | (g->out_type != OutTypeObj || g->link_objects.length > 1 || |
| 10704 | (!need_llvm_module(g) && !g->enable_cache))) | 10701 | (!need_llvm_module(g) && !g->enable_cache))) |
| 10705 | { | 10702 | { |
| ... | @@ -10777,6 +10774,7 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget | ... | @@ -10777,6 +10774,7 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget |
| 10777 | Stage2LibCInstallation *libc, Buf *cache_dir, bool is_test_build, Stage2ProgressNode *progress_node) | 10774 | Stage2LibCInstallation *libc, Buf *cache_dir, bool is_test_build, Stage2ProgressNode *progress_node) |
| 10778 | { | 10775 | { |
| 10779 | CodeGen *g = heap::c_allocator.create<CodeGen>(); | 10776 | CodeGen *g = heap::c_allocator.create<CodeGen>(); |
| 10777 | g->emit_bin = true; | ||
| 10780 | g->pass1_arena = heap::ArenaAllocator::construct(&heap::c_allocator, &heap::c_allocator, "pass1"); | 10778 | g->pass1_arena = heap::ArenaAllocator::construct(&heap::c_allocator, &heap::c_allocator, "pass1"); |
| 10781 | g->main_progress_node = progress_node; | 10779 | g->main_progress_node = progress_node; |
| 10782 | 10780 |
src/codegen.hpp-3| ... | @@ -26,9 +26,6 @@ void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len); | ... | @@ -26,9 +26,6 @@ void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len); |
| 26 | void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len); | 26 | void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len); |
| 27 | void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath); | 27 | void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath); |
| 28 | 28 | ||
| 29 | void codegen_set_emit_asm(CodeGen *codegen, bool emit); | ||
| 30 | void codegen_set_emit_llvm_ir(CodeGen *codegen, bool emit); | ||
| 31 | |||
| 32 | void codegen_set_strip(CodeGen *codegen, bool strip); | 29 | void codegen_set_strip(CodeGen *codegen, bool strip); |
| 33 | void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color); | 30 | void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color); |
| 34 | void codegen_set_out_name(CodeGen *codegen, Buf *out_name); | 31 | void 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 | ... | @@ -605,7 +605,7 @@ static const char *build_libc_object(CodeGen *parent_gen, const char *name, CFil |
| 605 | c_source_files.append(c_file); | 605 | c_source_files.append(c_file); |
| 606 | child_gen->c_source_files = c_source_files; | 606 | child_gen->c_source_files = c_source_files; |
| 607 | codegen_build_and_link(child_gen); | 607 | 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); |
| 609 | } | 609 | } |
| 610 | 610 | ||
| 611 | static const char *path_from_zig_lib(CodeGen *g, const char *dir, const char *subpath) { | 611 | 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 | ... | @@ -682,7 +682,7 @@ static const char *build_libunwind(CodeGen *parent, Stage2ProgressNode *progress |
| 682 | } | 682 | } |
| 683 | child_gen->c_source_files = c_source_files; | 683 | child_gen->c_source_files = c_source_files; |
| 684 | codegen_build_and_link(child_gen); | 684 | 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); |
| 686 | } | 686 | } |
| 687 | 687 | ||
| 688 | static void mingw_add_cc_args(CodeGen *parent, CFile *c_file) { | 688 | 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 | ... | @@ -1123,7 +1123,7 @@ static const char *build_musl(CodeGen *parent, Stage2ProgressNode *progress_node |
| 1123 | 1123 | ||
| 1124 | child_gen->c_source_files = c_source_files; | 1124 | child_gen->c_source_files = c_source_files; |
| 1125 | codegen_build_and_link(child_gen); | 1125 | 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); |
| 1127 | } | 1127 | } |
| 1128 | 1128 | ||
| 1129 | static void add_msvcrt_os_dep(CodeGen *parent, CodeGen *child_gen, const char *src_path) { | 1129 | 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 | ... | @@ -1253,7 +1253,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr |
| 1253 | child_gen->c_source_files.append(c_file); | 1253 | child_gen->c_source_files.append(c_file); |
| 1254 | } | 1254 | } |
| 1255 | codegen_build_and_link(child_gen); | 1255 | 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); |
| 1257 | } else if (strcmp(file, "msvcrt-os.lib") == 0) { | 1257 | } else if (strcmp(file, "msvcrt-os.lib") == 0) { |
| 1258 | CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "msvcrt-os", progress_node); | 1258 | CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "msvcrt-os", progress_node); |
| 1259 | 1259 | ||
| ... | @@ -1270,7 +1270,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr | ... | @@ -1270,7 +1270,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr |
| 1270 | } | 1270 | } |
| 1271 | } | 1271 | } |
| 1272 | codegen_build_and_link(child_gen); | 1272 | 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); |
| 1274 | } else if (strcmp(file, "mingwex.lib") == 0) { | 1274 | } else if (strcmp(file, "mingwex.lib") == 0) { |
| 1275 | CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "mingwex", progress_node); | 1275 | CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "mingwex", progress_node); |
| 1276 | 1276 | ||
| ... | @@ -1295,7 +1295,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr | ... | @@ -1295,7 +1295,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr |
| 1295 | zig_unreachable(); | 1295 | zig_unreachable(); |
| 1296 | } | 1296 | } |
| 1297 | codegen_build_and_link(child_gen); | 1297 | 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); |
| 1299 | } else { | 1299 | } else { |
| 1300 | zig_unreachable(); | 1300 | zig_unreachable(); |
| 1301 | } | 1301 | } |
| ... | @@ -1365,7 +1365,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr | ... | @@ -1365,7 +1365,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr |
| 1365 | codegen_add_object(child_gen, buf_create_from_str(start_os)); | 1365 | codegen_add_object(child_gen, buf_create_from_str(start_os)); |
| 1366 | codegen_add_object(child_gen, buf_create_from_str(abi_note_o)); | 1366 | codegen_add_object(child_gen, buf_create_from_str(abi_note_o)); |
| 1367 | codegen_build_and_link(child_gen); | 1367 | 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); |
| 1369 | } else if (strcmp(file, "libc_nonshared.a") == 0) { | 1369 | } else if (strcmp(file, "libc_nonshared.a") == 0) { |
| 1370 | CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "c_nonshared", progress_node); | 1370 | CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "c_nonshared", progress_node); |
| 1371 | { | 1371 | { |
| ... | @@ -1445,7 +1445,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr | ... | @@ -1445,7 +1445,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr |
| 1445 | build_libc_object(parent, deps[i].name, c_file, progress_node))); | 1445 | build_libc_object(parent, deps[i].name, c_file, progress_node))); |
| 1446 | } | 1446 | } |
| 1447 | codegen_build_and_link(child_gen); | 1447 | 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); |
| 1449 | } else { | 1449 | } else { |
| 1450 | zig_unreachable(); | 1450 | zig_unreachable(); |
| 1451 | } | 1451 | } |
| ... | @@ -1519,7 +1519,7 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path, | ... | @@ -1519,7 +1519,7 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path, |
| 1519 | child_gen->want_stack_check = WantStackCheckDisabled; | 1519 | child_gen->want_stack_check = WantStackCheckDisabled; |
| 1520 | 1520 | ||
| 1521 | codegen_build_and_link(child_gen); | 1521 | codegen_build_and_link(child_gen); |
| 1522 | return &child_gen->output_file_path; | 1522 | return &child_gen->bin_file_output_path; |
| 1523 | } | 1523 | } |
| 1524 | 1524 | ||
| 1525 | static Buf *build_compiler_rt(CodeGen *parent_gen, OutType child_out_type, Stage2ProgressNode *progress_node) { | 1525 | 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) { | ... | @@ -1681,7 +1681,7 @@ static void construct_linker_job_elf(LinkJob *lj) { |
| 1681 | } else if (is_dyn_lib) { | 1681 | } else if (is_dyn_lib) { |
| 1682 | lj->args.append("-shared"); | 1682 | lj->args.append("-shared"); |
| 1683 | 1683 | ||
| 1684 | assert(buf_len(&g->output_file_path) != 0); | 1684 | assert(buf_len(&g->bin_file_output_path) != 0); |
| 1685 | soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize, buf_ptr(g->root_out_name), g->version_major); | 1685 | soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize, buf_ptr(g->root_out_name), g->version_major); |
| 1686 | } | 1686 | } |
| 1687 | 1687 | ||
| ... | @@ -1690,7 +1690,7 @@ static void construct_linker_job_elf(LinkJob *lj) { | ... | @@ -1690,7 +1690,7 @@ static void construct_linker_job_elf(LinkJob *lj) { |
| 1690 | } | 1690 | } |
| 1691 | 1691 | ||
| 1692 | lj->args.append("-o"); | 1692 | 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)); |
| 1694 | 1694 | ||
| 1695 | if (lj->link_in_crt) { | 1695 | if (lj->link_in_crt) { |
| 1696 | const char *crt1o; | 1696 | const char *crt1o; |
| ... | @@ -1872,7 +1872,7 @@ static void construct_linker_job_wasm(LinkJob *lj) { | ... | @@ -1872,7 +1872,7 @@ static void construct_linker_job_wasm(LinkJob *lj) { |
| 1872 | } | 1872 | } |
| 1873 | lj->args.append("--allow-undefined"); | 1873 | lj->args.append("--allow-undefined"); |
| 1874 | lj->args.append("-o"); | 1874 | 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)); |
| 1876 | 1876 | ||
| 1877 | // .o files | 1877 | // .o files |
| 1878 | for (size_t i = 0; i < g->link_objects.length; i += 1) { | 1878 | for (size_t i = 0; i < g->link_objects.length; i += 1) { |
| ... | @@ -2248,7 +2248,7 @@ static void construct_linker_job_coff(LinkJob *lj) { | ... | @@ -2248,7 +2248,7 @@ static void construct_linker_job_coff(LinkJob *lj) { |
| 2248 | lj->args.append("-DLL"); | 2248 | lj->args.append("-DLL"); |
| 2249 | } | 2249 | } |
| 2250 | 2250 | ||
| 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)))); |
| 2252 | 2252 | ||
| 2253 | if (g->libc_link_lib != nullptr && g->libc != nullptr) { | 2253 | if (g->libc_link_lib != nullptr && g->libc != nullptr) { |
| 2254 | lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->crt_dir))); | 2254 | 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) { | ... | @@ -2501,7 +2501,7 @@ static void construct_linker_job_macho(LinkJob *lj) { |
| 2501 | //lj->args.append("-install_name"); | 2501 | //lj->args.append("-install_name"); |
| 2502 | //lj->args.append(buf_ptr(dylib_install_name)); | 2502 | //lj->args.append(buf_ptr(dylib_install_name)); |
| 2503 | 2503 | ||
| 2504 | assert(buf_len(&g->output_file_path) != 0); | 2504 | assert(buf_len(&g->bin_file_output_path) != 0); |
| 2505 | } | 2505 | } |
| 2506 | 2506 | ||
| 2507 | lj->args.append("-arch"); | 2507 | lj->args.append("-arch"); |
| ... | @@ -2532,14 +2532,14 @@ static void construct_linker_job_macho(LinkJob *lj) { | ... | @@ -2532,14 +2532,14 @@ static void construct_linker_job_macho(LinkJob *lj) { |
| 2532 | } | 2532 | } |
| 2533 | 2533 | ||
| 2534 | lj->args.append("-o"); | 2534 | 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)); |
| 2536 | 2536 | ||
| 2537 | for (size_t i = 0; i < g->rpath_list.length; i += 1) { | 2537 | for (size_t i = 0; i < g->rpath_list.length; i += 1) { |
| 2538 | Buf *rpath = g->rpath_list.at(i); | 2538 | Buf *rpath = g->rpath_list.at(i); |
| 2539 | add_rpath(lj, rpath); | 2539 | add_rpath(lj, rpath); |
| 2540 | } | 2540 | } |
| 2541 | if (is_dyn_lib) { | 2541 | if (is_dyn_lib) { |
| 2542 | add_rpath(lj, &g->output_file_path); | 2542 | add_rpath(lj, &g->bin_file_output_path); |
| 2543 | } | 2543 | } |
| 2544 | 2544 | ||
| 2545 | if (is_dyn_lib) { | 2545 | if (is_dyn_lib) { |
| ... | @@ -2659,14 +2659,14 @@ void codegen_link(CodeGen *g) { | ... | @@ -2659,14 +2659,14 @@ void codegen_link(CodeGen *g) { |
| 2659 | progress_name, strlen(progress_name), 0)); | 2659 | progress_name, strlen(progress_name), 0)); |
| 2660 | } | 2660 | } |
| 2661 | if (g->verbose_link) { | 2661 | 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)); |
| 2663 | for (size_t i = 0; i < file_names.length; i += 1) { | 2663 | for (size_t i = 0; i < file_names.length; i += 1) { |
| 2664 | fprintf(stderr, " %s", file_names.at(i)); | 2664 | fprintf(stderr, " %s", file_names.at(i)); |
| 2665 | } | 2665 | } |
| 2666 | fprintf(stderr, "\n"); | 2666 | fprintf(stderr, "\n"); |
| 2667 | } | 2667 | } |
| 2668 | if (ZigLLVMWriteArchive(buf_ptr(&g->output_file_path), file_names.items, file_names.length, os_type)) { | 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->output_file_path)); | 2669 | fprintf(stderr, "Unable to write archive '%s'\n", buf_ptr(&g->bin_file_output_path)); |
| 2670 | exit(1); | 2670 | exit(1); |
| 2671 | } | 2671 | } |
| 2672 | return; | 2672 | return; |
src/main.cpp+31-32| ... | @@ -62,17 +62,21 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { | ... | @@ -62,17 +62,21 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { |
| 62 | " -fno-stack-check disable stack probing in safe builds\n" | 62 | " -fno-stack-check disable stack probing in safe builds\n" |
| 63 | " -fsanitize-c enable C undefined behavior detection in unsafe builds\n" | 63 | " -fsanitize-c enable C undefined behavior detection in unsafe builds\n" |
| 64 | " -fno-sanitize-c disable C undefined behavior detection in safe builds\n" | 64 | " -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" |
| 66 | " -fPIC enable Position Independent Code\n" | 66 | " -fPIC enable Position Independent Code\n" |
| 67 | " -fno-PIC disable Position Independent Code\n" | 67 | " -fno-PIC disable Position Independent Code\n" |
| 68 | " -ftime-report print timing diagnostics\n" | 68 | " -ftime-report print timing diagnostics\n" |
| 69 | " -fstack-report print stack size diagnostics\n" | 69 | " -fstack-report print stack size diagnostics\n" |
| 70 | #ifdef ZIG_ENABLE_MEM_PROFILE | ||
| 71 | " -fmem-report print memory usage diagnostics\n" | 70 | " -fmem-report print memory usage diagnostics\n" |
| 72 | #endif | ||
| 73 | " -fdump-analysis write analysis.json file with type information\n" | 71 | " -fdump-analysis write analysis.json file with type information\n" |
| 74 | " -femit-docs create a docs/ dir with html documentation\n" | 72 | " -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" | ||
| 76 | " --libc [file] Provide a file which specifies libc paths\n" | 80 | " --libc [file] Provide a file which specifies libc paths\n" |
| 77 | " --name [name] override output name\n" | 81 | " --name [name] override output name\n" |
| 78 | " --output-dir [dir] override output directory (defaults to cwd)\n" | 82 | " --output-dir [dir] override output directory (defaults to cwd)\n" |
| ... | @@ -423,7 +427,7 @@ static int main0(int argc, char **argv) { | ... | @@ -423,7 +427,7 @@ static int main0(int argc, char **argv) { |
| 423 | bool stack_report = false; | 427 | bool stack_report = false; |
| 424 | bool enable_dump_analysis = false; | 428 | bool enable_dump_analysis = false; |
| 425 | bool enable_doc_generation = false; | 429 | bool enable_doc_generation = false; |
| 426 | bool disable_bin_generation = false; | 430 | bool emit_bin = true; |
| 427 | bool emit_asm = false; | 431 | bool emit_asm = false; |
| 428 | bool emit_llvm_ir = false; | 432 | bool emit_llvm_ir = false; |
| 429 | const char *cache_dir = nullptr; | 433 | const char *cache_dir = nullptr; |
| ... | @@ -553,7 +557,7 @@ static int main0(int argc, char **argv) { | ... | @@ -553,7 +557,7 @@ static int main0(int argc, char **argv) { |
| 553 | } | 557 | } |
| 554 | 558 | ||
| 555 | Termination term; | 559 | Termination term; |
| 556 | args.items[0] = buf_ptr(&g->output_file_path); | 560 | args.items[0] = buf_ptr(&g->bin_file_output_path); |
| 557 | os_spawn_process(args, &term); | 561 | os_spawn_process(args, &term); |
| 558 | if (term.how != TerminationIdClean || term.code != 0) { | 562 | if (term.how != TerminationIdClean || term.code != 0) { |
| 559 | fprintf(stderr, "\nBuild failed. The following command failed:\n"); | 563 | fprintf(stderr, "\nBuild failed. The following command failed:\n"); |
| ... | @@ -632,8 +636,6 @@ static int main0(int argc, char **argv) { | ... | @@ -632,8 +636,6 @@ static int main0(int argc, char **argv) { |
| 632 | enable_dump_analysis = true; | 636 | enable_dump_analysis = true; |
| 633 | } else if (strcmp(arg, "-femit-docs") == 0) { | 637 | } else if (strcmp(arg, "-femit-docs") == 0) { |
| 634 | enable_doc_generation = true; | 638 | enable_doc_generation = true; |
| 635 | } else if (strcmp(arg, "-fno-emit-bin") == 0) { | ||
| 636 | disable_bin_generation = true; | ||
| 637 | } else if (strcmp(arg, "--enable-valgrind") == 0) { | 639 | } else if (strcmp(arg, "--enable-valgrind") == 0) { |
| 638 | valgrind_support = ValgrindSupportEnabled; | 640 | valgrind_support = ValgrindSupportEnabled; |
| 639 | } else if (strcmp(arg, "--disable-valgrind") == 0) { | 641 | } else if (strcmp(arg, "--disable-valgrind") == 0) { |
| ... | @@ -703,9 +705,9 @@ static int main0(int argc, char **argv) { | ... | @@ -703,9 +705,9 @@ static int main0(int argc, char **argv) { |
| 703 | } else if (strcmp(arg, "--test-evented-io") == 0) { | 705 | } else if (strcmp(arg, "--test-evented-io") == 0) { |
| 704 | test_evented_io = true; | 706 | test_evented_io = true; |
| 705 | } else if (strcmp(arg, "-femit-bin") == 0) { | 707 | } else if (strcmp(arg, "-femit-bin") == 0) { |
| 706 | disable_bin_generation = false; | 708 | emit_bin = true; |
| 707 | } else if (strcmp(arg, "-fno-emit-bin") == 0) { | 709 | } else if (strcmp(arg, "-fno-emit-bin") == 0) { |
| 708 | disable_bin_generation = true; | 710 | emit_bin = false; |
| 709 | } else if (strcmp(arg, "-femit-asm") == 0) { | 711 | } else if (strcmp(arg, "-femit-asm") == 0) { |
| 710 | emit_asm = true; | 712 | emit_asm = true; |
| 711 | } else if (strcmp(arg, "-fno-emit-asm") == 0) { | 713 | } else if (strcmp(arg, "-fno-emit-asm") == 0) { |
| ... | @@ -746,12 +748,12 @@ static int main0(int argc, char **argv) { | ... | @@ -746,12 +748,12 @@ static int main0(int argc, char **argv) { |
| 746 | } else if (strcmp(arg, "--emit") == 0) { | 748 | } else if (strcmp(arg, "--emit") == 0) { |
| 747 | if (strcmp(argv[i], "asm") == 0) { | 749 | if (strcmp(argv[i], "asm") == 0) { |
| 748 | emit_asm = true; | 750 | emit_asm = true; |
| 749 | disable_bin_generation = true; | 751 | emit_bin = false; |
| 750 | } else if (strcmp(argv[i], "bin") == 0) { | 752 | } else if (strcmp(argv[i], "bin") == 0) { |
| 751 | disable_bin_generation = false; | 753 | emit_bin = true; |
| 752 | } else if (strcmp(argv[i], "llvm-ir") == 0) { | 754 | } else if (strcmp(argv[i], "llvm-ir") == 0) { |
| 753 | emit_llvm_ir = true; | 755 | emit_llvm_ir = true; |
| 754 | disable_bin_generation = true; | 756 | emit_bin = false; |
| 755 | } else { | 757 | } else { |
| 756 | fprintf(stderr, "--emit options are 'asm', 'bin', or 'llvm-ir'\n"); | 758 | fprintf(stderr, "--emit options are 'asm', 'bin', or 'llvm-ir'\n"); |
| 757 | return print_error_usage(arg0); | 759 | return print_error_usage(arg0); |
| ... | @@ -1113,8 +1115,8 @@ static int main0(int argc, char **argv) { | ... | @@ -1113,8 +1115,8 @@ static int main0(int argc, char **argv) { |
| 1113 | { | 1115 | { |
| 1114 | fprintf(stderr, "Expected source file argument.\n"); | 1116 | fprintf(stderr, "Expected source file argument.\n"); |
| 1115 | return print_error_usage(arg0); | 1117 | return print_error_usage(arg0); |
| 1116 | } else if (cmd == CmdRun && disable_bin_generation) { | 1118 | } else if (cmd == CmdRun && !emit_bin) { |
| 1117 | fprintf(stderr, "Cannot run non-executable file.\n"); | 1119 | fprintf(stderr, "Cannot run without emitting a binary file.\n"); |
| 1118 | return print_error_usage(arg0); | 1120 | return print_error_usage(arg0); |
| 1119 | } | 1121 | } |
| 1120 | 1122 | ||
| ... | @@ -1191,7 +1193,10 @@ static int main0(int argc, char **argv) { | ... | @@ -1191,7 +1193,10 @@ static int main0(int argc, char **argv) { |
| 1191 | g->enable_stack_report = stack_report; | 1193 | g->enable_stack_report = stack_report; |
| 1192 | g->enable_dump_analysis = enable_dump_analysis; | 1194 | g->enable_dump_analysis = enable_dump_analysis; |
| 1193 | g->enable_doc_generation = enable_doc_generation; | 1195 | g->enable_doc_generation = enable_doc_generation; |
| 1194 | 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 | |||
| 1195 | codegen_set_out_name(g, buf_out_name); | 1200 | codegen_set_out_name(g, buf_out_name); |
| 1196 | codegen_set_lib_version(g, ver_major, ver_minor, ver_patch); | 1201 | codegen_set_lib_version(g, ver_major, ver_minor, ver_patch); |
| 1197 | g->want_single_threaded = want_single_threaded; | 1202 | g->want_single_threaded = want_single_threaded; |
| ... | @@ -1277,9 +1282,6 @@ static int main0(int argc, char **argv) { | ... | @@ -1277,9 +1282,6 @@ static int main0(int argc, char **argv) { |
| 1277 | 1282 | ||
| 1278 | 1283 | ||
| 1279 | if (cmd == CmdBuild || cmd == CmdRun) { | 1284 | if (cmd == CmdBuild || cmd == CmdRun) { |
| 1280 | codegen_set_emit_asm(g, emit_asm); | ||
| 1281 | codegen_set_emit_llvm_ir(g, emit_llvm_ir); | ||
| 1282 | |||
| 1283 | g->enable_cache = get_cache_opt(enable_cache, cmd == CmdRun); | 1285 | g->enable_cache = get_cache_opt(enable_cache, cmd == CmdRun); |
| 1284 | codegen_build_and_link(g); | 1286 | codegen_build_and_link(g); |
| 1285 | if (root_progress_node != nullptr) { | 1287 | if (root_progress_node != nullptr) { |
| ... | @@ -1297,7 +1299,7 @@ static int main0(int argc, char **argv) { | ... | @@ -1297,7 +1299,7 @@ static int main0(int argc, char **argv) { |
| 1297 | mem::print_report(); | 1299 | mem::print_report(); |
| 1298 | #endif | 1300 | #endif |
| 1299 | 1301 | ||
| 1300 | const char *exec_path = buf_ptr(&g->output_file_path); | 1302 | const char *exec_path = buf_ptr(&g->bin_file_output_path); |
| 1301 | ZigList<const char*> args = {0}; | 1303 | ZigList<const char*> args = {0}; |
| 1302 | 1304 | ||
| 1303 | args.append(exec_path); | 1305 | args.append(exec_path); |
| ... | @@ -1317,21 +1319,21 @@ static int main0(int argc, char **argv) { | ... | @@ -1317,21 +1319,21 @@ static int main0(int argc, char **argv) { |
| 1317 | } else if (cmd == CmdBuild) { | 1319 | } else if (cmd == CmdBuild) { |
| 1318 | if (g->enable_cache) { | 1320 | if (g->enable_cache) { |
| 1319 | #if defined(ZIG_OS_WINDOWS) | 1321 | #if defined(ZIG_OS_WINDOWS) |
| 1320 | buf_replace(&g->output_file_path, '/', '\\'); | 1322 | buf_replace(&g->bin_file_output_path, '/', '\\'); |
| 1321 | #endif | 1323 | #endif |
| 1322 | if (final_output_dir_step != nullptr) { | 1324 | if (final_output_dir_step != nullptr) { |
| 1323 | Buf *dest_basename = buf_alloc(); | 1325 | Buf *dest_basename = buf_alloc(); |
| 1324 | os_path_split(&g->output_file_path, nullptr, dest_basename); | 1326 | os_path_split(&g->bin_file_output_path, nullptr, dest_basename); |
| 1325 | Buf *dest_path = buf_alloc(); | 1327 | Buf *dest_path = buf_alloc(); |
| 1326 | os_path_join(final_output_dir_step, dest_basename, dest_path); | 1328 | os_path_join(final_output_dir_step, dest_basename, dest_path); |
| 1327 | 1329 | ||
| 1328 | if ((err = os_update_file(&g->output_file_path, dest_path))) { | 1330 | if ((err = os_update_file(&g->bin_file_output_path, dest_path))) { |
| 1329 | fprintf(stderr, "unable to copy %s to %s: %s\n", buf_ptr(&g->output_file_path), | 1331 | fprintf(stderr, "unable to copy %s to %s: %s\n", buf_ptr(&g->bin_file_output_path), |
| 1330 | buf_ptr(dest_path), err_str(err)); | 1332 | buf_ptr(dest_path), err_str(err)); |
| 1331 | return main_exit(root_progress_node, EXIT_FAILURE); | 1333 | return main_exit(root_progress_node, EXIT_FAILURE); |
| 1332 | } | 1334 | } |
| 1333 | } else { | 1335 | } else { |
| 1334 | if (printf("%s\n", buf_ptr(&g->output_file_path)) < 0) | 1336 | if (printf("%s\n", buf_ptr(&g->bin_file_output_path)) < 0) |
| 1335 | return main_exit(root_progress_node, EXIT_FAILURE); | 1337 | return main_exit(root_progress_node, EXIT_FAILURE); |
| 1336 | } | 1338 | } |
| 1337 | } | 1339 | } |
| ... | @@ -1346,9 +1348,6 @@ static int main0(int argc, char **argv) { | ... | @@ -1346,9 +1348,6 @@ static int main0(int argc, char **argv) { |
| 1346 | codegen_print_timing_report(g, stderr); | 1348 | codegen_print_timing_report(g, stderr); |
| 1347 | return main_exit(root_progress_node, EXIT_SUCCESS); | 1349 | return main_exit(root_progress_node, EXIT_SUCCESS); |
| 1348 | } else if (cmd == CmdTest) { | 1350 | } else if (cmd == CmdTest) { |
| 1349 | codegen_set_emit_asm(g, emit_asm); | ||
| 1350 | codegen_set_emit_llvm_ir(g, emit_llvm_ir); | ||
| 1351 | |||
| 1352 | ZigTarget native; | 1351 | ZigTarget native; |
| 1353 | get_native_target(&native); | 1352 | get_native_target(&native); |
| 1354 | 1353 | ||
| ... | @@ -1367,17 +1366,17 @@ static int main0(int argc, char **argv) { | ... | @@ -1367,17 +1366,17 @@ static int main0(int argc, char **argv) { |
| 1367 | zig_print_stack_report(g, stdout); | 1366 | zig_print_stack_report(g, stdout); |
| 1368 | } | 1367 | } |
| 1369 | 1368 | ||
| 1370 | if (g->disable_bin_generation) { | 1369 | if (!g->emit_bin) { |
| 1371 | fprintf(stderr, "Semantic analysis complete. No binary produced due to -fno-emit-bin.\n"); | 1370 | fprintf(stderr, "Semantic analysis complete. No binary produced due to -fno-emit-bin.\n"); |
| 1372 | return main_exit(root_progress_node, EXIT_SUCCESS); | 1371 | return main_exit(root_progress_node, EXIT_SUCCESS); |
| 1373 | } | 1372 | } |
| 1374 | 1373 | ||
| 1375 | Buf *test_exe_path_unresolved = &g->output_file_path; | 1374 | Buf *test_exe_path_unresolved = &g->bin_file_output_path; |
| 1376 | Buf *test_exe_path = buf_alloc(); | 1375 | Buf *test_exe_path = buf_alloc(); |
| 1377 | *test_exe_path = os_path_resolve(&test_exe_path_unresolved, 1); | 1376 | *test_exe_path = os_path_resolve(&test_exe_path_unresolved, 1); |
| 1378 | 1377 | ||
| 1379 | if (disable_bin_generation) { | 1378 | if (!g->emit_bin) { |
| 1380 | fprintf(stderr, "Created %s but skipping execution because it is non executable.\n", | 1379 | fprintf(stderr, "Created %s but skipping execution because no binary generated.\n", |
| 1381 | buf_ptr(test_exe_path)); | 1380 | buf_ptr(test_exe_path)); |
| 1382 | return main_exit(root_progress_node, EXIT_SUCCESS); | 1381 | return main_exit(root_progress_node, EXIT_SUCCESS); |
| 1383 | } | 1382 | } |
src/zig_llvm.cpp+59-42| ... | @@ -161,17 +161,32 @@ unsigned ZigLLVMDataLayoutGetProgramAddressSpace(LLVMTargetDataRef TD) { | ... | @@ -161,17 +161,32 @@ unsigned ZigLLVMDataLayoutGetProgramAddressSpace(LLVMTargetDataRef TD) { |
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref, | 163 | bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref, |
| 164 | const char *filename, ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug, | 164 | char **error_message, bool is_debug, |
| 165 | bool is_small, bool time_report) | 165 | bool is_small, bool time_report, |
| 166 | const char *asm_filename, const char *bin_filename, const char *llvm_ir_filename) | ||
| 166 | { | 167 | { |
| 167 | TimePassesIsEnabled = time_report; | 168 | TimePassesIsEnabled = time_report; |
| 168 | 169 | ||
| 169 | std::error_code EC; | 170 | raw_fd_ostream *dest_asm = nullptr; |
| 170 | raw_fd_ostream dest(filename, EC, sys::fs::F_None); | 171 | raw_fd_ostream *dest_bin = nullptr; |
| 171 | if (EC) { | 172 | |
| 172 | *error_message = strdup((const char *)StringRef(EC.message()).bytes_begin()); | 173 | if (asm_filename) { |
| 173 | return true; | 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 | } | ||
| 174 | } | 180 | } |
| 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 | |||
| 175 | TargetMachine* target_machine = reinterpret_cast<TargetMachine*>(targ_machine_ref); | 190 | TargetMachine* target_machine = reinterpret_cast<TargetMachine*>(targ_machine_ref); |
| 176 | target_machine->setO0WantsFastISel(true); | 191 | target_machine->setO0WantsFastISel(true); |
| 177 | 192 | ||
| ... | @@ -222,49 +237,51 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM | ... | @@ -222,49 +237,51 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM |
| 222 | } | 237 | } |
| 223 | PMBuilder->populateFunctionPassManager(FPM); | 238 | PMBuilder->populateFunctionPassManager(FPM); |
| 224 | 239 | ||
| 225 | // Set up the per-module pass manager. | 240 | { |
| 226 | legacy::PassManager MPM; | 241 | // Set up the per-module pass manager. |
| 227 | MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis())); | 242 | legacy::PassManager MPM; |
| 228 | PMBuilder->populateModulePassManager(MPM); | 243 | MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis())); |
| 229 | 244 | PMBuilder->populateModulePassManager(MPM); | |
| 230 | // Set output pass. | 245 | |
| 231 | TargetMachine::CodeGenFileType ft; | 246 | // Set output passes. |
| 232 | if (output_type != ZigLLVM_EmitLLVMIr) { | 247 | if (dest_bin) { |
| 233 | switch (output_type) { | 248 | if (target_machine->addPassesToEmitFile(MPM, *dest_bin, nullptr, TargetMachine::CGFT_ObjectFile)) { |
| 234 | case ZigLLVM_EmitAssembly: | 249 | *error_message = strdup("TargetMachine can't emit an object file"); |
| 235 | ft = TargetMachine::CGFT_AssemblyFile; | 250 | return true; |
| 236 | break; | 251 | } |
| 237 | case ZigLLVM_EmitBinary: | ||
| 238 | ft = TargetMachine::CGFT_ObjectFile; | ||
| 239 | break; | ||
| 240 | default: | ||
| 241 | abort(); | ||
| 242 | } | 252 | } |
| 243 | 253 | if (dest_asm) { | |
| 244 | if (target_machine->addPassesToEmitFile(MPM, dest, nullptr, ft)) { | 254 | if (target_machine->addPassesToEmitFile(MPM, *dest_asm, nullptr, TargetMachine::CGFT_AssemblyFile)) { |
| 245 | *error_message = strdup("TargetMachine can't emit a file of this type"); | 255 | *error_message = strdup("TargetMachine can't emit an assembly file"); |
| 246 | return true; | 256 | return true; |
| 257 | } | ||
| 247 | } | 258 | } |
| 248 | } | ||
| 249 | 259 | ||
| 250 | // run per function optimization passes | 260 | // run per function optimization passes |
| 251 | FPM.doInitialization(); | 261 | FPM.doInitialization(); |
| 252 | for (Function &F : *module) | 262 | for (Function &F : *module) |
| 253 | if (!F.isDeclaration()) | 263 | if (!F.isDeclaration()) |
| 254 | FPM.run(F); | 264 | FPM.run(F); |
| 255 | FPM.doFinalization(); | 265 | FPM.doFinalization(); |
| 256 | 266 | ||
| 257 | MPM.run(*module); | 267 | MPM.run(*module); |
| 258 | 268 | ||
| 259 | if (output_type == ZigLLVM_EmitLLVMIr) { | 269 | if (llvm_ir_filename) { |
| 260 | if (LLVMPrintModuleToFile(module_ref, filename, error_message)) { | 270 | if (LLVMPrintModuleToFile(module_ref, llvm_ir_filename, error_message)) { |
| 261 | return true; | 271 | return true; |
| 272 | } | ||
| 262 | } | 273 | } |
| 263 | } | ||
| 264 | 274 | ||
| 265 | if (time_report) { | 275 | if (time_report) { |
| 266 | TimerGroup::printAll(errs()); | 276 | TimerGroup::printAll(errs()); |
| 277 | } | ||
| 278 | |||
| 279 | // MPM goes out of scope and writes to the out streams | ||
| 267 | } | 280 | } |
| 281 | |||
| 282 | delete dest_asm; | ||
| 283 | delete dest_bin; | ||
| 284 | |||
| 268 | return false; | 285 | return false; |
| 269 | } | 286 | } |
| 270 | 287 |
src/zig_llvm.h+3-10| ... | @@ -46,17 +46,10 @@ ZIG_EXTERN_C void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R); | ... | @@ -46,17 +46,10 @@ ZIG_EXTERN_C void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R); |
| 46 | ZIG_EXTERN_C char *ZigLLVMGetHostCPUName(void); | 46 | ZIG_EXTERN_C char *ZigLLVMGetHostCPUName(void); |
| 47 | ZIG_EXTERN_C char *ZigLLVMGetNativeFeatures(void); | 47 | ZIG_EXTERN_C char *ZigLLVMGetNativeFeatures(void); |
| 48 | 48 | ||
| 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. | ||
| 51 | enum ZigLLVM_EmitOutputType { | ||
| 52 | ZigLLVM_EmitAssembly, | ||
| 53 | ZigLLVM_EmitBinary, | ||
| 54 | ZigLLVM_EmitLLVMIr, | ||
| 55 | }; | ||
| 56 | |||
| 57 | ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref, | 49 | ZIG_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, | 50 | char **error_message, bool is_debug, |
| 59 | bool is_small, bool time_report); | 51 | bool is_small, bool time_report, |
| 52 | const char *asm_filename, const char *bin_filename, const char *llvm_ir_filename); | ||
| 60 | 53 | ||
| 61 | ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Triple, | 54 | ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Triple, |
| 62 | const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, | 55 | const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc, |