authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-05-28 06:36:47+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-06-12 13:55:39+01:00
log3743c3e39c6bb645db7403fd446953d43ac7c7dc
treee9223b737051f606b7eec326e71e5977f4164dfc
parent424e6ac54b0f8bbfb43f24e28c71ac72169f3719
signaturelock-open Commit is signed but in an unrecognized format.

compiler: slightly untangle LLVM from the linkers

The main goal of this commit is to make it easier to decouple codegen from the linkers by being able to do LLVM codegen without going through the `link.File`; however, this ended up being a nice refactor anyway. Previously, every linker stored an optional `llvm.Object`, which was populated when using LLVM for the ZCU *and* linking an output binary; and `Zcu` also stored an optional `llvm.Object`, which was used only when we needed LLVM for the ZCU (e.g. for `-femit-llvm-bc`) but were not emitting a binary. This situation was incredibly silly. It meant there were N+1 places the LLVM object might be instead of just 1, and it meant that every linker had to start a bunch of methods by checking for an LLVM object, and just dispatching to the corresponding method on *it* instead if it was not `null`. Instead, we now always store the LLVM object on the `Zcu` -- which makes sense, because it corresponds to the object emitted by, well, the Zig Compilation Unit! The linkers now mostly don't make reference to LLVM. `Compilation` makes sure to emit the LLVM object if necessary before calling `flush`, so it is ready for the linker. Also, all of the `link.File` methods which act on the ZCU -- like `updateNav` -- now check for the LLVM object in `link.zig` instead of in every single individual linker implementation. Notably, the change to LLVM emit improves this rather ludicrous call chain in the `-fllvm -flld` case: * Compilation.flush * link.File.flush * link.Elf.flush * link.Elf.linkWithLLD * link.Elf.flushModule * link.emitLlvmObject * Compilation.emitLlvmObject * llvm.Object.emit Replacing it with this one: * Compilation.flush * llvm.Object.emit ...although we do currently still end up in `link.Elf.linkWithLLD` to do the actual linking. The logic for invoking LLD should probably also be unified at least somewhat; I haven't done that in this commit.

20 files changed, 227 insertions(+), 337 deletions(-)

