Skip to content

Commit 72868e0

Browse files
committedJun 11, 2021
Auto merge of #85961 - 1000teslas:issue-71519-fix, r=petrochenkov
MVP for using rust-lld as part of cc Will fix #71519. I need to figure out how to write a test showing that lld is used instead of whatever linker cc normally uses. When I manually run rustc using `echo 'fn main() {}' | RUSTC_LOG=rustc_codegen_ssa::back::link=debug ./rustc -Clinker-flavor=gcc-lld --crate-type bin -Clink-arg=-Wl,-v` (thanks to bjorn3 on Zulip), I can see that lld is used, but I'm not sure how to inspect that output in a test.
2 parents 46ad16b + 2a76762 commit 72868e0

File tree

8 files changed

+82
-1
lines changed

8 files changed

+82
-1
lines changed
 

‎compiler/rustc_codegen_ssa/src/back/link.rs

+30-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_fs_util::fix_windows_verbatim_for_gcc;
55
use rustc_hir::def_id::CrateNum;
66
use rustc_middle::middle::cstore::{DllImport, LibSource};
77
use rustc_middle::middle::dependency_format::Linkage;
8-
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, Strip};
8+
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
99
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest};
1010
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
1111
use rustc_session::search_paths::PathKind;
@@ -1927,6 +1927,8 @@ fn add_order_independent_options(
19271927
out_filename: &Path,
19281928
tmpdir: &Path,
19291929
) {
1930+
add_gcc_ld_path(cmd, sess, flavor);
1931+
19301932
add_apple_sdk(cmd, sess, flavor);
19311933

19321934
add_link_script(cmd, sess, tmpdir, crate_type);
@@ -2528,3 +2530,30 @@ fn get_apple_sdk_root(sdk_name: &str) -> Result<String, String> {
25282530
Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e)),
25292531
}
25302532
}
2533+
2534+
fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
2535+
if let Some(ld_impl) = sess.opts.debugging_opts.gcc_ld {
2536+
if let LinkerFlavor::Gcc = flavor {
2537+
match ld_impl {
2538+
LdImpl::Lld => {
2539+
let tools_path =
2540+
sess.host_filesearch(PathKind::All).get_tools_search_paths(false);
2541+
let lld_path = tools_path
2542+
.into_iter()
2543+
.map(|p| p.join("gcc-ld"))
2544+
.find(|p| {
2545+
p.join(if sess.host.is_like_windows { "ld.exe" } else { "ld" }).exists()
2546+
})
2547+
.unwrap_or_else(|| sess.fatal("rust-lld (as ld) not found"));
2548+
cmd.cmd().arg({
2549+
let mut arg = OsString::from("-B");
2550+
arg.push(lld_path);
2551+
arg
2552+
});
2553+
}
2554+
}
2555+
} else {
2556+
sess.fatal("option `-Z gcc-ld` is used even though linker flavor is not gcc");
2557+
}
2558+
}
2559+
}

