Skip to content

Commit fc55c1b

Browse files
authored
Merge pull request #23698 from alexrp/goff-xcoff-stubs
`link`: Stub out GOFF/XCOFF linker code based on LLVM
2 parents 4102982 + 2d44bc5 commit fc55c1b

File tree

7 files changed

+267
-9
lines changed

7 files changed

+267
-9
lines changed

CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,7 @@ set(ZIG_STAGE2_SOURCES
612612
src/link/Elf/relocatable.zig
613613
src/link/Elf/relocation.zig
614614
src/link/Elf/synthetic_sections.zig
615+
src/link/Goff.zig
615616
src/link/LdScript.zig
616617
src/link/MachO.zig
617618
src/link/MachO/Archive.zig
@@ -652,6 +653,7 @@ set(ZIG_STAGE2_SOURCES
652653
src/link/Wasm/Archive.zig
653654
src/link/Wasm/Flush.zig
654655
src/link/Wasm/Object.zig
656+
src/link/Xcoff.zig
655657
src/link/aarch64.zig
656658
src/link/riscv.zig
657659
src/link/table_section.zig

src/codegen/llvm.zig

+1-1
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ pub fn dataLayout(target: std.Target) []const u8 {
398398
.sparc => "E-m:e-p:32:32-i64:64-i128:128-f128:64-n32-S64",
399399
.sparc64 => "E-m:e-i64:64-i128:128-n32:64-S128",
400400
.s390x => if (target.os.tag == .zos)
401-
"E-m:l-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64"
401+
"E-m:l-p1:32:32-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64"
402402
else
403403
"E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64",
404404
.x86 => if (target.os.tag == .windows) switch (target.abi) {

src/dev.zig

+4
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ pub const Env = enum {
8282
.spirv_linker,
8383
.plan9_linker,
8484
.nvptx_linker,
85+
.goff_linker,
86+
.xcoff_linker,
8587
=> true,
8688
.cc_command,
8789
.translate_c_command,
@@ -228,6 +230,8 @@ pub const Feature = enum {
228230
spirv_linker,
229231
plan9_linker,
230232
nvptx_linker,
233+
goff_linker,
234+
xcoff_linker,
231235
};
232236

233237
/// Makes the code following the call to this function unreachable if `feature` is disabled.

src/link.zig

+18-6
Original file line numberDiff line numberDiff line change
@@ -556,9 +556,9 @@ pub const File = struct {
556556
const comp = base.comp;
557557
const gpa = comp.gpa;
558558
switch (base.tag) {
559-
.coff, .elf, .macho, .plan9, .wasm => {
559+
.coff, .elf, .macho, .plan9, .wasm, .goff, .xcoff => {
560560
if (base.file != null) return;
561-
dev.checkAny(&.{ .coff_linker, .elf_linker, .macho_linker, .plan9_linker, .wasm_linker });
561+
dev.checkAny(&.{ .coff_linker, .elf_linker, .macho_linker, .plan9_linker, .wasm_linker, .goff_linker, .xcoff_linker });
562562
const emit = base.emit;
563563
if (base.child_pid) |pid| {
564564
if (builtin.os.tag == .windows) {
@@ -650,8 +650,8 @@ pub const File = struct {
650650
}
651651
}
652652
},
653-
.coff, .macho, .plan9, .wasm => if (base.file) |f| {
654-
dev.checkAny(&.{ .coff_linker, .macho_linker, .plan9_linker, .wasm_linker });
653+
.coff, .macho, .plan9, .wasm, .goff, .xcoff => if (base.file) |f| {
654+
dev.checkAny(&.{ .coff_linker, .macho_linker, .plan9_linker, .wasm_linker, .goff_linker, .xcoff_linker });
655655
if (base.zcu_object_sub_path != null) {
656656
// The file we have open is not the final file that we want to
657657
// make executable, so we don't have to close it.
@@ -767,6 +767,7 @@ pub const File = struct {
767767

768768
switch (base.tag) {
769769
.spirv, .nvptx => {},
770+
.goff, .xcoff => {},
770771
inline else => |tag| {
771772
dev.check(tag.devFeature());
772773
return @as(*tag.Type(), @fieldParentPtr("base", base)).updateLineNumber(pt, ti_id);
@@ -902,6 +903,7 @@ pub const File = struct {
902903
.spirv => unreachable,
903904
.nvptx => unreachable,
904905
.wasm => unreachable,
906+
.goff, .xcoff => unreachable,
905907
inline else => |tag| {
906908
dev.check(tag.devFeature());
907909
return @as(*tag.Type(), @fieldParentPtr("base", base)).getNavVAddr(pt, nav_index, reloc_info);
@@ -921,6 +923,7 @@ pub const File = struct {
921923
.spirv => unreachable,
922924
.nvptx => unreachable,
923925
.wasm => unreachable,
926+
.goff, .xcoff => unreachable,
924927
inline else => |tag| {
925928
dev.check(tag.devFeature());
926929
return @as(*tag.Type(), @fieldParentPtr("base", base)).lowerUav(pt, decl_val, decl_align, src_loc);
@@ -934,6 +937,7 @@ pub const File = struct {
934937
.spirv => unreachable,
935938
.nvptx => unreachable,
936939
.wasm => unreachable,
940+
.goff, .xcoff => unreachable,
937941
inline else => |tag| {
938942
dev.check(tag.devFeature());
939943
return @as(*tag.Type(), @fieldParentPtr("base", base)).getUavVAddr(decl_val, reloc_info);
@@ -950,6 +954,8 @@ pub const File = struct {
950954
.plan9,
951955
.spirv,
952956
.nvptx,
957+
.goff,
958+
.xcoff,
953959
=> {},
954960

955961
inline else => |tag| {
@@ -1246,6 +1252,8 @@ pub const File = struct {
12461252
spirv,
12471253
plan9,
12481254
nvptx,
1255+
goff,
1256+
xcoff,
12491257

12501258
pub fn Type(comptime tag: Tag) type {
12511259
return switch (tag) {
@@ -1257,6 +1265,8 @@ pub const File = struct {
12571265
.spirv => SpirV,
12581266
.plan9 => Plan9,
12591267
.nvptx => NvPtx,
1268+
.goff => Goff,
1269+
.xcoff => Xcoff,
12601270
};
12611271
}
12621272

@@ -1270,8 +1280,8 @@ pub const File = struct {
12701280
.c => .c,
12711281
.spirv => .spirv,
12721282
.nvptx => .nvptx,
1273-
.goff => @panic("TODO implement goff object format"),
1274-
.xcoff => @panic("TODO implement xcoff object format"),
1283+
.goff => .goff,
1284+
.xcoff => .xcoff,
12751285
.hex => @panic("TODO implement hex object format"),
12761286
.raw => @panic("TODO implement raw object format"),
12771287
};
@@ -1377,6 +1387,8 @@ pub const File = struct {
13771387
pub const SpirV = @import("link/SpirV.zig");
13781388
pub const Wasm = @import("link/Wasm.zig");
13791389
pub const NvPtx = @import("link/NvPtx.zig");
1390+
pub const Goff = @import("link/Goff.zig");
1391+
pub const Xcoff = @import("link/Xcoff.zig");
13801392
pub const Dwarf = @import("link/Dwarf.zig");
13811393
};
13821394

src/link/Goff.zig

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
//! Stub linker support for GOFF based on LLVM.
2+
3+
const Goff = @This();
4+
5+
const std = @import("std");
6+
const builtin = @import("builtin");
7+
8+
const Allocator = std.mem.Allocator;
9+
const assert = std.debug.assert;
10+
const log = std.log.scoped(.link);
11+
const Path = std.Build.Cache.Path;
12+
13+
const Zcu = @import("../Zcu.zig");
14+
const InternPool = @import("../InternPool.zig");
15+
const Compilation = @import("../Compilation.zig");
16+
const link = @import("../link.zig");
17+
const trace = @import("../tracy.zig").trace;
18+
const build_options = @import("build_options");
19+
const Air = @import("../Air.zig");
20+
const Liveness = @import("../Liveness.zig");
21+
const LlvmObject = @import("../codegen/llvm.zig").Object;
22+
23+
base: link.File,
24+
llvm_object: LlvmObject.Ptr,
25+
26+
pub fn createEmpty(
27+
arena: Allocator,
28+
comp: *Compilation,
29+
emit: Path,
30+
options: link.File.OpenOptions,
31+
) !*Goff {
32+
const target = comp.root_mod.resolved_target.result;
33+
const use_lld = build_options.have_llvm and comp.config.use_lld;
34+
const use_llvm = comp.config.use_llvm;
35+
36+
assert(use_llvm); // Caught by Compilation.Config.resolve.
37+
assert(!use_lld); // Caught by Compilation.Config.resolve.
38+
assert(target.os.tag == .zos); // Caught by Compilation.Config.resolve.
39+
40+
const llvm_object = try LlvmObject.create(arena, comp);
41+
const goff = try arena.create(Goff);
42+
goff.* = .{
43+
.base = .{
44+
.tag = .goff,
45+
.comp = comp,
46+
.emit = emit,
47+
.zcu_object_sub_path = emit.sub_path,
48+
.gc_sections = options.gc_sections orelse false,
49+
.print_gc_sections = options.print_gc_sections,
50+
.stack_size = options.stack_size orelse 0,
51+
.allow_shlib_undefined = options.allow_shlib_undefined orelse false,
52+
.file = null,
53+
.disable_lld_caching = options.disable_lld_caching,
54+
.build_id = options.build_id,
55+
},
56+
.llvm_object = llvm_object,
57+
};
58+
59+
return goff;
60+
}
61+
62+
pub fn open(
63+
arena: Allocator,
64+
comp: *Compilation,
65+
emit: Path,
66+
options: link.File.OpenOptions,
67+
) !*Goff {
68+
const target = comp.root_mod.resolved_target.result;
69+
assert(target.ofmt == .goff);
70+
return createEmpty(arena, comp, emit, options);
71+
}
72+
73+
pub fn deinit(self: *Goff) void {
74+
self.llvm_object.deinit();
75+
}
76+
77+
pub fn updateFunc(
78+
self: *Goff,
79+
pt: Zcu.PerThread,
80+
func_index: InternPool.Index,
81+
air: Air,
82+
liveness: Liveness,
83+
) link.File.UpdateNavError!void {
84+
if (build_options.skip_non_native and builtin.object_format != .goff)
85+
@panic("Attempted to compile for object format that was disabled by build configuration");
86+
87+
try self.llvm_object.updateFunc(pt, func_index, air, liveness);
88+
}
89+
90+
pub fn updateNav(self: *Goff, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.File.UpdateNavError!void {
91+
if (build_options.skip_non_native and builtin.object_format != .goff)
92+
@panic("Attempted to compile for object format that was disabled by build configuration");
93+
94+
return self.llvm_object.updateNav(pt, nav);
95+
}
96+
97+
pub fn updateExports(
98+
self: *Goff,
99+
pt: Zcu.PerThread,
100+
exported: Zcu.Exported,
101+
export_indices: []const Zcu.Export.Index,
102+
) !void {
103+
if (build_options.skip_non_native and builtin.object_format != .goff)
104+
@panic("Attempted to compile for object format that was disabled by build configuration");
105+
106+
return self.llvm_object.updateExports(pt, exported, export_indices);
107+
}
108+
109+
pub fn flush(self: *Goff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
110+
return self.flushModule(arena, tid, prog_node);
111+
}
112+
113+
pub fn flushModule(self: *Goff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
114+
if (build_options.skip_non_native and builtin.object_format != .goff)
115+
@panic("Attempted to compile for object format that was disabled by build configuration");
116+
117+
_ = tid;
118+
119+
try self.base.emitLlvmObject(arena, self.llvm_object, prog_node);
120+
}

src/link/Xcoff.zig

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
//! Stub linker support for GOFF based on LLVM.
2+
3+
const Xcoff = @This();
4+
5+
const std = @import("std");
6+
const builtin = @import("builtin");
7+
8+
const Allocator = std.mem.Allocator;
9+
const assert = std.debug.assert;
10+
const log = std.log.scoped(.link);
11+
const Path = std.Build.Cache.Path;
12+
13+
const Zcu = @import("../Zcu.zig");
14+
const InternPool = @import("../InternPool.zig");
15+
const Compilation = @import("../Compilation.zig");
16+
const link = @import("../link.zig");
17+
const trace = @import("../tracy.zig").trace;
18+
const build_options = @import("build_options");
19+
const Air = @import("../Air.zig");
20+
const Liveness = @import("../Liveness.zig");
21+
const LlvmObject = @import("../codegen/llvm.zig").Object;
22+
23+
base: link.File,
24+
llvm_object: LlvmObject.Ptr,
25+
26+
pub fn createEmpty(
27+
arena: Allocator,
28+
comp: *Compilation,
29+
emit: Path,
30+
options: link.File.OpenOptions,
31+
) !*Xcoff {
32+
const target = comp.root_mod.resolved_target.result;
33+
const use_lld = build_options.have_llvm and comp.config.use_lld;
34+
const use_llvm = comp.config.use_llvm;
35+
36+
assert(use_llvm); // Caught by Compilation.Config.resolve.
37+
assert(!use_lld); // Caught by Compilation.Config.resolve.
38+
assert(target.os.tag == .aix); // Caught by Compilation.Config.resolve.
39+
40+
const llvm_object = try LlvmObject.create(arena, comp);
41+
const xcoff = try arena.create(Xcoff);
42+
xcoff.* = .{
43+
.base = .{
44+
.tag = .xcoff,
45+
.comp = comp,
46+
.emit = emit,
47+
.zcu_object_sub_path = emit.sub_path,
48+
.gc_sections = options.gc_sections orelse false,
49+
.print_gc_sections = options.print_gc_sections,
50+
.stack_size = options.stack_size orelse 0,
51+
.allow_shlib_undefined = options.allow_shlib_undefined orelse false,
52+
.file = null,
53+
.disable_lld_caching = options.disable_lld_caching,
54+
.build_id = options.build_id,
55+
},
56+
.llvm_object = llvm_object,
57+
};
58+
59+
return xcoff;
60+
}
61+
62+
pub fn open(
63+
arena: Allocator,
64+
comp: *Compilation,
65+
emit: Path,
66+
options: link.File.OpenOptions,
67+
) !*Xcoff {
68+
const target = comp.root_mod.resolved_target.result;
69+
assert(target.ofmt == .xcoff);
70+
return createEmpty(arena, comp, emit, options);
71+
}
72+
73+
pub fn deinit(self: *Xcoff) void {
74+
self.llvm_object.deinit();
75+
}
76+
77+
pub fn updateFunc(
78+
self: *Xcoff,
79+
pt: Zcu.PerThread,
80+
func_index: InternPool.Index,
81+
air: Air,
82+
liveness: Liveness,
83+
) link.File.UpdateNavError!void {
84+
if (build_options.skip_non_native and builtin.object_format != .xcoff)
85+
@panic("Attempted to compile for object format that was disabled by build configuration");
86+
87+
try self.llvm_object.updateFunc(pt, func_index, air, liveness);
88+
}
89+
90+
pub fn updateNav(self: *Xcoff, pt: Zcu.PerThread, nav: InternPool.Nav.Index) link.File.UpdateNavError!void {
91+
if (build_options.skip_non_native and builtin.object_format != .xcoff)
92+
@panic("Attempted to compile for object format that was disabled by build configuration");
93+
94+
return self.llvm_object.updateNav(pt, nav);
95+
}
96+
97+
pub fn updateExports(
98+
self: *Xcoff,
99+
pt: Zcu.PerThread,
100+
exported: Zcu.Exported,
101+
export_indices: []const Zcu.Export.Index,
102+
) !void {
103+
if (build_options.skip_non_native and builtin.object_format != .xcoff)
104+
@panic("Attempted to compile for object format that was disabled by build configuration");
105+
106+
return self.llvm_object.updateExports(pt, exported, export_indices);
107+
}
108+
109+
pub fn flush(self: *Xcoff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
110+
return self.flushModule(arena, tid, prog_node);
111+
}
112+
113+
pub fn flushModule(self: *Xcoff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) link.File.FlushError!void {
114+
if (build_options.skip_non_native and builtin.object_format != .xcoff)
115+
@panic("Attempted to compile for object format that was disabled by build configuration");
116+
117+
_ = tid;
118+
119+
try self.base.emitLlvmObject(arena, self.llvm_object, prog_node);
120+
}

0 commit comments

Comments
 (0)