Skip to content

Commit 5f5c5eb

Browse files
committed
[ld.lld] understand -r, --relocatable
clang and gcc accept `-r`, which is a `--relocatable` argument of ld.lld. This diff understands the flag and passes to the linker. Impact: this makes the Go's `cmd/link` test suite pass[*]. To reproduce, do in go/src directory (currently patched, hopefully not for long): ``` echo 'exec zig cc "$@"' > zig-cc; chmod a+x zig-cc CC="./zig-cc" ./run.bash -run cmd/link ``` [*]: at the moment it requires golang/go#52815 to pass
1 parent 50a5dde commit 5f5c5eb

File tree

9 files changed

+41
-7
lines changed

9 files changed

+41
-7
lines changed

src/Compilation.zig

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,7 @@ pub const InitOptions = struct {
732732
use_clang: ?bool = null,
733733
use_stage1: ?bool = null,
734734
single_threaded: ?bool = null,
735+
relocatable: bool = false,
735736
rdynamic: bool = false,
736737
strip: bool = false,
737738
function_sections: bool = false,
@@ -1615,6 +1616,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
16151616
.gc_sections = options.linker_gc_sections,
16161617
.eh_frame_hdr = link_eh_frame_hdr,
16171618
.emit_relocs = options.link_emit_relocs,
1619+
.relocatable = options.relocatable,
16181620
.rdynamic = options.rdynamic,
16191621
.soname = options.soname,
16201622
.version = options.version,
@@ -2255,7 +2257,7 @@ fn prepareWholeEmitSubPath(arena: Allocator, opt_emit: ?EmitLoc) error{OutOfMemo
22552257
/// to remind the programmer to update multiple related pieces of code that
22562258
/// are in different locations. Bump this number when adding or deleting
22572259
/// anything from the link cache manifest.
2258-
pub const link_hash_implementation_version = 2;
2260+
pub const link_hash_implementation_version = 3;
22592261

22602262
fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifest) !void {
22612263
const gpa = comp.gpa;
@@ -2265,7 +2267,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
22652267
defer arena_allocator.deinit();
22662268
const arena = arena_allocator.allocator();
22672269

2268-
comptime assert(link_hash_implementation_version == 2);
2270+
comptime assert(link_hash_implementation_version == 3);
22692271

22702272
if (comp.bin_file.options.module) |mod| {
22712273
const main_zig_file = try mod.main_pkg.root_src_directory.join(arena, &[_][]const u8{
@@ -2324,6 +2326,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
23242326
man.hash.addOptional(comp.bin_file.options.gc_sections);
23252327
man.hash.add(comp.bin_file.options.eh_frame_hdr);
23262328
man.hash.add(comp.bin_file.options.emit_relocs);
2329+
man.hash.add(comp.bin_file.options.relocatable);
23272330
man.hash.add(comp.bin_file.options.rdynamic);
23282331
man.hash.addListOfBytes(comp.bin_file.options.lib_dirs);
23292332
man.hash.addListOfBytes(comp.bin_file.options.rpath_list);

src/clang_options_data.zig

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4623,7 +4623,14 @@ flagpd1("print-stats"),
46234623
flagpd1("private_bundle"),
46244624
flagpd1("pthread"),
46254625
flagpd1("pthreads"),
4626-
flagpd1("r"),
4626+
.{
4627+
.name = "r",
4628+
.syntax = .flag,
4629+
.zig_equivalent = .r,
4630+
.pd1 = true,
4631+
.pd2 = false,
4632+
.psl = false,
4633+
},
46274634
.{
46284635
.name = "rdynamic",
46294636
.syntax = .flag,

src/link.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ pub const Options = struct {
107107
function_sections: bool,
108108
eh_frame_hdr: bool,
109109
emit_relocs: bool,
110+
relocatable: bool,
110111
rdynamic: bool,
111112
z_nodelete: bool,
112113
z_notext: bool,

src/link/Coff.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !
969969
man = comp.cache_parent.obtain();
970970
self.base.releaseLock();
971971

972-
comptime assert(Compilation.link_hash_implementation_version == 2);
972+
comptime assert(Compilation.link_hash_implementation_version == 3);
973973

974974
for (self.base.options.objects) |obj| {
975975
_ = try man.addFile(obj.path, null);

src/link/Elf.zig

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1294,7 +1294,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
12941294
// We are about to obtain this lock, so here we give other processes a chance first.
12951295
self.base.releaseLock();
12961296

1297-
comptime assert(Compilation.link_hash_implementation_version == 2);
1297+
comptime assert(Compilation.link_hash_implementation_version == 3);
12981298

12991299
try man.addOptionalFile(self.base.options.linker_script);
13001300
try man.addOptionalFile(self.base.options.version_script);
@@ -1316,6 +1316,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
13161316
man.hash.add(gc_sections);
13171317
man.hash.add(self.base.options.eh_frame_hdr);
13181318
man.hash.add(self.base.options.emit_relocs);
1319+
man.hash.add(self.base.options.relocatable);
13191320
man.hash.add(self.base.options.rdynamic);
13201321
man.hash.addListOfBytes(self.base.options.lib_dirs);
13211322
man.hash.addListOfBytes(self.base.options.rpath_list);
@@ -1472,6 +1473,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
14721473
try argv.append("--emit-relocs");
14731474
}
14741475

1476+
if (self.base.options.relocatable) {
1477+
try argv.append("--relocatable");
1478+
}
1479+
14751480
if (self.base.options.rdynamic) {
14761481
try argv.append("--export-dynamic");
14771482
}

src/link/MachO.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
527527
// We are about to obtain this lock, so here we give other processes a chance first.
528528
self.base.releaseLock();
529529

530-
comptime assert(Compilation.link_hash_implementation_version == 2);
530+
comptime assert(Compilation.link_hash_implementation_version == 3);
531531

532532
for (self.base.options.objects) |obj| {
533533
_ = try man.addFile(obj.path, null);

src/link/Wasm.zig

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2274,7 +2274,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
22742274
// We are about to obtain this lock, so here we give other processes a chance first.
22752275
self.base.releaseLock();
22762276

2277-
comptime assert(Compilation.link_hash_implementation_version == 2);
2277+
comptime assert(Compilation.link_hash_implementation_version == 3);
22782278

22792279
for (self.base.options.objects) |obj| {
22802280
_ = try man.addFile(obj.path, null);
@@ -2290,6 +2290,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
22902290
man.hash.add(self.base.options.import_memory);
22912291
man.hash.add(self.base.options.import_table);
22922292
man.hash.add(self.base.options.export_table);
2293+
man.hash.add(self.base.options.relocatable);
22932294
man.hash.addOptional(self.base.options.initial_memory);
22942295
man.hash.addOptional(self.base.options.max_memory);
22952296
man.hash.add(self.base.options.shared_memory);
@@ -2388,6 +2389,10 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
23882389
try argv.append("-s");
23892390
}
23902391

2392+
if (self.base.options.relocatable) {
2393+
try argv.append("--relocatable");
2394+
}
2395+
23912396
if (self.base.options.initial_memory) |initial_memory| {
23922397
const arg = try std.fmt.allocPrint(arena, "--initial-memory={d}", .{initial_memory});
23932398
try argv.append(arg);

src/main.zig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ const usage_build_generic =
417417
\\ -fno-LLD Prevent using LLD as the linker
418418
\\ -fcompiler-rt Always include compiler-rt symbols in output
419419
\\ -fno-compiler-rt Prevent including compiler-rt symbols in output
420+
\\ -r Produce a relocatable object as output. This is also known as partial linking
420421
\\ -rdynamic Add all symbols to the dynamic symbol table
421422
\\ -rpath [path] Add directory to the runtime library search path
422423
\\ -feach-lib-rpath Ensure adding rpath for each used dynamic library
@@ -633,6 +634,7 @@ fn buildOutputType(
633634
var want_valgrind: ?bool = null;
634635
var want_tsan: ?bool = null;
635636
var want_compiler_rt: ?bool = null;
637+
var r: bool = false;
636638
var rdynamic: bool = false;
637639
var linker_script: ?[]const u8 = null;
638640
var version_script: ?[]const u8 = null;
@@ -1099,6 +1101,8 @@ fn buildOutputType(
10991101
use_stage1 = true;
11001102
} else if (mem.eql(u8, arg, "-fno-stage1")) {
11011103
use_stage1 = false;
1104+
} else if (mem.eql(u8, arg, "-r")) {
1105+
r = true;
11021106
} else if (mem.eql(u8, arg, "-rdynamic")) {
11031107
rdynamic = true;
11041108
} else if (mem.eql(u8, arg, "-fsoname")) {
@@ -1408,6 +1412,7 @@ fn buildOutputType(
14081412
link_mode = .Dynamic;
14091413
is_shared_lib = true;
14101414
},
1415+
.r => r = true,
14111416
.rdynamic => rdynamic = true,
14121417
.wl => {
14131418
var split_it = mem.split(u8, it.only_arg, ",");
@@ -1602,6 +1607,8 @@ fn buildOutputType(
16021607
fatal("expected linker arg after '{s}'", .{arg});
16031608
}
16041609
target_dynamic_linker = linker_args.items[i];
1610+
} else if (mem.eql(u8, arg, "-r") or mem.eql(u8, arg, "--relocatable")) {
1611+
r = true;
16051612
} else if (mem.eql(u8, arg, "-E") or
16061613
mem.eql(u8, arg, "--export-dynamic") or
16071614
mem.eql(u8, arg, "-export-dynamic"))
@@ -2671,6 +2678,7 @@ fn buildOutputType(
26712678
.use_clang = use_clang,
26722679
.use_stage1 = use_stage1,
26732680
.hash_style = hash_style,
2681+
.relocatable = r,
26742682
.rdynamic = rdynamic,
26752683
.linker_script = linker_script,
26762684
.version_script = version_script,
@@ -4401,6 +4409,7 @@ pub const ClangArgIterator = struct {
44014409
nostdlib,
44024410
nostdlib_cpp,
44034411
shared,
4412+
r,
44044413
rdynamic,
44054414
wl,
44064415
preprocess_only,

tools/update_clang_options.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ const known_options = [_]KnownOpt{
142142
.name = "shared",
143143
.ident = "shared",
144144
},
145+
.{
146+
.name = "r",
147+
.ident = "r",
148+
},
145149
.{
146150
.name = "rdynamic",
147151
.ident = "rdynamic",

0 commit comments

Comments
 (0)