‎compiler/rustc_session/src/config.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2417,6 +2417,7 @@ impl PpMode {
24172417
/// we have an opt-in scheme here, so one is hopefully forced to think about
24182418
/// how the hash should be calculated when adding a new command-line argument.
24192419
crate mod dep_tracking {
2420+
use super::LdImpl;
24202421
use super::{
24212422
CFGuard, CrateType, DebugInfo, ErrorOutputType, InstrumentCoverage, LinkerPluginLto,
24222423
LtoCli, OptLevel, OutputTypes, Passes, SourceFileHashAlgorithm, SwitchWithOptPath,
@@ -2497,6 +2498,7 @@ crate mod dep_tracking {
24972498
SymbolManglingVersion,
24982499
SourceFileHashAlgorithm,
24992500
TrimmedDefPaths,
2501+
Option<LdImpl>,
25002502
);
25012503

25022504
impl<T1, T2> DepTrackingHash for (T1, T2)

‎compiler/rustc_session/src/options.rs

+16
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ mod desc {
370370
pub const parse_wasi_exec_model: &str = "either `command` or `reactor`";
371371
pub const parse_split_debuginfo: &str =
372372
"one of supported split-debuginfo modes (`off`, `packed`, or `unpacked`)";
373+
pub const parse_gcc_ld: &str = "one of: no value, `lld`";
373374
}
374375

375376
mod parse {
@@ -864,6 +865,15 @@ mod parse {
864865
}
865866
true
866867
}
868+
869+
crate fn parse_gcc_ld(slot: &mut Option<LdImpl>, v: Option<&str>) -> bool {
870+
match v {
871+
None => *slot = None,
872+
Some("lld") => *slot = Some(LdImpl::Lld),
873+
_ => return false,
874+
}
875+
true
876+
}
867877
}
868878

869879
options! {
@@ -1067,6 +1077,7 @@ options! {
10671077
"set the optimization fuel quota for a crate"),
10681078
function_sections: Option<bool> = (None, parse_opt_bool, [TRACKED],
10691079
"whether each function should go in its own section"),
1080+
gcc_ld: Option<LdImpl> = (None, parse_gcc_ld, [TRACKED], "implementation of ld used by cc"),
10701081
graphviz_dark_mode: bool = (false, parse_bool, [UNTRACKED],
10711082
"use dark-themed colors in graphviz output (default: no)"),
10721083
graphviz_font: String = ("Courier, monospace".to_string(), parse_string, [UNTRACKED],
@@ -1321,3 +1332,8 @@ pub enum WasiExecModel {
13211332
Command,
13221333
Reactor,
13231334
}
1335+
1336+
#[derive(Clone, Copy, Hash)]
1337+
pub enum LdImpl {
1338+
Lld,
1339+
}

‎src/bootstrap/compile.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1108,6 +1108,13 @@ impl Step for Assemble {
11081108
let src_exe = exe("lld", target_compiler.host);
11091109
let dst_exe = exe("rust-lld", target_compiler.host);
11101110
builder.copy(&lld_install.join("bin").join(&src_exe), &libdir_bin.join(&dst_exe));
1111+
// for `-Z gcc-ld=lld`
1112+
let gcc_ld_dir = libdir_bin.join("gcc-ld");
1113+
t!(fs::create_dir(&gcc_ld_dir));
1114+
builder.copy(
1115+
&lld_install.join("bin").join(&src_exe),
1116+
&gcc_ld_dir.join(exe("ld", target_compiler.host)),
1117+
);
11111118
}
11121119

11131120
// Similarly, copy `llvm-dwp` into libdir for Split DWARF. Only copy it when the LLVM

‎src/bootstrap/dist.rs

+4
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,10 @@ impl Step for Rustc {
402402
if builder.config.lld_enabled {
403403
let exe = exe("rust-lld", compiler.host);
404404
builder.copy(&src_dir.join(&exe), &dst_dir.join(&exe));
405+
// for `-Z gcc-ld=lld`
406+
let gcc_lld_dir = dst_dir.join("gcc-ld");
407+
t!(fs::create_dir(&gcc_lld_dir));
408+
builder.copy(&src_dir.join(&exe), &gcc_lld_dir.join(&exe));
405409
}
406410

407411
// Copy over llvm-dwp if it's there
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
-include ../../run-make-fulldeps/tools.mk
2+
3+
# needs-rust-lld
4+
all:
5+
RUSTC_LOG=rustc_codegen_ssa::back::link=info $(RUSTC) -Z gcc-ld=lld -C link-args=-Wl,-v main.rs 2> $(TMPDIR)/output.txt
6+
$(CGREP) -e "^LLD [0-9]+\.[0-9]+\.[0-9]+" < $(TMPDIR)/output.txt

‎src/test/run-make/issue-71519/main.rs

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// test linking using cc with rust-lld injected into search path as ld
2+
// see rust-lang/rust#71519 for more info
3+
4+
fn main() {}

‎src/tools/compiletest/src/header.rs

+13
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,15 @@ impl EarlyProps {
5050
let has_msan = util::MSAN_SUPPORTED_TARGETS.contains(&&*config.target);
5151
let has_tsan = util::TSAN_SUPPORTED_TARGETS.contains(&&*config.target);
5252
let has_hwasan = util::HWASAN_SUPPORTED_TARGETS.contains(&&*config.target);
53+
// for `-Z gcc-ld=lld`
54+
let has_rust_lld = config
55+
.compile_lib_path
56+
.join("rustlib")
57+
.join(&config.target)
58+
.join("bin")
59+
.join("gcc-ld")
60+
.join(if config.host.contains("windows") { "ld.exe" } else { "ld" })
61+
.exists();
5362

5463
iter_header(testfile, None, rdr, &mut |ln| {
5564
// we should check if any only-<platform> exists and if it exists
@@ -136,6 +145,10 @@ impl EarlyProps {
136145
if config.debugger == Some(Debugger::Lldb) && ignore_lldb(config, ln) {
137146
props.ignore = true;
138147
}
148+
149+
if !has_rust_lld && config.parse_name_directive(ln, "needs-rust-lld") {
150+
props.ignore = true;
151+
}
139152
}
140153

141154
if let Some(s) = config.parse_aux_build(ln) {

0 commit comments

Comments
 (0)
Please sign in to comment.