Skip to content

Commit 456f65e

Browse files
committed
rustc_target: Some more tests and fixes for linker arguments
1 parent 46aba88 commit 456f65e

11 files changed

+132
-44
lines changed

Diff for: compiler/rustc_target/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
//! LLVM.
99
1010
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
11+
#![feature(assert_matches)]
1112
#![feature(associated_type_bounds)]
1213
#![feature(exhaustive_patterns)]
1314
#![feature(let_else)]

Diff for: compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ use crate::spec::{FramePointer, LinkerFlavor, Target};
33
pub fn target() -> Target {
44
let mut base = super::windows_gnu_base::opts();
55
base.cpu = "pentium4".into();
6-
base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pe"]);
76
base.max_atomic_width = Some(64);
87
base.frame_pointer = FramePointer::Always; // Required for backtraces
98
base.linker = Some("i686-w64-mingw32-gcc".into());
109

1110
// Mark all dynamic libraries and executables as compatible with the larger 4GiB address
1211
// space available to x86 Windows binaries on x86_64.
12+
base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pe", "--large-address-aware"]);
1313
base.add_pre_link_args(LinkerFlavor::Gcc, &["-Wl,--large-address-aware"]);
1414

1515
Target {

Diff for: compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ use crate::spec::{FramePointer, LinkerFlavor, Target};
33
pub fn target() -> Target {
44
let mut base = super::windows_uwp_gnu_base::opts();
55
base.cpu = "pentium4".into();
6-
base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pe"]);
76
base.max_atomic_width = Some(64);
87
base.frame_pointer = FramePointer::Always; // Required for backtraces
98

109
// Mark all dynamic libraries and executables as compatible with the larger 4GiB address
1110
// space available to x86 Windows binaries on x86_64.
11+
base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pe", "--large-address-aware"]);
1212
base.add_pre_link_args(LinkerFlavor::Gcc, &["-Wl,--large-address-aware"]);
1313

1414
Target {

Diff for: compiler/rustc_target/src/spec/tests/tests_impl.rs

+84-13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::super::*;
2+
use std::assert_matches::assert_matches;
23

34
// Test target self-consistency and JSON encoding/decoding roundtrip.
45
pub(super) fn test_target(target: Target) {
@@ -14,35 +15,105 @@ impl Target {
1415
assert_eq!(self.is_like_wasm, self.arch == "wasm32" || self.arch == "wasm64");
1516
assert!(self.is_like_windows || !self.is_like_msvc);
1617

17-
// Check that LLD with the given flavor is treated identically to the linker it emulates.
18-
// If your target really needs to deviate from the rules below, except it and document the
19-
// reasons.
20-
assert_eq!(
21-
self.linker_flavor == LinkerFlavor::Msvc
22-
|| self.linker_flavor == LinkerFlavor::Lld(LldFlavor::Link),
23-
self.lld_flavor == LldFlavor::Link,
24-
);
25-
assert_eq!(self.is_like_msvc, self.lld_flavor == LldFlavor::Link);
26-
for args in &[
18+
// Check that default linker flavor and lld flavor are compatible
19+
// with some other key properties.
20+
assert_eq!(self.is_like_osx, matches!(self.lld_flavor, LldFlavor::Ld64));
21+
assert_eq!(self.is_like_msvc, matches!(self.lld_flavor, LldFlavor::Link));
22+
assert_eq!(self.is_like_wasm, matches!(self.lld_flavor, LldFlavor::Wasm));
23+
assert_eq!(self.os == "l4re", matches!(self.linker_flavor, LinkerFlavor::L4Bender));
24+
assert_eq!(self.os == "emscripten", matches!(self.linker_flavor, LinkerFlavor::Em));
25+
assert_eq!(self.arch == "bpf", matches!(self.linker_flavor, LinkerFlavor::BpfLinker));
26+
assert_eq!(self.arch == "nvptx64", matches!(self.linker_flavor, LinkerFlavor::PtxLinker));
27+
28+
for args in [
2729
&self.pre_link_args,
2830
&self.late_link_args,
2931
&self.late_link_args_dynamic,
3032
&self.late_link_args_static,
3133
&self.post_link_args,
3234
] {
35+
for (&flavor, flavor_args) in args {
36+
assert!(!flavor_args.is_empty());
37+
// Check that flavors mentioned in link args are compatible with the default flavor.
38+
match (self.linker_flavor, self.lld_flavor) {
39+
(
40+
LinkerFlavor::Ld | LinkerFlavor::Lld(LldFlavor::Ld) | LinkerFlavor::Gcc,
41+
LldFlavor::Ld,
42+
) => {
43+
assert_matches!(
44+
flavor,
45+
LinkerFlavor::Ld | LinkerFlavor::Lld(LldFlavor::Ld) | LinkerFlavor::Gcc
46+
)
47+
}
48+
(LinkerFlavor::Gcc, LldFlavor::Ld64) => {
49+
assert_matches!(flavor, LinkerFlavor::Gcc)
50+
}
51+
(LinkerFlavor::Msvc | LinkerFlavor::Lld(LldFlavor::Link), LldFlavor::Link) => {
52+
assert_matches!(
53+
flavor,
54+
LinkerFlavor::Msvc | LinkerFlavor::Lld(LldFlavor::Link)
55+
)
56+
}
57+
(LinkerFlavor::Lld(LldFlavor::Wasm) | LinkerFlavor::Gcc, LldFlavor::Wasm) => {
58+
assert_matches!(
59+
flavor,
60+
LinkerFlavor::Lld(LldFlavor::Wasm) | LinkerFlavor::Gcc
61+
)
62+
}
63+
(LinkerFlavor::L4Bender, LldFlavor::Ld) => {
64+
assert_matches!(flavor, LinkerFlavor::L4Bender)
65+
}
66+
(LinkerFlavor::Em, LldFlavor::Wasm) => {
67+
assert_matches!(flavor, LinkerFlavor::Em)
68+
}
69+
(LinkerFlavor::BpfLinker, LldFlavor::Ld) => {
70+
assert_matches!(flavor, LinkerFlavor::BpfLinker)
71+
}
72+
(LinkerFlavor::PtxLinker, LldFlavor::Ld) => {
73+
assert_matches!(flavor, LinkerFlavor::PtxLinker)
74+
}
75+
flavors => unreachable!("unexpected flavor combination: {:?}", flavors),
76+
}
77+
78+
// Check that link args for cc and non-cc versions of flavors are consistent.
79+
let check_noncc = |noncc_flavor| {
80+
if let Some(noncc_args) = args.get(&noncc_flavor) {
81+
for arg in flavor_args {
82+
if let Some(suffix) = arg.strip_prefix("-Wl,") {
83+
assert!(noncc_args.iter().any(|a| a == suffix));
84+
}
85+
}
86+
}
87+
};
88+
match self.linker_flavor {
89+
LinkerFlavor::Gcc => match self.lld_flavor {
90+
LldFlavor::Ld => {
91+
check_noncc(LinkerFlavor::Ld);
92+
check_noncc(LinkerFlavor::Lld(LldFlavor::Ld));
93+
}
94+
LldFlavor::Wasm => check_noncc(LinkerFlavor::Lld(LldFlavor::Wasm)),
95+
LldFlavor::Ld64 | LldFlavor::Link => {}
96+
},
97+
_ => {}
98+
}
99+
}
100+
101+
// Check that link args for lld and non-lld versions of flavors are consistent.
102+
assert_eq!(args.get(&LinkerFlavor::Ld), args.get(&LinkerFlavor::Lld(LldFlavor::Ld)));
33103
assert_eq!(
34104
args.get(&LinkerFlavor::Msvc),
35105
args.get(&LinkerFlavor::Lld(LldFlavor::Link)),
36106
);
37-
if args.contains_key(&LinkerFlavor::Msvc) {
38-
assert_eq!(self.lld_flavor, LldFlavor::Link);
39-
}
40107
}
108+
41109
assert!(
42110
(self.pre_link_objects_fallback.is_empty()
43111
&& self.post_link_objects_fallback.is_empty())
44112
|| self.crt_objects_fallback.is_some()
45113
);
114+
115+
// If your target really needs to deviate from the rules below,
116+
// except it and document the reasons.
46117
// Keep the default "unknown" vendor instead.
47118
assert_ne!(self.vendor, "");
48119
if !self.can_use_os_unknown() {

Diff for: compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs

+10-11
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
use super::{cvs, wasm_base};
2-
use super::{LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
2+
use super::{LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
33

44
pub fn target() -> Target {
5-
let mut options = wasm_base::options();
6-
7-
// Rust really needs a way for users to specify exports and imports in
8-
// the source code. --export-dynamic isn't the right tool for this job,
9-
// however it does have the side effect of automatically exporting a lot
10-
// of symbols, which approximates what people want when compiling for
11-
// wasm32-unknown-unknown expect, so use it for now.
12-
options.add_pre_link_args(LinkerFlavor::Gcc, &["--export-dynamic"]);
13-
options.add_post_link_args(LinkerFlavor::Em, &["-sABORTING_MALLOC=0", "-Wl,--fatal-warnings"]);
5+
// Reset flags for non-Em flavors back to empty to satisfy sanity checking tests.
6+
let pre_link_args = LinkArgs::new();
7+
let post_link_args = TargetOptions::link_args(
8+
LinkerFlavor::Em,
9+
&["-sABORTING_MALLOC=0", "-Wl,--fatal-warnings"],
10+
);
1411

1512
let opts = TargetOptions {
1613
os: "emscripten".into(),
@@ -19,11 +16,13 @@ pub fn target() -> Target {
1916
// functionality, and a .wasm file.
2017
exe_suffix: ".js".into(),
2118
linker: None,
19+
pre_link_args,
20+
post_link_args,
2221
relocation_model: RelocModel::Pic,
2322
panic_strategy: PanicStrategy::Unwind,
2423
no_default_libraries: false,
2524
families: cvs!["unix", "wasm"],
26-
..options
25+
..wasm_base::options()
2726
};
2827
Target {
2928
llvm_target: "wasm32-unknown-emscripten".into(),

Diff for: compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -30,27 +30,30 @@ pub fn target() -> Target {
3030
options.default_adjusted_cabi = Some(Abi::Wasm);
3131

3232
options.add_pre_link_args(
33-
LinkerFlavor::Gcc,
33+
LinkerFlavor::Lld(LldFlavor::Wasm),
3434
&[
35-
// Make sure clang uses LLD as its linker and is configured appropriately
36-
// otherwise
37-
"--target=wasm32-unknown-unknown",
3835
// For now this target just never has an entry symbol no matter the output
3936
// type, so unconditionally pass this.
40-
"-Wl,--no-entry",
37+
"--no-entry",
4138
// Rust really needs a way for users to specify exports and imports in
4239
// the source code. --export-dynamic isn't the right tool for this job,
4340
// however it does have the side effect of automatically exporting a lot
4441
// of symbols, which approximates what people want when compiling for
4542
// wasm32-unknown-unknown expect, so use it for now.
43+
"--export-dynamic",
44+
],
45+
);
46+
options.add_pre_link_args(
47+
LinkerFlavor::Gcc,
48+
&[
49+
// Make sure clang uses LLD as its linker and is configured appropriately
50+
// otherwise
51+
"--target=wasm32-unknown-unknown",
52+
"-Wl,--no-entry",
4653
"-Wl,--export-dynamic",
4754
],
4855
);
4956

50-
// Add the flags to wasm-ld's args too.
51-
options
52-
.add_pre_link_args(LinkerFlavor::Lld(LldFlavor::Wasm), &["--no-entry", "--export-dynamic"]);
53-
5457
Target {
5558
llvm_target: "wasm32-unknown-unknown".into(),
5659
pointer_width: 32,

Diff for: compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,25 @@ pub fn target() -> Target {
1515
options.os = "unknown".into();
1616
options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm);
1717

18+
options.add_pre_link_args(
19+
LinkerFlavor::Lld(LldFlavor::Wasm),
20+
&[
21+
// For now this target just never has an entry symbol no matter the output
22+
// type, so unconditionally pass this.
23+
"--no-entry",
24+
"-mwasm64",
25+
],
26+
);
1827
options.add_pre_link_args(
1928
LinkerFlavor::Gcc,
2029
&[
2130
// Make sure clang uses LLD as its linker and is configured appropriately
2231
// otherwise
2332
"--target=wasm64-unknown-unknown",
24-
// For now this target just never has an entry symbol no matter the output
25-
// type, so unconditionally pass this.
2633
"-Wl,--no-entry",
2734
],
2835
);
2936

30-
options.add_pre_link_args(LinkerFlavor::Lld(LldFlavor::Wasm), &["--no-entry", "-mwasm64"]);
31-
3237
// Any engine that implements wasm64 will surely implement the rest of these
3338
// features since they were all merged into the official spec by the time
3439
// wasm64 was designed.

Diff for: compiler/rustc_target/src/spec/windows_gnu_base.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,23 @@ use crate::spec::crt_objects::{self, CrtObjectsFallback};
22
use crate::spec::{cvs, LinkerFlavor, TargetOptions};
33

44
pub fn opts() -> TargetOptions {
5-
let pre_link_args = TargetOptions::link_args(
5+
let mut pre_link_args = TargetOptions::link_args(
6+
LinkerFlavor::Ld,
7+
&[
8+
// Enable ASLR
9+
"--dynamicbase",
10+
// ASLR will rebase it anyway so leaving that option enabled only leads to confusion
11+
"--disable-auto-image-base",
12+
],
13+
);
14+
super::add_link_args(
15+
&mut pre_link_args,
616
LinkerFlavor::Gcc,
717
&[
818
// Tell GCC to avoid linker plugins, because we are not bundling
919
// them with Windows installer, and Rust does its own LTO anyways.
1020
"-fno-use-linker-plugin",
11-
// Enable ASLR
1221
"-Wl,--dynamicbase",
13-
// ASLR will rebase it anyway so leaving that option enabled only leads to confusion
1422
"-Wl,--disable-auto-image-base",
1523
],
1624
);

Diff for: compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub fn opts() -> TargetOptions {
1717
];
1818
let mut late_link_args = TargetOptions::link_args(LinkerFlavor::Ld, mingw_libs);
1919
super::add_link_args(&mut late_link_args, LinkerFlavor::Gcc, mingw_libs);
20+
// Reset the flags back to empty until the FIXME above is addressed.
2021
let late_link_args_dynamic = LinkArgs::new();
2122
let late_link_args_static = LinkArgs::new();
2223

Diff for: compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ pub fn target() -> Target {
44
let mut base = super::windows_gnu_base::opts();
55
base.cpu = "x86-64".into();
66
// Use high-entropy 64 bit address space for ASLR
7+
base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pep", "--high-entropy-va"]);
78
base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64", "-Wl,--high-entropy-va"]);
8-
base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pep"]);
99
base.max_atomic_width = Some(64);
1010
base.linker = Some("x86_64-w64-mingw32-gcc".into());
1111

Diff for: compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ pub fn target() -> Target {
44
let mut base = super::windows_uwp_gnu_base::opts();
55
base.cpu = "x86-64".into();
66
// Use high-entropy 64 bit address space for ASLR
7+
base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pep", "--high-entropy-va"]);
78
base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64", "-Wl,--high-entropy-va"]);
8-
base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pep"]);
99
base.max_atomic_width = Some(64);
1010

1111
Target {

0 commit comments

Comments
 (0)