src/Compilation.zig+31-41
...@@ -2188,14 +2188,10 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -2188,14 +2188,10 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
2188 },2188 },
2189 }2189 }
21902190
2191 // Handle the case of e.g. -fno-emit-bin -femit-llvm-ir.2191 if (use_llvm) {
2192 if (options.emit_bin == null and (comp.verbose_llvm_ir != null or2192 if (opt_zcu) |zcu| {
2193 comp.verbose_llvm_bc != null or2193 zcu.llvm_object = try LlvmObject.create(arena, comp);
2194 (use_llvm and comp.emit_asm != null) or2194 }
2195 comp.emit_llvm_ir != null or
2196 comp.emit_llvm_bc != null))
2197 {
2198 if (opt_zcu) |zcu| zcu.llvm_object = try LlvmObject.create(arena, comp);
2199 }2195 }
22002196
2201 break :comp comp;2197 break :comp comp;
...@@ -2945,6 +2941,33 @@ fn flush(...@@ -2945,6 +2941,33 @@ fn flush(
2945 tid: Zcu.PerThread.Id,2941 tid: Zcu.PerThread.Id,
2946 prog_node: std.Progress.Node,2942 prog_node: std.Progress.Node,
2947) !void {2943) !void {
2944 if (comp.zcu) |zcu| {
2945 if (zcu.llvm_object) |llvm_object| {
2946 // Emit the ZCU object from LLVM now; it's required to flush the output file.
2947 // If there's an output file, it wants to decide where the LLVM object goes!
2948 const zcu_obj_emit_loc: ?EmitLoc = if (comp.bin_file) |lf| .{
2949 .directory = null,
2950 .basename = lf.zcu_object_sub_path.?,
2951 } else null;
2952 const sub_prog_node = prog_node.start("LLVM Emit Object", 0);
2953 defer sub_prog_node.end();
2954 try llvm_object.emit(.{
2955 .pre_ir_path = comp.verbose_llvm_ir,
2956 .pre_bc_path = comp.verbose_llvm_bc,
2957 .bin_path = try resolveEmitLoc(arena, default_artifact_directory, zcu_obj_emit_loc),
2958 .asm_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_asm),
2959 .post_ir_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_llvm_ir),
2960 .post_bc_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_llvm_bc),
2961
2962 .is_debug = comp.root_mod.optimize_mode == .Debug,
2963 .is_small = comp.root_mod.optimize_mode == .ReleaseSmall,
2964 .time_report = comp.time_report,
2965 .sanitize_thread = comp.config.any_sanitize_thread,
2966 .fuzz = comp.config.any_fuzz,
2967 .lto = comp.config.lto,
2968 });
2969 }
2970 }
2948 if (comp.bin_file) |lf| {2971 if (comp.bin_file) |lf| {
2949 // This is needed before reading the error flags.2972 // This is needed before reading the error flags.
2950 lf.flush(arena, tid, prog_node) catch |err| switch (err) {2973 lf.flush(arena, tid, prog_node) catch |err| switch (err) {
...@@ -2952,13 +2975,8 @@ fn flush(...@@ -2952,13 +2975,8 @@ fn flush(
2952 error.OutOfMemory => return error.OutOfMemory,2975 error.OutOfMemory => return error.OutOfMemory,
2953 };2976 };
2954 }2977 }
2955
2956 if (comp.zcu) |zcu| {2978 if (comp.zcu) |zcu| {
2957 try link.File.C.flushEmitH(zcu);2979 try link.File.C.flushEmitH(zcu);
2958
2959 if (zcu.llvm_object) |llvm_object| {
2960 try emitLlvmObject(comp, arena, default_artifact_directory, null, llvm_object, prog_node);
2961 }
2962 }2980 }
2963}2981}
29642982
...@@ -3233,34 +3251,6 @@ fn emitOthers(comp: *Compilation) void {...@@ -3233,34 +3251,6 @@ fn emitOthers(comp: *Compilation) void {
3233 }3251 }
3234}3252}
32353253
3236pub fn emitLlvmObject(
3237 comp: *Compilation,
3238 arena: Allocator,
3239 default_artifact_directory: Cache.Path,
3240 bin_emit_loc: ?EmitLoc,
3241 llvm_object: LlvmObject.Ptr,
3242 prog_node: std.Progress.Node,
3243) !void {
3244 const sub_prog_node = prog_node.start("LLVM Emit Object", 0);
3245 defer sub_prog_node.end();
3246
3247 try llvm_object.emit(.{
3248 .pre_ir_path = comp.verbose_llvm_ir,
3249 .pre_bc_path = comp.verbose_llvm_bc,
3250 .bin_path = try resolveEmitLoc(arena, default_artifact_directory, bin_emit_loc),
3251 .asm_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_asm),
3252 .post_ir_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_llvm_ir),
3253 .post_bc_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_llvm_bc),
3254
3255 .is_debug = comp.root_mod.optimize_mode == .Debug,
3256 .is_small = comp.root_mod.optimize_mode == .ReleaseSmall,
3257 .time_report = comp.time_report,
3258 .sanitize_thread = comp.config.any_sanitize_thread,
3259 .fuzz = comp.config.any_fuzz,
3260 .lto = comp.config.lto,
3261 });
3262}
3263
3264fn resolveEmitLoc(3254fn resolveEmitLoc(
3265 arena: Allocator,3255 arena: Allocator,
3266 default_artifact_directory: Cache.Path,3256 default_artifact_directory: Cache.Path,
src/Zcu.zig+2-13
...@@ -56,9 +56,8 @@ comptime {...@@ -56,9 +56,8 @@ comptime {
56/// General-purpose allocator. Used for both temporary and long-term storage.56/// General-purpose allocator. Used for both temporary and long-term storage.
57gpa: Allocator,57gpa: Allocator,
58comp: *Compilation,58comp: *Compilation,
59/// Usually, the LlvmObject is managed by linker code, however, in the case59/// If the ZCU is emitting an LLVM object (i.e. we are using the LLVM backend), then this is the
60/// that -fno-emit-bin is specified, the linker code never executes, so we60/// `LlvmObject` we are emitting to.
61/// store the LlvmObject here.
62llvm_object: ?LlvmObject.Ptr,61llvm_object: ?LlvmObject.Ptr,
6362
64/// Pointer to externally managed resource.63/// Pointer to externally managed resource.
...@@ -267,16 +266,6 @@ resolved_references: ?std.AutoHashMapUnmanaged(AnalUnit, ?ResolvedReference) = n...@@ -267,16 +266,6 @@ resolved_references: ?std.AutoHashMapUnmanaged(AnalUnit, ?ResolvedReference) = n
267/// Reset to `false` at the start of each update in `Compilation.update`.266/// Reset to `false` at the start of each update in `Compilation.update`.
268skip_analysis_this_update: bool = false,267skip_analysis_this_update: bool = false,
269268
270stage1_flags: packed struct {
271 have_winmain: bool = false,
272 have_wwinmain: bool = false,
273 have_winmain_crt_startup: bool = false,
274 have_wwinmain_crt_startup: bool = false,
275 have_dllmain_crt_startup: bool = false,
276 have_c_main: bool = false,
277 reserved: u2 = 0,
278} = .{},
279
280test_functions: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty,269test_functions: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, void) = .empty,
281270
282global_assembly: std.AutoArrayHashMapUnmanaged(AnalUnit, []u8) = .empty,271global_assembly: std.AutoArrayHashMapUnmanaged(AnalUnit, []u8) = .empty,
src/Zcu/PerThread.zig+9-12
...@@ -1784,8 +1784,12 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: *A...@@ -1784,8 +1784,12 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: *A
1784 };1784 };
1785 }1785 }
17861786
1787 if (comp.bin_file) |lf| {1787 if (zcu.llvm_object) |llvm_object| {
1788 lf.updateFunc(pt, func_index, air.*, liveness) catch |err| switch (err) {1788 llvm_object.updateFunc(pt, func_index, air.*, liveness) catch |err| switch (err) {
1789 error.OutOfMemory => return error.OutOfMemory,
1790 };
1791 } else if (comp.bin_file) |lf| {
1792 lf.updateFunc(pt, func_index, air, liveness) catch |err| switch (err) {
1789 error.OutOfMemory => return error.OutOfMemory,1793 error.OutOfMemory => return error.OutOfMemory,
1790 error.CodegenFail => assert(zcu.failed_codegen.contains(nav_index)),1794 error.CodegenFail => assert(zcu.failed_codegen.contains(nav_index)),
1791 error.Overflow, error.RelocationNotByteAligned => {1795 error.Overflow, error.RelocationNotByteAligned => {
...@@ -1798,10 +1802,6 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: *A...@@ -1798,10 +1802,6 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: *A
1798 // Not a retryable failure.1802 // Not a retryable failure.
1799 },1803 },
1800 };1804 };
1801 } else if (zcu.llvm_object) |llvm_object| {
1802 llvm_object.updateFunc(pt, func_index, air.*, liveness) catch |err| switch (err) {
1803 error.OutOfMemory => return error.OutOfMemory,
1804 };
1805 }1805 }
1806}1806}
18071807
...@@ -1877,7 +1877,6 @@ fn createFileRootStruct(...@@ -1877,7 +1877,6 @@ fn createFileRootStruct(
1877 try pt.scanNamespace(namespace_index, decls);1877 try pt.scanNamespace(namespace_index, decls);
1878 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });1878 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
1879 codegen_type: {1879 codegen_type: {
1880 if (zcu.comp.config.use_llvm) break :codegen_type;
1881 if (file.mod.?.strip) break :codegen_type;1880 if (file.mod.?.strip) break :codegen_type;
1882 // This job depends on any resolve_type_fully jobs queued up before it.1881 // This job depends on any resolve_type_fully jobs queued up before it.
1883 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });1882 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
...@@ -3309,10 +3308,10 @@ fn processExportsInner(...@@ -3309,10 +3308,10 @@ fn processExportsInner(
3309 .uav => {},3308 .uav => {},
3310 }3309 }
33113310
3312 if (zcu.comp.bin_file) |lf| {3311 if (zcu.llvm_object) |llvm_object| {
3313 try zcu.handleUpdateExports(export_indices, lf.updateExports(pt, exported, export_indices));
3314 } else if (zcu.llvm_object) |llvm_object| {
3315 try zcu.handleUpdateExports(export_indices, llvm_object.updateExports(pt, exported, export_indices));3312 try zcu.handleUpdateExports(export_indices, llvm_object.updateExports(pt, exported, export_indices));
3313 } else if (zcu.comp.bin_file) |lf| {
3314 try zcu.handleUpdateExports(export_indices, lf.updateExports(pt, exported, export_indices));
3316 }3315 }
3317}3316}
33183317
...@@ -4064,7 +4063,6 @@ fn recreateStructType(...@@ -4064,7 +4063,6 @@ fn recreateStructType(
4064 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });4063 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
40654064
4066 codegen_type: {4065 codegen_type: {
4067 if (zcu.comp.config.use_llvm) break :codegen_type;
4068 if (file.mod.?.strip) break :codegen_type;4066 if (file.mod.?.strip) break :codegen_type;
4069 // This job depends on any resolve_type_fully jobs queued up before it.4067 // This job depends on any resolve_type_fully jobs queued up before it.
4070 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });4068 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
...@@ -4157,7 +4155,6 @@ fn recreateUnionType(...@@ -4157,7 +4155,6 @@ fn recreateUnionType(
4157 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });4155 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
41584156
4159 codegen_type: {4157 codegen_type: {
4160 if (zcu.comp.config.use_llvm) break :codegen_type;
4161 if (file.mod.?.strip) break :codegen_type;4158 if (file.mod.?.strip) break :codegen_type;
4162 // This job depends on any resolve_type_fully jobs queued up before it.4159 // This job depends on any resolve_type_fully jobs queued up before it.
4163 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });4160 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
src/codegen/llvm.zig+18
...@@ -1586,6 +1586,24 @@ pub const Object = struct {...@@ -1586,6 +1586,24 @@ pub const Object = struct {
1586 const global_index = self.nav_map.get(nav_index).?;1586 const global_index = self.nav_map.get(nav_index).?;
1587 const comp = zcu.comp;1587 const comp = zcu.comp;
15881588
1589 // If we're on COFF and linking with LLD, the linker cares about our exports to determine the subsystem in use.
1590 if (comp.bin_file != null and
1591 comp.bin_file.?.tag == .coff and
1592 zcu.comp.config.use_lld and
1593 ip.isFunctionType(ip.getNav(nav_index).typeOf(ip)))
1594 {
1595 const flags = &comp.bin_file.?.cast(.coff).?.lld_export_flags;
1596 for (export_indices) |export_index| {
1597 const name = export_index.ptr(zcu).opts.name;
1598 if (name.eqlSlice("main", ip)) flags.c_main = true;
1599 if (name.eqlSlice("WinMain", ip)) flags.winmain = true;
1600 if (name.eqlSlice("wWinMain", ip)) flags.wwinmain = true;
1601 if (name.eqlSlice("WinMainCRTStartup", ip)) flags.winmain_crt_startup = true;
1602 if (name.eqlSlice("wWinMainCRTStartup", ip)) flags.wwinmain_crt_startup = true;
1603 if (name.eqlSlice("DllMainCRTStartup", ip)) flags.dllmain_crt_startup = true;
1604 }
1605 }
1606
1589 if (export_indices.len != 0) {1607 if (export_indices.len != 0) {
1590 return updateExportedGlobal(self, zcu, global_index, export_indices);1608 return updateExportedGlobal(self, zcu, global_index, export_indices);
1591 } else {1609 } else {
src/codegen/spirv/Section.zig-2
...@@ -386,8 +386,6 @@ test "SPIR-V Section emit() - string" {...@@ -386,8 +386,6 @@ test "SPIR-V Section emit() - string" {
386}386}
387387
388test "SPIR-V Section emit() - extended mask" {388test "SPIR-V Section emit() - extended mask" {
389 if (@import("builtin").zig_backend == .stage1) return error.SkipZigTest;
390
391 var section = Section{};389 var section = Section{};
392 defer section.deinit(std.testing.allocator);390 defer section.deinit(std.testing.allocator);
393391
src/link.zig+48-37
...@@ -19,7 +19,6 @@ const Zcu = @import("Zcu.zig");...@@ -19,7 +19,6 @@ const Zcu = @import("Zcu.zig");
19const InternPool = @import("InternPool.zig");19const InternPool = @import("InternPool.zig");
20const Type = @import("Type.zig");20const Type = @import("Type.zig");
21const Value = @import("Value.zig");21const Value = @import("Value.zig");
22const LlvmObject = @import("codegen/llvm.zig").Object;
23const lldMain = @import("main.zig").lldMain;22const lldMain = @import("main.zig").lldMain;
24const Package = @import("Package.zig");23const Package = @import("Package.zig");
25const dev = @import("dev.zig");24const dev = @import("dev.zig");
...@@ -704,7 +703,9 @@ pub const File = struct {...@@ -704,7 +703,9 @@ pub const File = struct {
704 }703 }
705704
706 /// May be called before or after updateExports for any given Nav.705 /// May be called before or after updateExports for any given Nav.
706 /// Asserts that the ZCU is not using the LLVM backend.
707 fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) UpdateNavError!void {707 fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) UpdateNavError!void {
708 assert(base.comp.zcu.?.llvm_object == null);
708 const nav = pt.zcu.intern_pool.getNav(nav_index);709 const nav = pt.zcu.intern_pool.getNav(nav_index);
709 assert(nav.status == .fully_resolved);710 assert(nav.status == .fully_resolved);
710 switch (base.tag) {711 switch (base.tag) {
...@@ -721,7 +722,9 @@ pub const File = struct {...@@ -721,7 +722,9 @@ pub const File = struct {
721 TypeFailureReported,722 TypeFailureReported,
722 };723 };
723724
725 /// Never called when LLVM is codegenning the ZCU.
724 fn updateContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index) UpdateContainerTypeError!void {726 fn updateContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index) UpdateContainerTypeError!void {
727 assert(base.comp.zcu.?.llvm_object == null);
725 switch (base.tag) {728 switch (base.tag) {
726 else => {},729 else => {},
727 inline .elf => |tag| {730 inline .elf => |tag| {
...@@ -733,6 +736,7 @@ pub const File = struct {...@@ -733,6 +736,7 @@ pub const File = struct {
733736
734 /// May be called before or after updateExports for any given Decl.737 /// May be called before or after updateExports for any given Decl.
735 /// TODO: currently `pub` because `Zcu.PerThread` is calling this.738 /// TODO: currently `pub` because `Zcu.PerThread` is calling this.
739 /// Never called when LLVM is codegenning the ZCU.
736 pub fn updateFunc(740 pub fn updateFunc(
737 base: *File,741 base: *File,
738 pt: Zcu.PerThread,742 pt: Zcu.PerThread,
...@@ -740,6 +744,7 @@ pub const File = struct {...@@ -740,6 +744,7 @@ pub const File = struct {
740 air: Air,744 air: Air,
741 liveness: Air.Liveness,745 liveness: Air.Liveness,
742 ) UpdateNavError!void {746 ) UpdateNavError!void {
747 assert(base.comp.zcu.?.llvm_object == null);
743 switch (base.tag) {748 switch (base.tag) {
744 inline else => |tag| {749 inline else => |tag| {
745 dev.check(tag.devFeature());750 dev.check(tag.devFeature());
...@@ -756,7 +761,9 @@ pub const File = struct {...@@ -756,7 +761,9 @@ pub const File = struct {
756761
757 /// On an incremental update, fixup the line number of all `Nav`s at the given `TrackedInst`, because762 /// On an incremental update, fixup the line number of all `Nav`s at the given `TrackedInst`, because
758 /// its line number has changed. The ZIR instruction `ti_id` has tag `.declaration`.763 /// its line number has changed. The ZIR instruction `ti_id` has tag `.declaration`.
764 /// Never called when LLVM is codegenning the ZCU.
759 fn updateLineNumber(base: *File, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) UpdateLineNumberError!void {765 fn updateLineNumber(base: *File, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) UpdateLineNumberError!void {
766 assert(base.comp.zcu.?.llvm_object == null);
760 {767 {
761 const ti = ti_id.resolveFull(&pt.zcu.intern_pool).?;768 const ti = ti_id.resolveFull(&pt.zcu.intern_pool).?;
762 const file = pt.zcu.fileByIndex(ti.file);769 const file = pt.zcu.fileByIndex(ti.file);
...@@ -846,11 +853,13 @@ pub const File = struct {...@@ -846,11 +853,13 @@ pub const File = struct {
846853
847 /// Commit pending changes and write headers. Works based on `effectiveOutputMode`854 /// Commit pending changes and write headers. Works based on `effectiveOutputMode`
848 /// rather than final output mode.855 /// rather than final output mode.
849 pub fn flushModule(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void {856 /// Never called when LLVM is codegenning the ZCU.
857 fn flushZcu(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void {
858 assert(base.comp.zcu.?.llvm_object == null);
850 switch (base.tag) {859 switch (base.tag) {
851 inline else => |tag| {860 inline else => |tag| {
852 dev.check(tag.devFeature());861 dev.check(tag.devFeature());
853 return @as(*tag.Type(), @fieldParentPtr("base", base)).flushModule(arena, tid, prog_node);862 return @as(*tag.Type(), @fieldParentPtr("base", base)).flushZcu(arena, tid, prog_node);
854 },863 },
855 }864 }
856 }865 }
...@@ -864,12 +873,14 @@ pub const File = struct {...@@ -864,12 +873,14 @@ pub const File = struct {
864 /// a list of size 1, meaning that `exported` is exported once. However, it is possible873 /// a list of size 1, meaning that `exported` is exported once. However, it is possible
865 /// to export the same thing with multiple different symbol names (aliases).874 /// to export the same thing with multiple different symbol names (aliases).
866 /// May be called before or after updateDecl for any given Decl.875 /// May be called before or after updateDecl for any given Decl.
876 /// Never called when LLVM is codegenning the ZCU.
867 pub fn updateExports(877 pub fn updateExports(
868 base: *File,878 base: *File,
869 pt: Zcu.PerThread,879 pt: Zcu.PerThread,
870 exported: Zcu.Exported,880 exported: Zcu.Exported,
871 export_indices: []const Zcu.Export.Index,881 export_indices: []const Zcu.Export.Index,
872 ) UpdateExportsError!void {882 ) UpdateExportsError!void {
883 assert(base.comp.zcu.?.llvm_object == null);
873 switch (base.tag) {884 switch (base.tag) {
874 inline else => |tag| {885 inline else => |tag| {
875 dev.check(tag.devFeature());886 dev.check(tag.devFeature());
...@@ -896,7 +907,9 @@ pub const File = struct {...@@ -896,7 +907,9 @@ pub const File = struct {
896 /// `Nav`'s address was not yet resolved, or the containing atom gets moved in virtual memory.907 /// `Nav`'s address was not yet resolved, or the containing atom gets moved in virtual memory.
897 /// May be called before or after updateFunc/updateNav therefore it is up to the linker to allocate908 /// May be called before or after updateFunc/updateNav therefore it is up to the linker to allocate
898 /// the block/atom.909 /// the block/atom.
910 /// Never called when LLVM is codegenning the ZCU.
899 pub fn getNavVAddr(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: RelocInfo) !u64 {911 pub fn getNavVAddr(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: RelocInfo) !u64 {
912 assert(base.comp.zcu.?.llvm_object == null);
900 switch (base.tag) {913 switch (base.tag) {
901 .c => unreachable,914 .c => unreachable,
902 .spirv => unreachable,915 .spirv => unreachable,
...@@ -909,6 +922,7 @@ pub const File = struct {...@@ -909,6 +922,7 @@ pub const File = struct {
909 }922 }
910 }923 }
911924
925 /// Never called when LLVM is codegenning the ZCU.
912 pub fn lowerUav(926 pub fn lowerUav(
913 base: *File,927 base: *File,
914 pt: Zcu.PerThread,928 pt: Zcu.PerThread,
...@@ -916,6 +930,7 @@ pub const File = struct {...@@ -916,6 +930,7 @@ pub const File = struct {
916 decl_align: InternPool.Alignment,930 decl_align: InternPool.Alignment,
917 src_loc: Zcu.LazySrcLoc,931 src_loc: Zcu.LazySrcLoc,
918 ) !codegen.GenResult {932 ) !codegen.GenResult {
933 assert(base.comp.zcu.?.llvm_object == null);
919 switch (base.tag) {934 switch (base.tag) {
920 .c => unreachable,935 .c => unreachable,
921 .spirv => unreachable,936 .spirv => unreachable,
...@@ -928,7 +943,9 @@ pub const File = struct {...@@ -928,7 +943,9 @@ pub const File = struct {
928 }943 }
929 }944 }
930945
946 /// Never called when LLVM is codegenning the ZCU.
931 pub fn getUavVAddr(base: *File, decl_val: InternPool.Index, reloc_info: RelocInfo) !u64 {947 pub fn getUavVAddr(base: *File, decl_val: InternPool.Index, reloc_info: RelocInfo) !u64 {
948 assert(base.comp.zcu.?.llvm_object == null);
932 switch (base.tag) {949 switch (base.tag) {
933 .c => unreachable,950 .c => unreachable,
934 .spirv => unreachable,951 .spirv => unreachable,
...@@ -941,11 +958,13 @@ pub const File = struct {...@@ -941,11 +958,13 @@ pub const File = struct {
941 }958 }
942 }959 }
943960
961 /// Never called when LLVM is codegenning the ZCU.
944 pub fn deleteExport(962 pub fn deleteExport(
945 base: *File,963 base: *File,
946 exported: Zcu.Exported,964 exported: Zcu.Exported,
947 name: InternPool.NullTerminatedString,965 name: InternPool.NullTerminatedString,
948 ) void {966 ) void {
967 assert(base.comp.zcu.?.llvm_object == null);
949 switch (base.tag) {968 switch (base.tag) {
950 .plan9,969 .plan9,
951 .spirv,970 .spirv,
...@@ -1077,7 +1096,7 @@ pub const File = struct {...@@ -1077,7 +1096,7 @@ pub const File = struct {
1077 }1096 }
1078 }1097 }
10791098
1080 pub fn linkAsArchive(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void {1099 fn linkAsArchive(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void {
1081 dev.check(.lld_linker);1100 dev.check(.lld_linker);
10821101
1083 const tracy = trace(@src());1102 const tracy = trace(@src());
...@@ -1103,9 +1122,12 @@ pub const File = struct {...@@ -1103,9 +1122,12 @@ pub const File = struct {
11031122
1104 // If there is no Zig code to compile, then we should skip flushing the output file1123 // If there is no Zig code to compile, then we should skip flushing the output file
1105 // because it will not be part of the linker line anyway.1124 // because it will not be part of the linker line anyway.
1106 const zcu_obj_path: ?[]const u8 = if (opt_zcu != null) blk: {1125 const zcu_obj_path: ?[]const u8 = if (opt_zcu) |zcu| blk: {
1107 try base.flushModule(arena, tid, prog_node);1126 if (zcu.llvm_object == null) {
11081127 try base.flushZcu(arena, tid, prog_node);
1128 } else {
1129 // `Compilation.flush` has already made LLVM emit this object file for us.
1130 }
1109 const dirname = fs.path.dirname(full_out_path_z) orelse ".";1131 const dirname = fs.path.dirname(full_out_path_z) orelse ".";
1110 break :blk try fs.path.join(arena, &.{ dirname, base.zcu_object_sub_path.? });1132 break :blk try fs.path.join(arena, &.{ dirname, base.zcu_object_sub_path.? });
1111 } else null;1133 } else null;
...@@ -1346,21 +1368,6 @@ pub const File = struct {...@@ -1346,21 +1368,6 @@ pub const File = struct {
1346 return output_mode == .Lib and !self.isStatic();1368 return output_mode == .Lib and !self.isStatic();
1347 }1369 }
13481370
1349 pub fn emitLlvmObject(
1350 base: File,
1351 arena: Allocator,
1352 llvm_object: LlvmObject.Ptr,
1353 prog_node: std.Progress.Node,
1354 ) !void {
1355 return base.comp.emitLlvmObject(arena, .{
1356 .root_dir = base.emit.root_dir,
1357 .sub_path = std.fs.path.dirname(base.emit.sub_path) orelse "",
1358 }, .{
1359 .directory = null,
1360 .basename = base.zcu_object_sub_path.?,
1361 }, llvm_object, prog_node);
1362 }
1363
1364 pub fn cgFail(1371 pub fn cgFail(
1365 base: *File,1372 base: *File,
1366 nav_index: InternPool.Nav.Index,1373 nav_index: InternPool.Nav.Index,
...@@ -1600,7 +1607,11 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {...@@ -1600,7 +1607,11 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
1600 // on the failed type, so when it is changed the `Nav` will be updated.1607 // on the failed type, so when it is changed the `Nav` will be updated.
1601 return;1608 return;
1602 }1609 }
1603 if (comp.bin_file) |lf| {1610 if (zcu.llvm_object) |llvm_object| {
1611 llvm_object.updateNav(pt, nav_index) catch |err| switch (err) {
1612 error.OutOfMemory => diags.setAllocFailure(),
1613 };
1614 } else if (comp.bin_file) |lf| {
1604 lf.updateNav(pt, nav_index) catch |err| switch (err) {1615 lf.updateNav(pt, nav_index) catch |err| switch (err) {
1605 error.OutOfMemory => diags.setAllocFailure(),1616 error.OutOfMemory => diags.setAllocFailure(),
1606 error.CodegenFail => assert(zcu.failed_codegen.contains(nav_index)),1617 error.CodegenFail => assert(zcu.failed_codegen.contains(nav_index)),
...@@ -1616,10 +1627,6 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {...@@ -1616,10 +1627,6 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
1616 // Not a retryable failure.1627 // Not a retryable failure.
1617 },1628 },
1618 };1629 };
1619 } else if (zcu.llvm_object) |llvm_object| {
1620 llvm_object.updateNav(pt, nav_index) catch |err| switch (err) {
1621 error.OutOfMemory => diags.setAllocFailure(),
1622 };
1623 }1630 }
1624 },1631 },
1625 .link_func => |func| {1632 .link_func => |func| {
...@@ -1650,11 +1657,13 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {...@@ -1650,11 +1657,13 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
1650 // on the failed type, so when that is changed, this type will be updated.1657 // on the failed type, so when that is changed, this type will be updated.
1651 return;1658 return;
1652 }1659 }
1653 if (comp.bin_file) |lf| {1660 if (zcu.llvm_object == null) {
1654 lf.updateContainerType(pt, ty) catch |err| switch (err) {1661 if (comp.bin_file) |lf| {
1655 error.OutOfMemory => diags.setAllocFailure(),1662 lf.updateContainerType(pt, ty) catch |err| switch (err) {
1656 error.TypeFailureReported => assert(zcu.failed_types.contains(ty)),1663 error.OutOfMemory => diags.setAllocFailure(),
1657 };1664 error.TypeFailureReported => assert(zcu.failed_types.contains(ty)),
1665 };
1666 }
1658 }1667 }
1659 },1668 },
1660 .update_line_number => |ti| {1669 .update_line_number => |ti| {
...@@ -1664,11 +1673,13 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {...@@ -1664,11 +1673,13 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
1664 }1673 }
1665 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));1674 const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
1666 defer pt.deactivate();1675 defer pt.deactivate();
1667 if (comp.bin_file) |lf| {1676 if (pt.zcu.llvm_object == null) {
1668 lf.updateLineNumber(pt, ti) catch |err| switch (err) {1677 if (comp.bin_file) |lf| {
1669 error.OutOfMemory => diags.setAllocFailure(),1678 lf.updateLineNumber(pt, ti) catch |err| switch (err) {
1670 else => |e| log.err("update line number failed: {s}", .{@errorName(e)}),1679 error.OutOfMemory => diags.setAllocFailure(),
1671 };1680 else => |e| log.err("update line number failed: {s}", .{@errorName(e)}),
1681 };
1682 }
1672 }1683 }
1673 },1684 },
1674 }1685 }
src/link/C.zig+2-2
...@@ -382,7 +382,7 @@ pub fn updateLineNumber(self: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedIn...@@ -382,7 +382,7 @@ pub fn updateLineNumber(self: *C, pt: Zcu.PerThread, ti_id: InternPool.TrackedIn
382}382}
383383
384pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {384pub fn flush(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
385 return self.flushModule(arena, tid, prog_node);385 return self.flushZcu(arena, tid, prog_node);
386}386}
387387
388fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {388fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {
...@@ -400,7 +400,7 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {...@@ -400,7 +400,7 @@ fn abiDefines(self: *C, target: std.Target) !std.ArrayList(u8) {
400 return defines;400 return defines;
401}401}
402402
403pub fn flushModule(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {403pub fn flushZcu(self: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
404 _ = arena; // Has the same lifetime as the call to Compilation.update.404 _ = arena; // Has the same lifetime as the call to Compilation.update.
405405
406 const tracy = trace(@src());406 const tracy = trace(@src());
src/link/Coff.zig+30-84
...@@ -3,9 +3,6 @@...@@ -3,9 +3,6 @@
3//! LLD for traditional linking (linking relocatable object files).3//! LLD for traditional linking (linking relocatable object files).
4//! LLD is also the default linker for LLVM.4//! LLD is also the default linker for LLVM.
55
6/// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path.
7llvm_object: ?LlvmObject.Ptr = null,
8
9base: link.File,6base: link.File,
10image_base: u64,7image_base: u64,
11subsystem: ?std.Target.SubSystem,8subsystem: ?std.Target.SubSystem,
...@@ -87,6 +84,16 @@ base_relocs: BaseRelocationTable = .{},...@@ -87,6 +84,16 @@ base_relocs: BaseRelocationTable = .{},
87/// Hot-code swapping state.84/// Hot-code swapping state.
88hot_state: if (is_hot_update_compatible) HotUpdateState else struct {} = .{},85hot_state: if (is_hot_update_compatible) HotUpdateState else struct {} = .{},
8986
87/// When linking with LLD, these flags are used to determine the subsystem to pass on the LLD command line.
88lld_export_flags: struct {
89 c_main: bool = false,
90 winmain: bool = false,
91 wwinmain: bool = false,
92 winmain_crt_startup: bool = false,
93 wwinmain_crt_startup: bool = false,
94 dllmain_crt_startup: bool = false,
95} = .{},
96
90const is_hot_update_compatible = switch (builtin.target.os.tag) {97const is_hot_update_compatible = switch (builtin.target.os.tag) {
91 .windows => true,98 .windows => true,
92 else => false,99 else => false,
...@@ -302,9 +309,6 @@ pub fn createEmpty(...@@ -302,9 +309,6 @@ pub fn createEmpty(
302 .pdb_out_path = options.pdb_out_path,309 .pdb_out_path = options.pdb_out_path,
303 .repro = options.repro,310 .repro = options.repro,
304 };311 };
305 if (use_llvm and comp.config.have_zcu) {
306 coff.llvm_object = try LlvmObject.create(arena, comp);
307 }
308 errdefer coff.base.destroy();312 errdefer coff.base.destroy();
309313
310 if (use_lld and (use_llvm or !comp.config.have_zcu)) {314 if (use_lld and (use_llvm or !comp.config.have_zcu)) {
...@@ -322,7 +326,6 @@ pub fn createEmpty(...@@ -322,7 +326,6 @@ pub fn createEmpty(
322 .mode = link.File.determineMode(use_lld, output_mode, link_mode),326 .mode = link.File.determineMode(use_lld, output_mode, link_mode),
323 });327 });
324328
325 assert(coff.llvm_object == null);
326 const gpa = comp.gpa;329 const gpa = comp.gpa;
327330
328 try coff.strtab.buffer.ensureUnusedCapacity(gpa, @sizeOf(u32));331 try coff.strtab.buffer.ensureUnusedCapacity(gpa, @sizeOf(u32));
...@@ -428,8 +431,6 @@ pub fn open(...@@ -428,8 +431,6 @@ pub fn open(
428pub fn deinit(coff: *Coff) void {431pub fn deinit(coff: *Coff) void {
429 const gpa = coff.base.comp.gpa;432 const gpa = coff.base.comp.gpa;
430433
431 if (coff.llvm_object) |llvm_object| llvm_object.deinit();
432
433 for (coff.sections.items(.free_list)) |*free_list| {434 for (coff.sections.items(.free_list)) |*free_list| {
434 free_list.deinit(gpa);435 free_list.deinit(gpa);
435 }436 }
...@@ -1103,9 +1104,6 @@ pub fn updateFunc(...@@ -1103,9 +1104,6 @@ pub fn updateFunc(
1103 if (build_options.skip_non_native and builtin.object_format != .coff) {1104 if (build_options.skip_non_native and builtin.object_format != .coff) {
1104 @panic("Attempted to compile for object format that was disabled by build configuration");1105 @panic("Attempted to compile for object format that was disabled by build configuration");
1105 }1106 }
1106 if (coff.llvm_object) |llvm_object| {
1107 return llvm_object.updateFunc(pt, func_index, air, liveness);
1108 }
1109 const tracy = trace(@src());1107 const tracy = trace(@src());
1110 defer tracy.end();1108 defer tracy.end();
11111109
...@@ -1205,7 +1203,6 @@ pub fn updateNav(...@@ -1205,7 +1203,6 @@ pub fn updateNav(
1205 if (build_options.skip_non_native and builtin.object_format != .coff) {1203 if (build_options.skip_non_native and builtin.object_format != .coff) {
1206 @panic("Attempted to compile for object format that was disabled by build configuration");1204 @panic("Attempted to compile for object format that was disabled by build configuration");
1207 }1205 }
1208 if (coff.llvm_object) |llvm_object| return llvm_object.updateNav(pt, nav_index);
1209 const tracy = trace(@src());1206 const tracy = trace(@src());
1210 defer tracy.end();1207 defer tracy.end();
12111208
...@@ -1330,7 +1327,7 @@ pub fn getOrCreateAtomForLazySymbol(...@@ -1330,7 +1327,7 @@ pub fn getOrCreateAtomForLazySymbol(
1330 }1327 }
1331 state_ptr.* = .pending_flush;1328 state_ptr.* = .pending_flush;
1332 const atom = atom_ptr.*;1329 const atom = atom_ptr.*;
1333 // anyerror needs to be deferred until flushModule1330 // anyerror needs to be deferred until flushZcu
1334 if (lazy_sym.ty != .anyerror_type) try coff.updateLazySymbolAtom(pt, lazy_sym, atom, switch (lazy_sym.kind) {1331 if (lazy_sym.ty != .anyerror_type) try coff.updateLazySymbolAtom(pt, lazy_sym, atom, switch (lazy_sym.kind) {
1335 .code => coff.text_section_index.?,1332 .code => coff.text_section_index.?,
1336 .const_data => coff.rdata_section_index.?,1333 .const_data => coff.rdata_section_index.?,
...@@ -1463,8 +1460,6 @@ fn updateNavCode(...@@ -1463,8 +1460,6 @@ fn updateNavCode(
1463}1460}
14641461
1465pub fn freeNav(coff: *Coff, nav_index: InternPool.NavIndex) void {1462pub fn freeNav(coff: *Coff, nav_index: InternPool.NavIndex) void {
1466 if (coff.llvm_object) |llvm_object| return llvm_object.freeNav(nav_index);
1467
1468 const gpa = coff.base.comp.gpa;1463 const gpa = coff.base.comp.gpa;
14691464
1470 if (coff.decls.fetchOrderedRemove(nav_index)) |const_kv| {1465 if (coff.decls.fetchOrderedRemove(nav_index)) |const_kv| {
...@@ -1485,50 +1480,7 @@ pub fn updateExports(...@@ -1485,50 +1480,7 @@ pub fn updateExports(
1485 }1480 }
14861481
1487 const zcu = pt.zcu;1482 const zcu = pt.zcu;
1488 const ip = &zcu.intern_pool;1483 const gpa = zcu.gpa;
1489 const comp = coff.base.comp;
1490 const target = comp.root_mod.resolved_target.result;
1491
1492 if (comp.config.use_llvm) {
1493 // Even in the case of LLVM, we need to notice certain exported symbols in order to
1494 // detect the default subsystem.
1495 for (export_indices) |export_idx| {
1496 const exp = export_idx.ptr(zcu);
1497 const exported_nav_index = switch (exp.exported) {
1498 .nav => |nav| nav,
1499 .uav => continue,
1500 };
1501 const exported_nav = ip.getNav(exported_nav_index);
1502 const exported_ty = exported_nav.typeOf(ip);
1503 if (!ip.isFunctionType(exported_ty)) continue;
1504 const c_cc = target.cCallingConvention().?;
1505 const winapi_cc: std.builtin.CallingConvention = switch (target.cpu.arch) {
1506 .x86 => .{ .x86_stdcall = .{} },
1507 else => c_cc,
1508 };
1509 const exported_cc = Type.fromInterned(exported_ty).fnCallingConvention(zcu);
1510 const CcTag = std.builtin.CallingConvention.Tag;
1511 if (@as(CcTag, exported_cc) == @as(CcTag, c_cc) and exp.opts.name.eqlSlice("main", ip) and comp.config.link_libc) {
1512 zcu.stage1_flags.have_c_main = true;
1513 } else if (@as(CcTag, exported_cc) == @as(CcTag, winapi_cc) and target.os.tag == .windows) {
1514 if (exp.opts.name.eqlSlice("WinMain", ip)) {
1515 zcu.stage1_flags.have_winmain = true;
1516 } else if (exp.opts.name.eqlSlice("wWinMain", ip)) {
1517 zcu.stage1_flags.have_wwinmain = true;
1518 } else if (exp.opts.name.eqlSlice("WinMainCRTStartup", ip)) {
1519 zcu.stage1_flags.have_winmain_crt_startup = true;
1520 } else if (exp.opts.name.eqlSlice("wWinMainCRTStartup", ip)) {
1521 zcu.stage1_flags.have_wwinmain_crt_startup = true;
1522 } else if (exp.opts.name.eqlSlice("DllMainCRTStartup", ip)) {
1523 zcu.stage1_flags.have_dllmain_crt_startup = true;
1524 }
1525 }
1526 }
1527 }
1528
1529 if (coff.llvm_object) |llvm_object| return llvm_object.updateExports(pt, exported, export_indices);
1530
1531 const gpa = comp.gpa;
15321484
1533 const metadata = switch (exported) {1485 const metadata = switch (exported) {
1534 .nav => |nav| blk: {1486 .nav => |nav| blk: {
...@@ -1621,7 +1573,6 @@ pub fn deleteExport(...@@ -1621,7 +1573,6 @@ pub fn deleteExport(
1621 exported: Zcu.Exported,1573 exported: Zcu.Exported,
1622 name: InternPool.NullTerminatedString,1574 name: InternPool.NullTerminatedString,
1623) void {1575) void {
1624 if (coff.llvm_object) |_| return;
1625 const metadata = switch (exported) {1576 const metadata = switch (exported) {
1626 .nav => |nav| coff.navs.getPtr(nav),1577 .nav => |nav| coff.navs.getPtr(nav),
1627 .uav => |uav| coff.uavs.getPtr(uav),1578 .uav => |uav| coff.uavs.getPtr(uav),
...@@ -1692,7 +1643,7 @@ pub fn flush(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: st...@@ -1692,7 +1643,7 @@ pub fn flush(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: st
1692 };1643 };
1693 }1644 }
1694 switch (comp.config.output_mode) {1645 switch (comp.config.output_mode) {
1695 .Exe, .Obj => return coff.flushModule(arena, tid, prog_node),1646 .Exe, .Obj => return coff.flushZcu(arena, tid, prog_node),
1696 .Lib => return diags.fail("writing lib files not yet implemented for COFF", .{}),1647 .Lib => return diags.fail("writing lib files not yet implemented for COFF", .{}),
1697 }1648 }
1698}1649}
...@@ -1711,8 +1662,12 @@ fn linkWithLLD(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:...@@ -1711,8 +1662,12 @@ fn linkWithLLD(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:
17111662
1712 // If there is no Zig code to compile, then we should skip flushing the output file because it1663 // If there is no Zig code to compile, then we should skip flushing the output file because it
1713 // will not be part of the linker line anyway.1664 // will not be part of the linker line anyway.
1714 const module_obj_path: ?[]const u8 = if (comp.zcu != null) blk: {1665 const module_obj_path: ?[]const u8 = if (comp.zcu) |zcu| blk: {
1715 try coff.flushModule(arena, tid, prog_node);1666 if (zcu.llvm_object == null) {
1667 try coff.flushZcu(arena, tid, prog_node);
1668 } else {
1669 // `Compilation.flush` has already made LLVM emit this object file for us.
1670 }
17161671
1717 if (fs.path.dirname(full_out_path)) |dirname| {1672 if (fs.path.dirname(full_out_path)) |dirname| {
1718 break :blk try fs.path.join(arena, &.{ dirname, coff.base.zcu_object_sub_path.? });1673 break :blk try fs.path.join(arena, &.{ dirname, coff.base.zcu_object_sub_path.? });
...@@ -1998,16 +1953,16 @@ fn linkWithLLD(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:...@@ -1998,16 +1953,16 @@ fn linkWithLLD(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:
1998 if (coff.subsystem) |explicit| break :blk explicit;1953 if (coff.subsystem) |explicit| break :blk explicit;
1999 switch (target.os.tag) {1954 switch (target.os.tag) {
2000 .windows => {1955 .windows => {
2001 if (comp.zcu) |module| {1956 if (comp.zcu != null) {
2002 if (module.stage1_flags.have_dllmain_crt_startup or is_dyn_lib)1957 if (coff.lld_export_flags.dllmain_crt_startup or is_dyn_lib)
2003 break :blk null;1958 break :blk null;
2004 if (module.stage1_flags.have_c_main or comp.config.is_test or1959 if (coff.lld_export_flags.c_main or comp.config.is_test or
2005 module.stage1_flags.have_winmain_crt_startup or1960 coff.lld_export_flags.winmain_crt_startup or
2006 module.stage1_flags.have_wwinmain_crt_startup)1961 coff.lld_export_flags.wwinmain_crt_startup)
2007 {1962 {
2008 break :blk .Console;1963 break :blk .Console;
2009 }1964 }
2010 if (module.stage1_flags.have_winmain or module.stage1_flags.have_wwinmain)1965 if (coff.lld_export_flags.winmain or coff.lld_export_flags.wwinmain)
2011 break :blk .Windows;1966 break :blk .Windows;
2012 }1967 }
2013 },1968 },
...@@ -2136,8 +2091,8 @@ fn linkWithLLD(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:...@@ -2136,8 +2091,8 @@ fn linkWithLLD(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:
2136 } else {2091 } else {
2137 try argv.append("-NODEFAULTLIB");2092 try argv.append("-NODEFAULTLIB");
2138 if (!is_lib and entry_name == null) {2093 if (!is_lib and entry_name == null) {
2139 if (comp.zcu) |module| {2094 if (comp.zcu != null) {
2140 if (module.stage1_flags.have_winmain_crt_startup) {2095 if (coff.lld_export_flags.winmain_crt_startup) {
2141 try argv.append("-ENTRY:WinMainCRTStartup");2096 try argv.append("-ENTRY:WinMainCRTStartup");
2142 } else {2097 } else {
2143 try argv.append("-ENTRY:wWinMainCRTStartup");2098 try argv.append("-ENTRY:wWinMainCRTStartup");
...@@ -2244,7 +2199,7 @@ fn findLib(arena: Allocator, name: []const u8, lib_directories: []const Director...@@ -2244,7 +2199,7 @@ fn findLib(arena: Allocator, name: []const u8, lib_directories: []const Director
2244 return null;2199 return null;
2245}2200}
22462201
2247pub fn flushModule(2202pub fn flushZcu(
2248 coff: *Coff,2203 coff: *Coff,
2249 arena: Allocator,2204 arena: Allocator,
2250 tid: Zcu.PerThread.Id,2205 tid: Zcu.PerThread.Id,
...@@ -2256,22 +2211,17 @@ pub fn flushModule(...@@ -2256,22 +2211,17 @@ pub fn flushModule(
2256 const comp = coff.base.comp;2211 const comp = coff.base.comp;
2257 const diags = &comp.link_diags;2212 const diags = &comp.link_diags;
22582213
2259 if (coff.llvm_object) |llvm_object| {
2260 try coff.base.emitLlvmObject(arena, llvm_object, prog_node);
2261 return;
2262 }
2263
2264 const sub_prog_node = prog_node.start("COFF Flush", 0);2214 const sub_prog_node = prog_node.start("COFF Flush", 0);
2265 defer sub_prog_node.end();2215 defer sub_prog_node.end();
22662216
2267 return flushModuleInner(coff, arena, tid) catch |err| switch (err) {2217 return flushZcuInner(coff, arena, tid) catch |err| switch (err) {
2268 error.OutOfMemory => return error.OutOfMemory,2218 error.OutOfMemory => return error.OutOfMemory,
2269 error.LinkFailure => return error.LinkFailure,2219 error.LinkFailure => return error.LinkFailure,
2270 else => |e| return diags.fail("COFF flush failed: {s}", .{@errorName(e)}),2220 else => |e| return diags.fail("COFF flush failed: {s}", .{@errorName(e)}),
2271 };2221 };
2272}2222}
22732223
2274fn flushModuleInner(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id) !void {2224fn flushZcuInner(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id) !void {
2275 _ = arena;2225 _ = arena;
22762226
2277 const comp = coff.base.comp;2227 const comp = coff.base.comp;
...@@ -2397,7 +2347,6 @@ pub fn getNavVAddr(...@@ -2397,7 +2347,6 @@ pub fn getNavVAddr(
2397 nav_index: InternPool.Nav.Index,2347 nav_index: InternPool.Nav.Index,
2398 reloc_info: link.File.RelocInfo,2348 reloc_info: link.File.RelocInfo,
2399) !u64 {2349) !u64 {
2400 assert(coff.llvm_object == null);
2401 const zcu = pt.zcu;2350 const zcu = pt.zcu;
2402 const ip = &zcu.intern_pool;2351 const ip = &zcu.intern_pool;
2403 const nav = ip.getNav(nav_index);2352 const nav = ip.getNav(nav_index);
...@@ -2483,8 +2432,6 @@ pub fn getUavVAddr(...@@ -2483,8 +2432,6 @@ pub fn getUavVAddr(
2483 uav: InternPool.Index,2432 uav: InternPool.Index,
2484 reloc_info: link.File.RelocInfo,2433 reloc_info: link.File.RelocInfo,
2485) !u64 {2434) !u64 {
2486 assert(coff.llvm_object == null);
2487
2488 const this_atom_index = coff.uavs.get(uav).?.atom;2435 const this_atom_index = coff.uavs.get(uav).?.atom;
2489 const sym_index = coff.getAtom(this_atom_index).getSymbolIndex().?;2436 const sym_index = coff.getAtom(this_atom_index).getSymbolIndex().?;
2490 const atom_index = coff.getAtomIndexForSymbol(.{2437 const atom_index = coff.getAtomIndexForSymbol(.{
...@@ -3798,7 +3745,6 @@ const trace = @import("../tracy.zig").trace;...@@ -3798,7 +3745,6 @@ const trace = @import("../tracy.zig").trace;
37983745
3799const Air = @import("../Air.zig");3746const Air = @import("../Air.zig");
3800const Compilation = @import("../Compilation.zig");3747const Compilation = @import("../Compilation.zig");
3801const LlvmObject = @import("../codegen/llvm.zig").Object;
3802const Zcu = @import("../Zcu.zig");3748const Zcu = @import("../Zcu.zig");
3803const InternPool = @import("../InternPool.zig");3749const InternPool = @import("../InternPool.zig");
3804const TableSection = @import("table_section.zig").TableSection;3750const TableSection = @import("table_section.zig").TableSection;
src/link/Dwarf.zig+1-1
...@@ -4391,7 +4391,7 @@ fn refAbbrevCode(dwarf: *Dwarf, abbrev_code: AbbrevCode) UpdateError!@typeInfo(A...@@ -4391,7 +4391,7 @@ fn refAbbrevCode(dwarf: *Dwarf, abbrev_code: AbbrevCode) UpdateError!@typeInfo(A
4391 return @intFromEnum(abbrev_code);4391 return @intFromEnum(abbrev_code);
4392}4392}
43934393
4394pub fn flushModule(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {4394pub fn flushZcu(dwarf: *Dwarf, pt: Zcu.PerThread) FlushError!void {
4395 const zcu = pt.zcu;4395 const zcu = pt.zcu;
4396 const ip = &zcu.intern_pool;4396 const ip = &zcu.intern_pool;
43974397
src/link/Elf.zig+10-30
...@@ -32,9 +32,6 @@ entry_name: ?[]const u8,...@@ -32,9 +32,6 @@ entry_name: ?[]const u8,
3232
33ptr_width: PtrWidth,33ptr_width: PtrWidth,
3434
35/// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path.
36llvm_object: ?LlvmObject.Ptr = null,
37
38/// A list of all input files.35/// A list of all input files.
39/// First index is a special "null file". Order is otherwise not observed.36/// First index is a special "null file". Order is otherwise not observed.
40files: std.MultiArrayList(File.Entry) = .{},37files: std.MultiArrayList(File.Entry) = .{},
...@@ -344,9 +341,6 @@ pub fn createEmpty(...@@ -344,9 +341,6 @@ pub fn createEmpty(
344 .print_map = options.print_map,341 .print_map = options.print_map,
345 .dump_argv_list = .empty,342 .dump_argv_list = .empty,
346 };343 };
347 if (use_llvm and comp.config.have_zcu) {
348 self.llvm_object = try LlvmObject.create(arena, comp);
349 }
350 errdefer self.base.destroy();344 errdefer self.base.destroy();
351345
352 if (use_lld and (use_llvm or !comp.config.have_zcu)) {346 if (use_lld and (use_llvm or !comp.config.have_zcu)) {
...@@ -457,8 +451,6 @@ pub fn open(...@@ -457,8 +451,6 @@ pub fn open(
457pub fn deinit(self: *Elf) void {451pub fn deinit(self: *Elf) void {
458 const gpa = self.base.comp.gpa;452 const gpa = self.base.comp.gpa;
459453
460 if (self.llvm_object) |llvm_object| llvm_object.deinit();
461
462 for (self.file_handles.items) |fh| {454 for (self.file_handles.items) |fh| {
463 fh.close();455 fh.close();
464 }456 }
...@@ -515,7 +507,6 @@ pub fn deinit(self: *Elf) void {...@@ -515,7 +507,6 @@ pub fn deinit(self: *Elf) void {
515}507}
516508
517pub fn getNavVAddr(self: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 {509pub fn getNavVAddr(self: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 {
518 assert(self.llvm_object == null);
519 return self.zigObjectPtr().?.getNavVAddr(self, pt, nav_index, reloc_info);510 return self.zigObjectPtr().?.getNavVAddr(self, pt, nav_index, reloc_info);
520}511}
521512
...@@ -530,7 +521,6 @@ pub fn lowerUav(...@@ -530,7 +521,6 @@ pub fn lowerUav(
530}521}
531522
532pub fn getUavVAddr(self: *Elf, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {523pub fn getUavVAddr(self: *Elf, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {
533 assert(self.llvm_object == null);
534 return self.zigObjectPtr().?.getUavVAddr(self, uav, reloc_info);524 return self.zigObjectPtr().?.getUavVAddr(self, uav, reloc_info);
535}525}
536526
...@@ -805,35 +795,29 @@ pub fn flush(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std...@@ -805,35 +795,29 @@ pub fn flush(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std
805 else => |e| return diags.fail("failed to link with LLD: {s}", .{@errorName(e)}),795 else => |e| return diags.fail("failed to link with LLD: {s}", .{@errorName(e)}),
806 };796 };
807 }797 }
808 try self.flushModule(arena, tid, prog_node);798 try self.flushZcu(arena, tid, prog_node);
809}799}
810800
811pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {801pub fn flushZcu(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
812 const tracy = trace(@src());802 const tracy = trace(@src());
813 defer tracy.end();803 defer tracy.end();
814804
815 const comp = self.base.comp;805 const comp = self.base.comp;
816 const diags = &comp.link_diags;806 const diags = &comp.link_diags;
817807
818 if (self.llvm_object) |llvm_object| {
819 try self.base.emitLlvmObject(arena, llvm_object, prog_node);
820 const use_lld = build_options.have_llvm and comp.config.use_lld;
821 if (use_lld) return;
822 }
823
824 if (comp.verbose_link) Compilation.dump_argv(self.dump_argv_list.items);808 if (comp.verbose_link) Compilation.dump_argv(self.dump_argv_list.items);
825809
826 const sub_prog_node = prog_node.start("ELF Flush", 0);810 const sub_prog_node = prog_node.start("ELF Flush", 0);
827 defer sub_prog_node.end();811 defer sub_prog_node.end();
828812
829 return flushModuleInner(self, arena, tid) catch |err| switch (err) {813 return flushZcuInner(self, arena, tid) catch |err| switch (err) {
830 error.OutOfMemory => return error.OutOfMemory,814 error.OutOfMemory => return error.OutOfMemory,
831 error.LinkFailure => return error.LinkFailure,815 error.LinkFailure => return error.LinkFailure,
832 else => |e| return diags.fail("ELF flush failed: {s}", .{@errorName(e)}),816 else => |e| return diags.fail("ELF flush failed: {s}", .{@errorName(e)}),
833 };817 };
834}818}
835819
836fn flushModuleInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {820fn flushZcuInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
837 const comp = self.base.comp;821 const comp = self.base.comp;
838 const gpa = comp.gpa;822 const gpa = comp.gpa;
839 const diags = &comp.link_diags;823 const diags = &comp.link_diags;
...@@ -1523,8 +1507,12 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s...@@ -1523,8 +1507,12 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s
15231507
1524 // If there is no Zig code to compile, then we should skip flushing the output file because it1508 // If there is no Zig code to compile, then we should skip flushing the output file because it
1525 // will not be part of the linker line anyway.1509 // will not be part of the linker line anyway.
1526 const module_obj_path: ?[]const u8 = if (comp.zcu != null) blk: {1510 const module_obj_path: ?[]const u8 = if (comp.zcu) |zcu| blk: {
1527 try self.flushModule(arena, tid, prog_node);1511 if (zcu.llvm_object == null) {
1512 try self.flushZcu(arena, tid, prog_node);
1513 } else {
1514 // `Compilation.flush` has already made LLVM emit this object file for us.
1515 }
15281516
1529 if (fs.path.dirname(full_out_path)) |dirname| {1517 if (fs.path.dirname(full_out_path)) |dirname| {
1530 break :blk try fs.path.join(arena, &.{ dirname, self.base.zcu_object_sub_path.? });1518 break :blk try fs.path.join(arena, &.{ dirname, self.base.zcu_object_sub_path.? });
...@@ -2385,7 +2373,6 @@ pub fn writeElfHeader(self: *Elf) !void {...@@ -2385,7 +2373,6 @@ pub fn writeElfHeader(self: *Elf) !void {
2385}2373}
23862374
2387pub fn freeNav(self: *Elf, nav: InternPool.Nav.Index) void {2375pub fn freeNav(self: *Elf, nav: InternPool.Nav.Index) void {
2388 if (self.llvm_object) |llvm_object| return llvm_object.freeNav(nav);
2389 return self.zigObjectPtr().?.freeNav(self, nav);2376 return self.zigObjectPtr().?.freeNav(self, nav);
2390}2377}
23912378
...@@ -2399,7 +2386,6 @@ pub fn updateFunc(...@@ -2399,7 +2386,6 @@ pub fn updateFunc(
2399 if (build_options.skip_non_native and builtin.object_format != .elf) {2386 if (build_options.skip_non_native and builtin.object_format != .elf) {
2400 @panic("Attempted to compile for object format that was disabled by build configuration");2387 @panic("Attempted to compile for object format that was disabled by build configuration");
2401 }2388 }
2402 if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(pt, func_index, air, liveness);
2403 return self.zigObjectPtr().?.updateFunc(self, pt, func_index, air, liveness);2389 return self.zigObjectPtr().?.updateFunc(self, pt, func_index, air, liveness);
2404}2390}
24052391
...@@ -2411,7 +2397,6 @@ pub fn updateNav(...@@ -2411,7 +2397,6 @@ pub fn updateNav(
2411 if (build_options.skip_non_native and builtin.object_format != .elf) {2397 if (build_options.skip_non_native and builtin.object_format != .elf) {
2412 @panic("Attempted to compile for object format that was disabled by build configuration");2398 @panic("Attempted to compile for object format that was disabled by build configuration");
2413 }2399 }
2414 if (self.llvm_object) |llvm_object| return llvm_object.updateNav(pt, nav);
2415 return self.zigObjectPtr().?.updateNav(self, pt, nav);2400 return self.zigObjectPtr().?.updateNav(self, pt, nav);
2416}2401}
24172402
...@@ -2423,7 +2408,6 @@ pub fn updateContainerType(...@@ -2423,7 +2408,6 @@ pub fn updateContainerType(
2423 if (build_options.skip_non_native and builtin.object_format != .elf) {2408 if (build_options.skip_non_native and builtin.object_format != .elf) {
2424 @panic("Attempted to compile for object format that was disabled by build configuration");2409 @panic("Attempted to compile for object format that was disabled by build configuration");
2425 }2410 }
2426 if (self.llvm_object) |_| return;
2427 const zcu = pt.zcu;2411 const zcu = pt.zcu;
2428 const gpa = zcu.gpa;2412 const gpa = zcu.gpa;
2429 return self.zigObjectPtr().?.updateContainerType(pt, ty) catch |err| switch (err) {2413 return self.zigObjectPtr().?.updateContainerType(pt, ty) catch |err| switch (err) {
...@@ -2449,12 +2433,10 @@ pub fn updateExports(...@@ -2449,12 +2433,10 @@ pub fn updateExports(
2449 if (build_options.skip_non_native and builtin.object_format != .elf) {2433 if (build_options.skip_non_native and builtin.object_format != .elf) {
2450 @panic("Attempted to compile for object format that was disabled by build configuration");2434 @panic("Attempted to compile for object format that was disabled by build configuration");
2451 }2435 }
2452 if (self.llvm_object) |llvm_object| return llvm_object.updateExports(pt, exported, export_indices);
2453 return self.zigObjectPtr().?.updateExports(self, pt, exported, export_indices);2436 return self.zigObjectPtr().?.updateExports(self, pt, exported, export_indices);
2454}2437}
24552438
2456pub fn updateLineNumber(self: *Elf, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {2439pub fn updateLineNumber(self: *Elf, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
2457 if (self.llvm_object) |_| return;
2458 return self.zigObjectPtr().?.updateLineNumber(pt, ti_id);2440 return self.zigObjectPtr().?.updateLineNumber(pt, ti_id);
2459}2441}
24602442
...@@ -2463,7 +2445,6 @@ pub fn deleteExport(...@@ -2463,7 +2445,6 @@ pub fn deleteExport(
2463 exported: Zcu.Exported,2445 exported: Zcu.Exported,
2464 name: InternPool.NullTerminatedString,2446 name: InternPool.NullTerminatedString,
2465) void {2447) void {
2466 if (self.llvm_object) |_| return;
2467 return self.zigObjectPtr().?.deleteExport(self, exported, name);2448 return self.zigObjectPtr().?.deleteExport(self, exported, name);
2468}2449}
24692450
...@@ -5332,7 +5313,6 @@ const GotSection = synthetic_sections.GotSection;...@@ -5332,7 +5313,6 @@ const GotSection = synthetic_sections.GotSection;
5332const GotPltSection = synthetic_sections.GotPltSection;5313const GotPltSection = synthetic_sections.GotPltSection;
5333const HashSection = synthetic_sections.HashSection;5314const HashSection = synthetic_sections.HashSection;
5334const LinkerDefined = @import("Elf/LinkerDefined.zig");5315const LinkerDefined = @import("Elf/LinkerDefined.zig");
5335const LlvmObject = @import("../codegen/llvm.zig").Object;
5336const Zcu = @import("../Zcu.zig");5316const Zcu = @import("../Zcu.zig");
5337const Object = @import("Elf/Object.zig");5317const Object = @import("Elf/Object.zig");
5338const InternPool = @import("../InternPool.zig");5318const InternPool = @import("../InternPool.zig");
src/link/Elf/ZigObject.zig+4-4
...@@ -310,7 +310,7 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void {...@@ -310,7 +310,7 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void {
310 if (self.dwarf) |*dwarf| {310 if (self.dwarf) |*dwarf| {
311 const pt: Zcu.PerThread = .activate(elf_file.base.comp.zcu.?, tid);311 const pt: Zcu.PerThread = .activate(elf_file.base.comp.zcu.?, tid);
312 defer pt.deactivate();312 defer pt.deactivate();
313 try dwarf.flushModule(pt);313 try dwarf.flushZcu(pt);
314314
315 const gpa = elf_file.base.comp.gpa;315 const gpa = elf_file.base.comp.gpa;
316 const cpu_arch = elf_file.getTarget().cpu.arch;316 const cpu_arch = elf_file.getTarget().cpu.arch;
...@@ -481,7 +481,7 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void {...@@ -481,7 +481,7 @@ pub fn flush(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !void {
481 self.debug_str_section_dirty = false;481 self.debug_str_section_dirty = false;
482 }482 }
483483
484 // The point of flushModule() is to commit changes, so in theory, nothing should484 // The point of flushZcu() is to commit changes, so in theory, nothing should
485 // be dirty after this. However, it is possible for some things to remain485 // be dirty after this. However, it is possible for some things to remain
486 // dirty because they fail to be written in the event of compile errors,486 // dirty because they fail to be written in the event of compile errors,
487 // such as debug_line_header_dirty and debug_info_header_dirty.487 // such as debug_line_header_dirty and debug_info_header_dirty.
...@@ -661,7 +661,7 @@ pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void {...@@ -661,7 +661,7 @@ pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void {
661 if (shdr.sh_type == elf.SHT_NOBITS) continue;661 if (shdr.sh_type == elf.SHT_NOBITS) continue;
662 if (atom_ptr.scanRelocsRequiresCode(elf_file)) {662 if (atom_ptr.scanRelocsRequiresCode(elf_file)) {
663 // TODO ideally we don't have to fetch the code here.663 // TODO ideally we don't have to fetch the code here.
664 // Perhaps it would make sense to save the code until flushModule where we664 // Perhaps it would make sense to save the code until flushZcu where we
665 // would free all of generated code?665 // would free all of generated code?
666 const code = try self.codeAlloc(elf_file, atom_index);666 const code = try self.codeAlloc(elf_file, atom_index);
667 defer gpa.free(code);667 defer gpa.free(code);
...@@ -1075,7 +1075,7 @@ pub fn getOrCreateMetadataForLazySymbol(...@@ -1075,7 +1075,7 @@ pub fn getOrCreateMetadataForLazySymbol(
1075 }1075 }
1076 state_ptr.* = .pending_flush;1076 state_ptr.* = .pending_flush;
1077 const symbol_index = symbol_index_ptr.*;1077 const symbol_index = symbol_index_ptr.*;
1078 // anyerror needs to be deferred until flushModule1078 // anyerror needs to be deferred until flushZcu
1079 if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbol(elf_file, pt, lazy_sym, symbol_index);1079 if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbol(elf_file, pt, lazy_sym, symbol_index);
1080 return symbol_index;1080 return symbol_index;
1081}1081}
src/link/Goff.zig+22-24
...@@ -17,10 +17,8 @@ const link = @import("../link.zig");...@@ -17,10 +17,8 @@ const link = @import("../link.zig");
17const trace = @import("../tracy.zig").trace;17const trace = @import("../tracy.zig").trace;
18const build_options = @import("build_options");18const build_options = @import("build_options");
19const Air = @import("../Air.zig");19const Air = @import("../Air.zig");
20const LlvmObject = @import("../codegen/llvm.zig").Object;
2120
22base: link.File,21base: link.File,
23llvm_object: LlvmObject.Ptr,
2422
25pub fn createEmpty(23pub fn createEmpty(
26 arena: Allocator,24 arena: Allocator,
...@@ -36,7 +34,6 @@ pub fn createEmpty(...@@ -36,7 +34,6 @@ pub fn createEmpty(
36 assert(!use_lld); // Caught by Compilation.Config.resolve.34 assert(!use_lld); // Caught by Compilation.Config.resolve.
37 assert(target.os.tag == .zos); // Caught by Compilation.Config.resolve.35 assert(target.os.tag == .zos); // Caught by Compilation.Config.resolve.
3836
39 const llvm_object = try LlvmObject.create(arena, comp);
40 const goff = try arena.create(Goff);37 const goff = try arena.create(Goff);
41 goff.* = .{38 goff.* = .{
42 .base = .{39 .base = .{
...@@ -52,7 +49,6 @@ pub fn createEmpty(...@@ -52,7 +49,6 @@ pub fn createEmpty(
52 .disable_lld_caching = options.disable_lld_caching,49 .disable_lld_caching = options.disable_lld_caching,
53 .build_id = options.build_id,50 .build_id = options.build_id,
54 },51 },
55 .llvm_object = llvm_object,
56 };52 };
5753
58 return goff;54 return goff;
...@@ -70,7 +66,7 @@ pub fn open(...@@ -70,7 +66,7 @@ pub fn open(
70}66}
7167
72pub fn deinit(self: *Goff) void {68pub fn deinit(self: *Goff) void {
73 self.llvm_object.deinit();69 _ = self;
74}70}
7571
76pub fn updateFunc(72pub fn updateFunc(
...@@ -80,17 +76,19 @@ pub fn updateFunc(...@@ -80,17 +76,19 @@ pub fn updateFunc(
80 air: Air,76 air: Air,
81 liveness: Air.Liveness,77 liveness: Air.Liveness,
82) link.File.UpdateNavError!void {78) link.File.UpdateNavError!void {
83 if (build_options.skip_non_native and builtin.object_format != .goff)79 _ = self;
84 @panic("Attempted to compile for object format that was disabled by build configuration");80 _ = pt;
8581 _ = func_index;
86 try self.llvm_object.updateFunc(pt, func_index, air, liveness);82 _ = air;
83 _ = liveness;
84 unreachable; // we always use llvm
87}85}
8886
89pub fn updateNav(self: *Goff, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.File.UpdateNavError!void {87pub fn updateNav(self: *Goff, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.File.UpdateNavError!void {
90 if (build_options.skip_non_native and builtin.object_format != .goff)88 _ = self;
91 @panic("Attempted to compile for object format that was disabled by build configuration");89 _ = pt;
9290 _ = nav;
93 return self.llvm_object.updateNav(pt, nav);91 unreachable; // we always use llvm
94}92}
9593
96pub fn updateExports(94pub fn updateExports(
...@@ -99,21 +97,21 @@ pub fn updateExports(...@@ -99,21 +97,21 @@ pub fn updateExports(
99 exported: Zcu.Exported,97 exported: Zcu.Exported,
100 export_indices: []const Zcu.Export.Index,98 export_indices: []const Zcu.Export.Index,
101) !void {99) !void {
102 if (build_options.skip_non_native and builtin.object_format != .goff)100 _ = self;
103 @panic("Attempted to compile for object format that was disabled by build configuration");101 _ = pt;
104102 _ = exported;
105 return self.llvm_object.updateExports(pt, exported, export_indices);103 _ = export_indices;
104 unreachable; // we always use llvm
106}105}
107106
108pub fn flush(self: *Goff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {107pub fn flush(self: *Goff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
109 return self.flushModule(arena, tid, prog_node);108 return self.flushZcu(arena, tid, prog_node);
110}109}
111110
112pub fn flushModule(self: *Goff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {111pub fn flushZcu(self: *Goff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
113 if (build_options.skip_non_native and builtin.object_format != .goff)112 _ = self;
114 @panic("Attempted to compile for object format that was disabled by build configuration");113 _ = arena;
115
116 _ = tid;114 _ = tid;
117115 _ = prog_node;
118 try self.base.emitLlvmObject(arena, self.llvm_object, prog_node);116 unreachable; // we always use llvm
119}117}
src/link/MachO.zig+4-25
...@@ -6,9 +6,6 @@ base: link.File,...@@ -6,9 +6,6 @@ base: link.File,
66
7rpath_list: []const []const u8,7rpath_list: []const []const u8,
88
9/// If this is not null, an object file is created by LLVM and emitted to zcu_object_sub_path.
10llvm_object: ?LlvmObject.Ptr = null,
11
12/// Debug symbols bundle (or dSym).9/// Debug symbols bundle (or dSym).
13d_sym: ?DebugSymbols = null,10d_sym: ?DebugSymbols = null,
1411
...@@ -225,9 +222,6 @@ pub fn createEmpty(...@@ -225,9 +222,6 @@ pub fn createEmpty(
225 .force_load_objc = options.force_load_objc,222 .force_load_objc = options.force_load_objc,
226 .discard_local_symbols = options.discard_local_symbols,223 .discard_local_symbols = options.discard_local_symbols,
227 };224 };
228 if (use_llvm and comp.config.have_zcu) {
229 self.llvm_object = try LlvmObject.create(arena, comp);
230 }
231 errdefer self.base.destroy();225 errdefer self.base.destroy();
232226
233 self.base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{227 self.base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{
...@@ -280,8 +274,6 @@ pub fn open(...@@ -280,8 +274,6 @@ pub fn open(
280pub fn deinit(self: *MachO) void {274pub fn deinit(self: *MachO) void {
281 const gpa = self.base.comp.gpa;275 const gpa = self.base.comp.gpa;
282276
283 if (self.llvm_object) |llvm_object| llvm_object.deinit();
284
285 if (self.d_sym) |*d_sym| {277 if (self.d_sym) |*d_sym| {
286 d_sym.deinit();278 d_sym.deinit();
287 }279 }
...@@ -350,10 +342,10 @@ pub fn flush(...@@ -350,10 +342,10 @@ pub fn flush(
350 tid: Zcu.PerThread.Id,342 tid: Zcu.PerThread.Id,
351 prog_node: std.Progress.Node,343 prog_node: std.Progress.Node,
352) link.File.FlushError!void {344) link.File.FlushError!void {
353 try self.flushModule(arena, tid, prog_node);345 try self.flushZcu(arena, tid, prog_node);
354}346}
355347
356pub fn flushModule(348pub fn flushZcu(
357 self: *MachO,349 self: *MachO,
358 arena: Allocator,350 arena: Allocator,
359 tid: Zcu.PerThread.Id,351 tid: Zcu.PerThread.Id,
...@@ -366,10 +358,6 @@ pub fn flushModule(...@@ -366,10 +358,6 @@ pub fn flushModule(
366 const gpa = comp.gpa;358 const gpa = comp.gpa;
367 const diags = &self.base.comp.link_diags;359 const diags = &self.base.comp.link_diags;
368360
369 if (self.llvm_object) |llvm_object| {
370 try self.base.emitLlvmObject(arena, llvm_object, prog_node);
371 }
372
373 const sub_prog_node = prog_node.start("MachO Flush", 0);361 const sub_prog_node = prog_node.start("MachO Flush", 0);
374 defer sub_prog_node.end();362 defer sub_prog_node.end();
375363
...@@ -385,7 +373,7 @@ pub fn flushModule(...@@ -385,7 +373,7 @@ pub fn flushModule(
385 // --verbose-link373 // --verbose-link
386 if (comp.verbose_link) try self.dumpArgv(comp);374 if (comp.verbose_link) try self.dumpArgv(comp);
387375
388 if (self.getZigObject()) |zo| try zo.flushModule(self, tid);376 if (self.getZigObject()) |zo| try zo.flushZcu(self, tid);
389 if (self.base.isStaticLib()) return relocatable.flushStaticLib(self, comp, module_obj_path);377 if (self.base.isStaticLib()) return relocatable.flushStaticLib(self, comp, module_obj_path);
390 if (self.base.isObject()) return relocatable.flushObject(self, comp, module_obj_path);378 if (self.base.isObject()) return relocatable.flushObject(self, comp, module_obj_path);
391379
...@@ -629,7 +617,7 @@ pub fn flushModule(...@@ -629,7 +617,7 @@ pub fn flushModule(
629 error.LinkFailure => return error.LinkFailure,617 error.LinkFailure => return error.LinkFailure,
630 else => |e| return diags.fail("failed to calculate and write uuid: {s}", .{@errorName(e)}),618 else => |e| return diags.fail("failed to calculate and write uuid: {s}", .{@errorName(e)}),
631 };619 };
632 if (self.getDebugSymbols()) |dsym| dsym.flushModule(self) catch |err| switch (err) {620 if (self.getDebugSymbols()) |dsym| dsym.flushZcu(self) catch |err| switch (err) {
633 error.OutOfMemory => return error.OutOfMemory,621 error.OutOfMemory => return error.OutOfMemory,
634 else => |e| return diags.fail("failed to get debug symbols: {s}", .{@errorName(e)}),622 else => |e| return diags.fail("failed to get debug symbols: {s}", .{@errorName(e)}),
635 };623 };
...@@ -3079,7 +3067,6 @@ pub fn updateFunc(...@@ -3079,7 +3067,6 @@ pub fn updateFunc(
3079 if (build_options.skip_non_native and builtin.object_format != .macho) {3067 if (build_options.skip_non_native and builtin.object_format != .macho) {
3080 @panic("Attempted to compile for object format that was disabled by build configuration");3068 @panic("Attempted to compile for object format that was disabled by build configuration");
3081 }3069 }
3082 if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(pt, func_index, air, liveness);
3083 return self.getZigObject().?.updateFunc(self, pt, func_index, air, liveness);3070 return self.getZigObject().?.updateFunc(self, pt, func_index, air, liveness);
3084}3071}
30853072
...@@ -3087,12 +3074,10 @@ pub fn updateNav(self: *MachO, pt: Zcu.PerThread, nav: InternPool.Nav.Index) lin...@@ -3087,12 +3074,10 @@ pub fn updateNav(self: *MachO, pt: Zcu.PerThread, nav: InternPool.Nav.Index) lin
3087 if (build_options.skip_non_native and builtin.object_format != .macho) {3074 if (build_options.skip_non_native and builtin.object_format != .macho) {
3088 @panic("Attempted to compile for object format that was disabled by build configuration");3075 @panic("Attempted to compile for object format that was disabled by build configuration");
3089 }3076 }
3090 if (self.llvm_object) |llvm_object| return llvm_object.updateNav(pt, nav);
3091 return self.getZigObject().?.updateNav(self, pt, nav);3077 return self.getZigObject().?.updateNav(self, pt, nav);
3092}3078}
30933079
3094pub fn updateLineNumber(self: *MachO, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {3080pub fn updateLineNumber(self: *MachO, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void {
3095 if (self.llvm_object) |_| return;
3096 return self.getZigObject().?.updateLineNumber(pt, ti_id);3081 return self.getZigObject().?.updateLineNumber(pt, ti_id);
3097}3082}
30983083
...@@ -3105,7 +3090,6 @@ pub fn updateExports(...@@ -3105,7 +3090,6 @@ pub fn updateExports(
3105 if (build_options.skip_non_native and builtin.object_format != .macho) {3090 if (build_options.skip_non_native and builtin.object_format != .macho) {
3106 @panic("Attempted to compile for object format that was disabled by build configuration");3091 @panic("Attempted to compile for object format that was disabled by build configuration");
3107 }3092 }
3108 if (self.llvm_object) |llvm_object| return llvm_object.updateExports(pt, exported, export_indices);
3109 return self.getZigObject().?.updateExports(self, pt, exported, export_indices);3093 return self.getZigObject().?.updateExports(self, pt, exported, export_indices);
3110}3094}
31113095
...@@ -3114,17 +3098,14 @@ pub fn deleteExport(...@@ -3114,17 +3098,14 @@ pub fn deleteExport(
3114 exported: Zcu.Exported,3098 exported: Zcu.Exported,
3115 name: InternPool.NullTerminatedString,3099 name: InternPool.NullTerminatedString,
3116) void {3100) void {
3117 if (self.llvm_object) |_| return;
3118 return self.getZigObject().?.deleteExport(self, exported, name);3101 return self.getZigObject().?.deleteExport(self, exported, name);
3119}3102}
31203103
3121pub fn freeNav(self: *MachO, nav: InternPool.Nav.Index) void {3104pub fn freeNav(self: *MachO, nav: InternPool.Nav.Index) void {
3122 if (self.llvm_object) |llvm_object| return llvm_object.freeNav(nav);
3123 return self.getZigObject().?.freeNav(nav);3105 return self.getZigObject().?.freeNav(nav);
3124}3106}
31253107
3126pub fn getNavVAddr(self: *MachO, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 {3108pub fn getNavVAddr(self: *MachO, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index, reloc_info: link.File.RelocInfo) !u64 {
3127 assert(self.llvm_object == null);
3128 return self.getZigObject().?.getNavVAddr(self, pt, nav_index, reloc_info);3109 return self.getZigObject().?.getNavVAddr(self, pt, nav_index, reloc_info);
3129}3110}
31303111
...@@ -3139,7 +3120,6 @@ pub fn lowerUav(...@@ -3139,7 +3120,6 @@ pub fn lowerUav(
3139}3120}
31403121
3141pub fn getUavVAddr(self: *MachO, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {3122pub fn getUavVAddr(self: *MachO, uav: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {
3142 assert(self.llvm_object == null);
3143 return self.getZigObject().?.getUavVAddr(self, uav, reloc_info);3123 return self.getZigObject().?.getUavVAddr(self, uav, reloc_info);
3144}3124}
31453125
...@@ -5496,7 +5476,6 @@ const ObjcStubsSection = synthetic.ObjcStubsSection;...@@ -5496,7 +5476,6 @@ const ObjcStubsSection = synthetic.ObjcStubsSection;
5496const Object = @import("MachO/Object.zig");5476const Object = @import("MachO/Object.zig");
5497const LazyBind = bind.LazyBind;5477const LazyBind = bind.LazyBind;
5498const LaSymbolPtrSection = synthetic.LaSymbolPtrSection;5478const LaSymbolPtrSection = synthetic.LaSymbolPtrSection;
5499const LlvmObject = @import("../codegen/llvm.zig").Object;
5500const Md5 = std.crypto.hash.Md5;5479const Md5 = std.crypto.hash.Md5;
5501const Zcu = @import("../Zcu.zig");5480const Zcu = @import("../Zcu.zig");
5502const InternPool = @import("../InternPool.zig");5481const InternPool = @import("../InternPool.zig");
src/link/MachO/DebugSymbols.zig+1-1
...@@ -178,7 +178,7 @@ fn findFreeSpace(self: *DebugSymbols, object_size: u64, min_alignment: u64) !u64...@@ -178,7 +178,7 @@ fn findFreeSpace(self: *DebugSymbols, object_size: u64, min_alignment: u64) !u64
178 return offset;178 return offset;
179}179}
180180
181pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void {181pub fn flushZcu(self: *DebugSymbols, macho_file: *MachO) !void {
182 const zo = macho_file.getZigObject().?;182 const zo = macho_file.getZigObject().?;
183 for (self.relocs.items) |*reloc| {183 for (self.relocs.items) |*reloc| {
184 const sym = zo.symbols.items[reloc.target];184 const sym = zo.symbols.items[reloc.target];
src/link/MachO/ZigObject.zig+4-4
...@@ -550,7 +550,7 @@ pub fn getInputSection(self: ZigObject, atom: Atom, macho_file: *MachO) macho.se...@@ -550,7 +550,7 @@ pub fn getInputSection(self: ZigObject, atom: Atom, macho_file: *MachO) macho.se
550 return sect;550 return sect;
551}551}
552552
553pub fn flushModule(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.File.FlushError!void {553pub fn flushZcu(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id) link.File.FlushError!void {
554 const diags = &macho_file.base.comp.link_diags;554 const diags = &macho_file.base.comp.link_diags;
555555
556 // Handle any lazy symbols that were emitted by incremental compilation.556 // Handle any lazy symbols that were emitted by incremental compilation.
...@@ -589,7 +589,7 @@ pub fn flushModule(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id)...@@ -589,7 +589,7 @@ pub fn flushModule(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id)
589 if (self.dwarf) |*dwarf| {589 if (self.dwarf) |*dwarf| {
590 const pt: Zcu.PerThread = .activate(macho_file.base.comp.zcu.?, tid);590 const pt: Zcu.PerThread = .activate(macho_file.base.comp.zcu.?, tid);
591 defer pt.deactivate();591 defer pt.deactivate();
592 dwarf.flushModule(pt) catch |err| switch (err) {592 dwarf.flushZcu(pt) catch |err| switch (err) {
593 error.OutOfMemory => return error.OutOfMemory,593 error.OutOfMemory => return error.OutOfMemory,
594 else => |e| return diags.fail("failed to flush dwarf module: {s}", .{@errorName(e)}),594 else => |e| return diags.fail("failed to flush dwarf module: {s}", .{@errorName(e)}),
595 };595 };
...@@ -599,7 +599,7 @@ pub fn flushModule(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id)...@@ -599,7 +599,7 @@ pub fn flushModule(self: *ZigObject, macho_file: *MachO, tid: Zcu.PerThread.Id)
599 self.debug_strtab_dirty = false;599 self.debug_strtab_dirty = false;
600 }600 }
601601
602 // The point of flushModule() is to commit changes, so in theory, nothing should602 // The point of flushZcu() is to commit changes, so in theory, nothing should
603 // be dirty after this. However, it is possible for some things to remain603 // be dirty after this. However, it is possible for some things to remain
604 // dirty because they fail to be written in the event of compile errors,604 // dirty because they fail to be written in the event of compile errors,
605 // such as debug_line_header_dirty and debug_info_header_dirty.605 // such as debug_line_header_dirty and debug_info_header_dirty.
...@@ -1537,7 +1537,7 @@ pub fn getOrCreateMetadataForLazySymbol(...@@ -1537,7 +1537,7 @@ pub fn getOrCreateMetadataForLazySymbol(
1537 }1537 }
1538 state_ptr.* = .pending_flush;1538 state_ptr.* = .pending_flush;
1539 const symbol_index = symbol_index_ptr.*;1539 const symbol_index = symbol_index_ptr.*;
1540 // anyerror needs to be deferred until flushModule1540 // anyerror needs to be deferred until flushZcu
1541 if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbol(macho_file, pt, lazy_sym, symbol_index);1541 if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbol(macho_file, pt, lazy_sym, symbol_index);
1542 return symbol_index;1542 return symbol_index;
1543}1543}
src/link/Plan9.zig+5-5
...@@ -494,7 +494,7 @@ fn updateFinish(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index...@@ -494,7 +494,7 @@ fn updateFinish(self: *Plan9, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index
494 // write the symbol494 // write the symbol
495 // we already have the got index495 // we already have the got index
496 const sym: aout.Sym = .{496 const sym: aout.Sym = .{
497 .value = undefined, // the value of stuff gets filled in in flushModule497 .value = undefined, // the value of stuff gets filled in in flushZcu
498 .type = atom.type,498 .type = atom.type,
499 .name = try gpa.dupe(u8, nav.name.toSlice(ip)),499 .name = try gpa.dupe(u8, nav.name.toSlice(ip)),
500 };500 };
...@@ -543,7 +543,7 @@ pub fn flush(...@@ -543,7 +543,7 @@ pub fn flush(
543 .Obj => return diags.fail("writing plan9 object files unimplemented", .{}),543 .Obj => return diags.fail("writing plan9 object files unimplemented", .{}),
544 .Lib => return diags.fail("writing plan9 lib files unimplemented", .{}),544 .Lib => return diags.fail("writing plan9 lib files unimplemented", .{}),
545 }545 }
546 return self.flushModule(arena, tid, prog_node);546 return self.flushZcu(arena, tid, prog_node);
547}547}
548548
549pub fn changeLine(l: *std.ArrayList(u8), delta_line: i32) !void {549pub fn changeLine(l: *std.ArrayList(u8), delta_line: i32) !void {
...@@ -586,7 +586,7 @@ fn atomCount(self: *Plan9) usize {...@@ -586,7 +586,7 @@ fn atomCount(self: *Plan9) usize {
586 return data_nav_count + fn_nav_count + lazy_atom_count + extern_atom_count + uav_atom_count;586 return data_nav_count + fn_nav_count + lazy_atom_count + extern_atom_count + uav_atom_count;
587}587}
588588
589pub fn flushModule(589pub fn flushZcu(
590 self: *Plan9,590 self: *Plan9,
591 arena: Allocator,591 arena: Allocator,
592 /// TODO: stop using this592 /// TODO: stop using this
...@@ -610,7 +610,7 @@ pub fn flushModule(...@@ -610,7 +610,7 @@ pub fn flushModule(
610 const sub_prog_node = prog_node.start("Flush Module", 0);610 const sub_prog_node = prog_node.start("Flush Module", 0);
611 defer sub_prog_node.end();611 defer sub_prog_node.end();
612612
613 log.debug("flushModule", .{});613 log.debug("flushZcu", .{});
614614
615 defer assert(self.hdr.entry != 0x0);615 defer assert(self.hdr.entry != 0x0);
616616
...@@ -1039,7 +1039,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *Plan9, pt: Zcu.PerThread, lazy_sym: F...@@ -1039,7 +1039,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *Plan9, pt: Zcu.PerThread, lazy_sym: F
1039 const atom = atom_ptr.*;1039 const atom = atom_ptr.*;
1040 _ = try self.getAtomPtr(atom).getOrCreateSymbolTableEntry(self);1040 _ = try self.getAtomPtr(atom).getOrCreateSymbolTableEntry(self);
1041 _ = self.getAtomPtr(atom).getOrCreateOffsetTableEntry(self);1041 _ = self.getAtomPtr(atom).getOrCreateOffsetTableEntry(self);
1042 // anyerror needs to be deferred until flushModule1042 // anyerror needs to be deferred until flushZcu
1043 if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbolAtom(pt, lazy_sym, atom);1043 if (lazy_sym.ty != .anyerror_type) try self.updateLazySymbolAtom(pt, lazy_sym, atom);
1044 return atom;1044 return atom;
1045}1045}
src/link/SpirV.zig+4-4
...@@ -17,7 +17,7 @@...@@ -17,7 +17,7 @@
17//! All regular functions.17//! All regular functions.
1818
19// Because SPIR-V requires re-compilation anyway, and so hot swapping will not work19// Because SPIR-V requires re-compilation anyway, and so hot swapping will not work
20// anyway, we simply generate all the code in flushModule. This keeps20// anyway, we simply generate all the code in flushZcu. This keeps
21// things considerably simpler.21// things considerably simpler.
2222
23const SpirV = @This();23const SpirV = @This();
...@@ -194,17 +194,17 @@ pub fn updateExports(...@@ -194,17 +194,17 @@ pub fn updateExports(
194}194}
195195
196pub fn flush(self: *SpirV, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {196pub fn flush(self: *SpirV, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
197 return self.flushModule(arena, tid, prog_node);197 return self.flushZcu(arena, tid, prog_node);
198}198}
199199
200pub fn flushModule(200pub fn flushZcu(
201 self: *SpirV,201 self: *SpirV,
202 arena: Allocator,202 arena: Allocator,
203 tid: Zcu.PerThread.Id,203 tid: Zcu.PerThread.Id,
204 prog_node: std.Progress.Node,204 prog_node: std.Progress.Node,
205) link.File.FlushError!void {205) link.File.FlushError!void {
206 // The goal is to never use this because it's only needed if we need to206 // The goal is to never use this because it's only needed if we need to
207 // write to InternPool, but flushModule is too late to be writing to the207 // write to InternPool, but flushZcu is too late to be writing to the
208 // InternPool.208 // InternPool.
209 _ = tid;209 _ = tid;
210210
src/link/Wasm.zig+9-23
...@@ -36,7 +36,6 @@ const abi = @import("../arch/wasm/abi.zig");...@@ -36,7 +36,6 @@ const abi = @import("../arch/wasm/abi.zig");
36const Compilation = @import("../Compilation.zig");36const Compilation = @import("../Compilation.zig");
37const Dwarf = @import("Dwarf.zig");37const Dwarf = @import("Dwarf.zig");
38const InternPool = @import("../InternPool.zig");38const InternPool = @import("../InternPool.zig");
39const LlvmObject = @import("../codegen/llvm.zig").Object;
40const Zcu = @import("../Zcu.zig");39const Zcu = @import("../Zcu.zig");
41const codegen = @import("../codegen.zig");40const codegen = @import("../codegen.zig");
42const dev = @import("../dev.zig");41const dev = @import("../dev.zig");
...@@ -81,8 +80,6 @@ import_table: bool,...@@ -81,8 +80,6 @@ import_table: bool,
81export_table: bool,80export_table: bool,
82/// Output name of the file81/// Output name of the file
83name: []const u8,82name: []const u8,
84/// If this is not null, an object file is created by LLVM and linked with LLD afterwards.
85llvm_object: ?LlvmObject.Ptr = null,
86/// List of relocatable files to be linked into the final binary.83/// List of relocatable files to be linked into the final binary.
87objects: std.ArrayListUnmanaged(Object) = .{},84objects: std.ArrayListUnmanaged(Object) = .{},
8885
...@@ -2992,9 +2989,6 @@ pub fn createEmpty(...@@ -2992,9 +2989,6 @@ pub fn createEmpty(
2992 .object_host_name = .none,2989 .object_host_name = .none,
2993 .preloaded_strings = undefined,2990 .preloaded_strings = undefined,
2994 };2991 };
2995 if (use_llvm and comp.config.have_zcu) {
2996 wasm.llvm_object = try LlvmObject.create(arena, comp);
2997 }
2998 errdefer wasm.base.destroy();2992 errdefer wasm.base.destroy();
29992993
3000 if (options.object_host_name) |name| wasm.object_host_name = (try wasm.internString(name)).toOptional();2994 if (options.object_host_name) |name| wasm.object_host_name = (try wasm.internString(name)).toOptional();
...@@ -3116,7 +3110,6 @@ fn parseArchive(wasm: *Wasm, obj: link.Input.Object) !void {...@@ -3116,7 +3110,6 @@ fn parseArchive(wasm: *Wasm, obj: link.Input.Object) !void {
31163110
3117pub fn deinit(wasm: *Wasm) void {3111pub fn deinit(wasm: *Wasm) void {
3118 const gpa = wasm.base.comp.gpa;3112 const gpa = wasm.base.comp.gpa;
3119 if (wasm.llvm_object) |llvm_object| llvm_object.deinit();
31203113
3121 wasm.navs_exe.deinit(gpa);3114 wasm.navs_exe.deinit(gpa);
3122 wasm.navs_obj.deinit(gpa);3115 wasm.navs_obj.deinit(gpa);
...@@ -3196,7 +3189,6 @@ pub fn updateFunc(wasm: *Wasm, pt: Zcu.PerThread, func_index: InternPool.Index,...@@ -3196,7 +3189,6 @@ pub fn updateFunc(wasm: *Wasm, pt: Zcu.PerThread, func_index: InternPool.Index,
3196 if (build_options.skip_non_native and builtin.object_format != .wasm) {3189 if (build_options.skip_non_native and builtin.object_format != .wasm) {
3197 @panic("Attempted to compile for object format that was disabled by build configuration");3190 @panic("Attempted to compile for object format that was disabled by build configuration");
3198 }3191 }
3199 if (wasm.llvm_object) |llvm_object| return llvm_object.updateFunc(pt, func_index, air, liveness);
32003192
3201 dev.check(.wasm_backend);3193 dev.check(.wasm_backend);
32023194
...@@ -3228,7 +3220,6 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index...@@ -3228,7 +3220,6 @@ pub fn updateNav(wasm: *Wasm, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index
3228 if (build_options.skip_non_native and builtin.object_format != .wasm) {3220 if (build_options.skip_non_native and builtin.object_format != .wasm) {
3229 @panic("Attempted to compile for object format that was disabled by build configuration");3221 @panic("Attempted to compile for object format that was disabled by build configuration");
3230 }3222 }
3231 if (wasm.llvm_object) |llvm_object| return llvm_object.updateNav(pt, nav_index);
3232 const zcu = pt.zcu;3223 const zcu = pt.zcu;
3233 const ip = &zcu.intern_pool;3224 const ip = &zcu.intern_pool;
3234 const nav = ip.getNav(nav_index);3225 const nav = ip.getNav(nav_index);
...@@ -3308,8 +3299,6 @@ pub fn deleteExport(...@@ -3308,8 +3299,6 @@ pub fn deleteExport(
3308 exported: Zcu.Exported,3299 exported: Zcu.Exported,
3309 name: InternPool.NullTerminatedString,3300 name: InternPool.NullTerminatedString,
3310) void {3301) void {
3311 if (wasm.llvm_object != null) return;
3312
3313 const zcu = wasm.base.comp.zcu.?;3302 const zcu = wasm.base.comp.zcu.?;
3314 const ip = &zcu.intern_pool;3303 const ip = &zcu.intern_pool;
3315 const name_slice = name.toSlice(ip);3304 const name_slice = name.toSlice(ip);
...@@ -3332,7 +3321,6 @@ pub fn updateExports(...@@ -3332,7 +3321,6 @@ pub fn updateExports(
3332 if (build_options.skip_non_native and builtin.object_format != .wasm) {3321 if (build_options.skip_non_native and builtin.object_format != .wasm) {
3333 @panic("Attempted to compile for object format that was disabled by build configuration");3322 @panic("Attempted to compile for object format that was disabled by build configuration");
3334 }3323 }
3335 if (wasm.llvm_object) |llvm_object| return llvm_object.updateExports(pt, exported, export_indices);
33363324
3337 const zcu = pt.zcu;3325 const zcu = pt.zcu;
3338 const gpa = zcu.gpa;3326 const gpa = zcu.gpa;
...@@ -3391,7 +3379,7 @@ pub fn flush(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: st...@@ -3391,7 +3379,7 @@ pub fn flush(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: st
3391 else => |e| return diags.fail("failed to link with LLD: {s}", .{@errorName(e)}),3379 else => |e| return diags.fail("failed to link with LLD: {s}", .{@errorName(e)}),
3392 };3380 };
3393 }3381 }
3394 return wasm.flushModule(arena, tid, prog_node);3382 return wasm.flushZcu(arena, tid, prog_node);
3395}3383}
33963384
3397pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!void {3385pub fn prelink(wasm: *Wasm, prog_node: std.Progress.Node) link.File.FlushError!void {
...@@ -3785,26 +3773,20 @@ fn markTable(wasm: *Wasm, i: ObjectTableIndex) link.File.FlushError!void {...@@ -3785,26 +3773,20 @@ fn markTable(wasm: *Wasm, i: ObjectTableIndex) link.File.FlushError!void {
3785 try wasm.tables.put(wasm.base.comp.gpa, .fromObjectTable(i), {});3773 try wasm.tables.put(wasm.base.comp.gpa, .fromObjectTable(i), {});
3786}3774}
37873775
3788pub fn flushModule(3776pub fn flushZcu(
3789 wasm: *Wasm,3777 wasm: *Wasm,
3790 arena: Allocator,3778 arena: Allocator,
3791 tid: Zcu.PerThread.Id,3779 tid: Zcu.PerThread.Id,
3792 prog_node: std.Progress.Node,3780 prog_node: std.Progress.Node,
3793) link.File.FlushError!void {3781) link.File.FlushError!void {
3794 // The goal is to never use this because it's only needed if we need to3782 // The goal is to never use this because it's only needed if we need to
3795 // write to InternPool, but flushModule is too late to be writing to the3783 // write to InternPool, but flushZcu is too late to be writing to the
3796 // InternPool.3784 // InternPool.
3797 _ = tid;3785 _ = tid;
3798 const comp = wasm.base.comp;3786 const comp = wasm.base.comp;
3799 const use_lld = build_options.have_llvm and comp.config.use_lld;
3800 const diags = &comp.link_diags;3787 const diags = &comp.link_diags;
3801 const gpa = comp.gpa;3788 const gpa = comp.gpa;
38023789
3803 if (wasm.llvm_object) |llvm_object| {
3804 try wasm.base.emitLlvmObject(arena, llvm_object, prog_node);
3805 if (use_lld) return;
3806 }
3807
3808 if (comp.verbose_link) Compilation.dump_argv(wasm.dump_argv_list.items);3790 if (comp.verbose_link) Compilation.dump_argv(wasm.dump_argv_list.items);
38093791
3810 if (wasm.base.zcu_object_sub_path) |path| {3792 if (wasm.base.zcu_object_sub_path) |path| {
...@@ -3870,8 +3852,12 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:...@@ -3870,8 +3852,12 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:
38703852
3871 // If there is no Zig code to compile, then we should skip flushing the output file because it3853 // If there is no Zig code to compile, then we should skip flushing the output file because it
3872 // will not be part of the linker line anyway.3854 // will not be part of the linker line anyway.
3873 const module_obj_path: ?[]const u8 = if (comp.zcu != null) blk: {3855 const module_obj_path: ?[]const u8 = if (comp.zcu) |zcu| blk: {
3874 try wasm.flushModule(arena, tid, prog_node);3856 if (zcu.llvm_object == null) {
3857 try wasm.flushZcu(arena, tid, prog_node);
3858 } else {
3859 // `Compilation.flush` has already made LLVM emit this object file for us.
3860 }
38753861
3876 if (fs.path.dirname(full_out_path)) |dirname| {3862 if (fs.path.dirname(full_out_path)) |dirname| {
3877 break :blk try fs.path.join(arena, &.{ dirname, wasm.base.zcu_object_sub_path.? });3863 break :blk try fs.path.join(arena, &.{ dirname, wasm.base.zcu_object_sub_path.? });
src/link/Xcoff.zig+22-24
...@@ -17,10 +17,8 @@ const link = @import("../link.zig");...@@ -17,10 +17,8 @@ const link = @import("../link.zig");
17const trace = @import("../tracy.zig").trace;17const trace = @import("../tracy.zig").trace;
18const build_options = @import("build_options");18const build_options = @import("build_options");
19const Air = @import("../Air.zig");19const Air = @import("../Air.zig");
20const LlvmObject = @import("../codegen/llvm.zig").Object;
2120
22base: link.File,21base: link.File,
23llvm_object: LlvmObject.Ptr,
2422
25pub fn createEmpty(23pub fn createEmpty(
26 arena: Allocator,24 arena: Allocator,
...@@ -36,7 +34,6 @@ pub fn createEmpty(...@@ -36,7 +34,6 @@ pub fn createEmpty(
36 assert(!use_lld); // Caught by Compilation.Config.resolve.34 assert(!use_lld); // Caught by Compilation.Config.resolve.
37 assert(target.os.tag == .aix); // Caught by Compilation.Config.resolve.35 assert(target.os.tag == .aix); // Caught by Compilation.Config.resolve.
3836
39 const llvm_object = try LlvmObject.create(arena, comp);
40 const xcoff = try arena.create(Xcoff);37 const xcoff = try arena.create(Xcoff);
41 xcoff.* = .{38 xcoff.* = .{
42 .base = .{39 .base = .{
...@@ -52,7 +49,6 @@ pub fn createEmpty(...@@ -52,7 +49,6 @@ pub fn createEmpty(
52 .disable_lld_caching = options.disable_lld_caching,49 .disable_lld_caching = options.disable_lld_caching,
53 .build_id = options.build_id,50 .build_id = options.build_id,
54 },51 },
55 .llvm_object = llvm_object,
56 };52 };
5753
58 return xcoff;54 return xcoff;
...@@ -70,7 +66,7 @@ pub fn open(...@@ -70,7 +66,7 @@ pub fn open(
70}66}
7167
72pub fn deinit(self: *Xcoff) void {68pub fn deinit(self: *Xcoff) void {
73 self.llvm_object.deinit();69 _ = self;
74}70}
7571
76pub fn updateFunc(72pub fn updateFunc(
...@@ -80,17 +76,19 @@ pub fn updateFunc(...@@ -80,17 +76,19 @@ pub fn updateFunc(
80 air: Air,76 air: Air,
81 liveness: Air.Liveness,77 liveness: Air.Liveness,
82) link.File.UpdateNavError!void {78) link.File.UpdateNavError!void {
83 if (build_options.skip_non_native and builtin.object_format != .xcoff)79 _ = self;
84 @panic("Attempted to compile for object format that was disabled by build configuration");80 _ = pt;
8581 _ = func_index;
86 try self.llvm_object.updateFunc(pt, func_index, air, liveness);82 _ = air;
83 _ = liveness;
84 unreachable; // we always use llvm
87}85}
8886
89pub fn updateNav(self: *Xcoff, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.File.UpdateNavError!void {87pub fn updateNav(self: *Xcoff, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.File.UpdateNavError!void {
90 if (build_options.skip_non_native and builtin.object_format != .xcoff)88 _ = self;
91 @panic("Attempted to compile for object format that was disabled by build configuration");89 _ = pt;
9290 _ = nav;
93 return self.llvm_object.updateNav(pt, nav);91 unreachable; // we always use llvm
94}92}
9593
96pub fn updateExports(94pub fn updateExports(
...@@ -99,21 +97,21 @@ pub fn updateExports(...@@ -99,21 +97,21 @@ pub fn updateExports(
99 exported: Zcu.Exported,97 exported: Zcu.Exported,
100 export_indices: []const Zcu.Export.Index,98 export_indices: []const Zcu.Export.Index,
101) !void {99) !void {
102 if (build_options.skip_non_native and builtin.object_format != .xcoff)100 _ = self;
103 @panic("Attempted to compile for object format that was disabled by build configuration");101 _ = pt;
104102 _ = exported;
105 return self.llvm_object.updateExports(pt, exported, export_indices);103 _ = export_indices;
104 unreachable; // we always use llvm
106}105}
107106
108pub fn flush(self: *Xcoff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {107pub fn flush(self: *Xcoff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
109 return self.flushModule(arena, tid, prog_node);108 return self.flushZcu(arena, tid, prog_node);
110}109}
111110
112pub fn flushModule(self: *Xcoff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {111pub fn flushZcu(self: *Xcoff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
113 if (build_options.skip_non_native and builtin.object_format != .xcoff)112 _ = self;
114 @panic("Attempted to compile for object format that was disabled by build configuration");113 _ = arena;
115
116 _ = tid;114 _ = tid;
117115 _ = prog_node;
118 try self.base.emitLlvmObject(arena, self.llvm_object, prog_node);116 unreachable; // we always use llvm
119}117}
src/target.zig+1-1
...@@ -739,7 +739,7 @@ pub fn functionPointerMask(target: std.Target) ?u64 {...@@ -739,7 +739,7 @@ pub fn functionPointerMask(target: std.Target) ?u64 {
739739
740pub fn supportsTailCall(target: std.Target, backend: std.builtin.CompilerBackend) bool {740pub fn supportsTailCall(target: std.Target, backend: std.builtin.CompilerBackend) bool {
741 switch (backend) {741 switch (backend) {
742 .stage1, .stage2_llvm => return @import("codegen/llvm.zig").supportsTailCall(target),742 .stage2_llvm => return @import("codegen/llvm.zig").supportsTailCall(target),
743 .stage2_c => return true,743 .stage2_c => return true,
744 else => return false,744 else => return false,
745 }745 }