| ... | ... | @@ -849,10 +849,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 849 | 849 | if (options.use_llvm) |explicit| |
| 850 | 850 | break :blk explicit; |
| 851 | 851 | |
| 852 | | // If we have no zig code to compile, no need for LLVM. |
| 853 | | if (options.main_pkg == null) |
| 854 | | break :blk false; |
| 855 | | |
| 856 | 852 | // If we are outputting .c code we must use Zig backend. |
| 857 | 853 | if (ofmt == .c) |
| 858 | 854 | break :blk false; |
| ... | ... | @@ -861,6 +857,10 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 861 | 857 | if (options.emit_llvm_ir != null or options.emit_llvm_bc != null) |
| 862 | 858 | break :blk true; |
| 863 | 859 | |
| 860 | // If we have no zig code to compile, no need for LLVM. |
| 861 | if (options.main_pkg == null) |
| 862 | break :blk false; |
| 863 | |
| 864 | 864 | // The stage1 compiler depends on the stage1 C++ LLVM backend |
| 865 | 865 | // to compile zig code. |
| 866 | 866 | if (use_stage1) |
| ... | ... | @@ -876,9 +876,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 876 | 876 | if (options.use_llvm == true) { |
| 877 | 877 | return error.ZigCompilerNotBuiltWithLLVMExtensions; |
| 878 | 878 | } |
| 879 | | if (options.machine_code_model != .default) { |
| 880 | | return error.MachineCodeModelNotSupportedWithoutLlvm; |
| 881 | | } |
| 882 | 879 | if (options.emit_llvm_ir != null or options.emit_llvm_bc != null) { |
| 883 | 880 | return error.EmittingLlvmModuleRequiresUsingLlvmBackend; |
| 884 | 881 | } |
| ... | ... | @@ -1793,6 +1790,10 @@ pub fn update(self: *Compilation) !void { |
| 1793 | 1790 | } |
| 1794 | 1791 | } |
| 1795 | 1792 | |
| 1793 | // Flush takes care of -femit-bin, but we still have -femit-llvm-ir, -femit-llvm-bc, and |
| 1794 | // -femit-asm to handle, in the case of C objects. |
| 1795 | try self.emitOthers(); |
| 1796 | |
| 1796 | 1797 | // If there are any errors, we anticipate the source files being loaded |
| 1797 | 1798 | // to report error messages. Otherwise we unload all source files to save memory. |
| 1798 | 1799 | // The ZIR needs to stay loaded in memory because (1) Decl objects contain references |
| ... | ... | @@ -1808,6 +1809,37 @@ pub fn update(self: *Compilation) !void { |
| 1808 | 1809 | } |
| 1809 | 1810 | } |
| 1810 | 1811 | |
| 1812 | fn emitOthers(comp: *Compilation) !void { |
| 1813 | if (comp.bin_file.options.output_mode != .Obj or comp.bin_file.options.module != null or |
| 1814 | comp.c_object_table.count() == 0) |
| 1815 | { |
| 1816 | return; |
| 1817 | } |
| 1818 | const obj_path = comp.c_object_table.keys()[0].status.success.object_path; |
| 1819 | const cwd = std.fs.cwd(); |
| 1820 | const ext = std.fs.path.extension(obj_path); |
| 1821 | const basename = obj_path[0 .. obj_path.len - ext.len]; |
| 1822 | // This obj path always ends with the object file extension, but if we change the |
| 1823 | // extension to .ll, .bc, or .s, then it will be the path to those things. |
| 1824 | const outs = [_]struct { |
| 1825 | emit: ?EmitLoc, |
| 1826 | ext: []const u8, |
| 1827 | }{ |
| 1828 | .{ .emit = comp.emit_asm, .ext = ".s" }, |
| 1829 | .{ .emit = comp.emit_llvm_ir, .ext = ".ll" }, |
| 1830 | .{ .emit = comp.emit_llvm_bc, .ext = ".bc" }, |
| 1831 | }; |
| 1832 | for (outs) |out| { |
| 1833 | if (out.emit) |loc| { |
| 1834 | if (loc.directory) |directory| { |
| 1835 | const src_path = try std.fmt.allocPrint(comp.gpa, "{s}{s}", .{ basename, out.ext }); |
| 1836 | defer comp.gpa.free(src_path); |
| 1837 | try cwd.copyFile(src_path, directory.handle, loc.basename, .{}); |
| 1838 | } |
| 1839 | } |
| 1840 | } |
| 1841 | } |
| 1842 | |
| 1811 | 1843 | /// Having the file open for writing is problematic as far as executing the |
| 1812 | 1844 | /// binary is concerned. This will remove the write flag, or close the file, |
| 1813 | 1845 | /// or whatever is needed so that it can be executed. |
| ... | ... | @@ -2764,6 +2796,9 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P |
| 2764 | 2796 | defer man.deinit(); |
| 2765 | 2797 | |
| 2766 | 2798 | man.hash.add(comp.clang_preprocessor_mode); |
| 2799 | man.hash.addOptionalEmitLoc(comp.emit_asm); |
| 2800 | man.hash.addOptionalEmitLoc(comp.emit_llvm_ir); |
| 2801 | man.hash.addOptionalEmitLoc(comp.emit_llvm_bc); |
| 2767 | 2802 | |
| 2768 | 2803 | try man.hashCSource(c_object.src); |
| 2769 | 2804 | |
| ... | ... | @@ -2787,16 +2822,29 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P |
| 2787 | 2822 | comp.bin_file.options.root_name |
| 2788 | 2823 | else |
| 2789 | 2824 | c_source_basename[0 .. c_source_basename.len - std.fs.path.extension(c_source_basename).len]; |
| 2790 | | const o_basename = try std.fmt.allocPrint(arena, "{s}{s}", .{ |
| 2791 | | o_basename_noext, |
| 2792 | | comp.bin_file.options.object_format.fileExt(comp.bin_file.options.target.cpu.arch), |
| 2793 | | }); |
| 2794 | 2825 | |
| 2826 | const o_ext = comp.bin_file.options.object_format.fileExt(comp.bin_file.options.target.cpu.arch); |
| 2795 | 2827 | const digest = if (!comp.disable_c_depfile and try man.hit()) man.final() else blk: { |
| 2796 | 2828 | var argv = std.ArrayList([]const u8).init(comp.gpa); |
| 2797 | 2829 | defer argv.deinit(); |
| 2798 | 2830 | |
| 2799 | | // We can't know the digest until we do the C compiler invocation, so we need a temporary filename. |
| 2831 | // In case we are doing passthrough mode, we need to detect -S and -emit-llvm. |
| 2832 | const out_ext = e: { |
| 2833 | if (!comp.clang_passthrough_mode) |
| 2834 | break :e o_ext; |
| 2835 | if (comp.emit_asm != null) |
| 2836 | break :e ".s"; |
| 2837 | if (comp.emit_llvm_ir != null) |
| 2838 | break :e ".ll"; |
| 2839 | if (comp.emit_llvm_bc != null) |
| 2840 | break :e ".bc"; |
| 2841 | |
| 2842 | break :e o_ext; |
| 2843 | }; |
| 2844 | const o_basename = try std.fmt.allocPrint(arena, "{s}{s}", .{ o_basename_noext, out_ext }); |
| 2845 | |
| 2846 | // We can't know the digest until we do the C compiler invocation, |
| 2847 | // so we need a temporary filename. |
| 2800 | 2848 | const out_obj_path = try comp.tmpFilePath(arena, o_basename); |
| 2801 | 2849 | var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath("tmp", .{}); |
| 2802 | 2850 | defer zig_cache_tmp_dir.close(); |
| ... | ... | @@ -2810,15 +2858,23 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P |
| 2810 | 2858 | try std.fmt.allocPrint(arena, "{s}.d", .{out_obj_path}); |
| 2811 | 2859 | try comp.addCCArgs(arena, &argv, ext, out_dep_path); |
| 2812 | 2860 | |
| 2813 | | try argv.ensureCapacity(argv.items.len + 3); |
| 2861 | try argv.ensureUnusedCapacity(6 + c_object.src.extra_flags.len); |
| 2814 | 2862 | switch (comp.clang_preprocessor_mode) { |
| 2815 | 2863 | .no => argv.appendSliceAssumeCapacity(&[_][]const u8{ "-c", "-o", out_obj_path }), |
| 2816 | 2864 | .yes => argv.appendSliceAssumeCapacity(&[_][]const u8{ "-E", "-o", out_obj_path }), |
| 2817 | 2865 | .stdout => argv.appendAssumeCapacity("-E"), |
| 2818 | 2866 | } |
| 2819 | | |
| 2820 | | try argv.append(c_object.src.src_path); |
| 2821 | | try argv.appendSlice(c_object.src.extra_flags); |
| 2867 | if (comp.clang_passthrough_mode) { |
| 2868 | if (comp.emit_asm != null) { |
| 2869 | argv.appendAssumeCapacity("-S"); |
| 2870 | } else if (comp.emit_llvm_ir != null) { |
| 2871 | argv.appendSliceAssumeCapacity(&[_][]const u8{ "-emit-llvm", "-S" }); |
| 2872 | } else if (comp.emit_llvm_bc != null) { |
| 2873 | argv.appendAssumeCapacity("-emit-llvm"); |
| 2874 | } |
| 2875 | } |
| 2876 | argv.appendAssumeCapacity(c_object.src.src_path); |
| 2877 | argv.appendSliceAssumeCapacity(c_object.src.extra_flags); |
| 2822 | 2878 | |
| 2823 | 2879 | if (comp.verbose_cc) { |
| 2824 | 2880 | dump_argv(argv.items); |
| ... | ... | @@ -2838,8 +2894,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P |
| 2838 | 2894 | switch (term) { |
| 2839 | 2895 | .Exited => |code| { |
| 2840 | 2896 | if (code != 0) { |
| 2841 | | // TODO https://github.com/ziglang/zig/issues/6342 |
| 2842 | | std.process.exit(1); |
| 2897 | std.process.exit(code); |
| 2843 | 2898 | } |
| 2844 | 2899 | if (comp.clang_preprocessor_mode == .stdout) |
| 2845 | 2900 | std.process.exit(0); |
| ... | ... | @@ -2855,9 +2910,6 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P |
| 2855 | 2910 | |
| 2856 | 2911 | const stderr_reader = child.stderr.?.reader(); |
| 2857 | 2912 | |
| 2858 | | // TODO https://github.com/ziglang/zig/issues/6343 |
| 2859 | | // Please uncomment and use stdout once this issue is fixed |
| 2860 | | // const stdout = try stdout_reader.readAllAlloc(arena, std.math.maxInt(u32)); |
| 2861 | 2913 | const stderr = try stderr_reader.readAllAlloc(arena, 10 * 1024 * 1024); |
| 2862 | 2914 | |
| 2863 | 2915 | const term = child.wait() catch |err| { |
| ... | ... | @@ -2907,6 +2959,8 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P |
| 2907 | 2959 | break :blk digest; |
| 2908 | 2960 | }; |
| 2909 | 2961 | |
| 2962 | const o_basename = try std.fmt.allocPrint(arena, "{s}{s}", .{ o_basename_noext, o_ext }); |
| 2963 | |
| 2910 | 2964 | c_object.status = .{ |
| 2911 | 2965 | .success = .{ |
| 2912 | 2966 | .object_path = try comp.local_cache_directory.join(comp.gpa, &[_][]const u8{ |