Skip to content

Commit cf0fa76

Browse files
committed
Auto merge of rust-lang#101988 - petrochenkov:flavor2, r=lqd
rustc_target: Refactor internal linker flavors In accordance with the design from rust-lang#96827 (comment) `lld_flavor` and `linker_is_gnu` fields are removed from internal target specs, but still parsed from JSON specs using compatibility layer introduced in rust-lang#100552. r? `@lqd`
2 parents 233384f + 572b6a9 commit cf0fa76

File tree

104 files changed

+569
-438
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

104 files changed

+569
-438
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

+45-30
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ use rustc_session::{filesearch, Session};
2323
use rustc_span::symbol::Symbol;
2424
use rustc_span::DebuggerVisualizerFile;
2525
use rustc_target::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault};
26-
use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo};
27-
use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target};
26+
use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy};
27+
use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, Target};
2828

2929
use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
3030
use super::command::Command;
@@ -748,8 +748,7 @@ fn link_natively<'a>(
748748
// then it should not default to linking executables as pie. Different
749749
// versions of gcc seem to use different quotes in the error message so
750750
// don't check for them.
751-
if sess.target.linker_is_gnu
752-
&& flavor != LinkerFlavor::Ld
751+
if matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _))
753752
&& unknown_arg_regex.is_match(&out)
754753
&& out.contains("-no-pie")
755754
&& cmd.get_args().iter().any(|e| e.to_string_lossy() == "-no-pie")
@@ -767,8 +766,7 @@ fn link_natively<'a>(
767766

768767
// Detect '-static-pie' used with an older version of gcc or clang not supporting it.
769768
// Fallback from '-static-pie' to '-static' in that case.
770-
if sess.target.linker_is_gnu
771-
&& flavor != LinkerFlavor::Ld
769+
if matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _))
772770
&& unknown_arg_regex.is_match(&out)
773771
&& (out.contains("-static-pie") || out.contains("--no-dynamic-linker"))
774772
&& cmd.get_args().iter().any(|e| e.to_string_lossy() == "-static-pie")
@@ -903,7 +901,7 @@ fn link_natively<'a>(
903901
// install the Visual Studio build tools.
904902
if let Some(code) = prog.status.code() {
905903
if sess.target.is_like_msvc
906-
&& flavor == LinkerFlavor::Msvc
904+
&& flavor == LinkerFlavor::Msvc(Lld::No)
907905
// Respect the command line override
908906
&& sess.opts.cg.linker.is_none()
909907
// Match exactly "link.exe"
@@ -1187,7 +1185,10 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
11871185
// only the linker flavor is known; use the default linker for the selected flavor
11881186
(None, Some(flavor)) => Some((
11891187
PathBuf::from(match flavor {
1190-
LinkerFlavor::Gcc => {
1188+
LinkerFlavor::Gnu(Cc::Yes, _)
1189+
| LinkerFlavor::Darwin(Cc::Yes, _)
1190+
| LinkerFlavor::WasmLld(Cc::Yes)
1191+
| LinkerFlavor::Unix(Cc::Yes) => {
11911192
if cfg!(any(target_os = "solaris", target_os = "illumos")) {
11921193
// On historical Solaris systems, "cc" may have
11931194
// been Sun Studio, which is not flag-compatible
@@ -1200,9 +1201,14 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
12001201
"cc"
12011202
}
12021203
}
1203-
LinkerFlavor::Ld => "ld",
1204-
LinkerFlavor::Lld(_) => "lld",
1205-
LinkerFlavor::Msvc => "link.exe",
1204+
LinkerFlavor::Gnu(_, Lld::Yes)
1205+
| LinkerFlavor::Darwin(_, Lld::Yes)
1206+
| LinkerFlavor::WasmLld(..)
1207+
| LinkerFlavor::Msvc(Lld::Yes) => "lld",
1208+
LinkerFlavor::Gnu(..) | LinkerFlavor::Darwin(..) | LinkerFlavor::Unix(..) => {
1209+
"ld"
1210+
}
1211+
LinkerFlavor::Msvc(..) => "link.exe",
12061212
LinkerFlavor::EmCc => {
12071213
if cfg!(windows) {
12081214
"emcc.bat"
@@ -1227,15 +1233,20 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
12271233
|| stem == "clang"
12281234
|| stem.ends_with("-clang")
12291235
{
1230-
LinkerFlavor::Gcc
1236+
LinkerFlavor::from_cli(LinkerFlavorCli::Gcc, &sess.target)
12311237
} else if stem == "wasm-ld" || stem.ends_with("-wasm-ld") {
1232-
LinkerFlavor::Lld(LldFlavor::Wasm)
1233-
} else if stem == "ld" || stem == "ld.lld" || stem.ends_with("-ld") {
1234-
LinkerFlavor::Ld
1235-
} else if stem == "link" || stem == "lld-link" {
1236-
LinkerFlavor::Msvc
1238+
LinkerFlavor::WasmLld(Cc::No)
1239+
} else if stem == "ld" || stem.ends_with("-ld") {
1240+
LinkerFlavor::from_cli(LinkerFlavorCli::Ld, &sess.target)
1241+
} else if stem == "ld.lld" {
1242+
LinkerFlavor::Gnu(Cc::No, Lld::Yes)
1243+
} else if stem == "link" {
1244+
LinkerFlavor::Msvc(Lld::No)
1245+
} else if stem == "lld-link" {
1246+
LinkerFlavor::Msvc(Lld::Yes)
12371247
} else if stem == "lld" || stem == "rust-lld" {
1238-
LinkerFlavor::Lld(sess.target.lld_flavor)
1248+
let lld_flavor = sess.target.linker_flavor.lld_flavor();
1249+
LinkerFlavor::from_cli(LinkerFlavorCli::Lld(lld_flavor), &sess.target)
12391250
} else {
12401251
// fall back to the value in the target spec
12411252
sess.target.linker_flavor
@@ -1249,7 +1260,8 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
12491260

12501261
// linker and linker flavor specified via command line have precedence over what the target
12511262
// specification specifies
1252-
let linker_flavor = sess.opts.cg.linker_flavor.map(LinkerFlavor::from_cli);
1263+
let linker_flavor =
1264+
sess.opts.cg.linker_flavor.map(|flavor| LinkerFlavor::from_cli(flavor, &sess.target));
12531265
if let Some(ret) = infer_from(sess, sess.opts.cg.linker.clone(), linker_flavor) {
12541266
return ret;
12551267
}
@@ -1320,7 +1332,7 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) {
13201332
let verbatim = lib.verbatim.unwrap_or(false);
13211333
if sess.target.is_like_msvc {
13221334
Some(format!("{}{}", name, if verbatim { "" } else { ".lib" }))
1323-
} else if sess.target.linker_is_gnu {
1335+
} else if sess.target.linker_flavor.is_gnu() {
13241336
Some(format!("-l{}{}", if verbatim { ":" } else { "" }, name))
13251337
} else {
13261338
Some(format!("-l{}", name))
@@ -1607,7 +1619,7 @@ fn add_pre_link_objects(
16071619
let empty = Default::default();
16081620
let objects = if self_contained {
16091621
&opts.pre_link_objects_self_contained
1610-
} else if !(sess.target.os == "fuchsia" && flavor == LinkerFlavor::Gcc) {
1622+
} else if !(sess.target.os == "fuchsia" && matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _))) {
16111623
&opts.pre_link_objects
16121624
} else {
16131625
&empty
@@ -1647,7 +1659,7 @@ fn add_pre_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor)
16471659
fn add_link_script(cmd: &mut dyn Linker, sess: &Session, tmpdir: &Path, crate_type: CrateType) {
16481660
match (crate_type, &sess.target.link_script) {
16491661
(CrateType::Cdylib | CrateType::Executable, Some(script)) => {
1650-
if !sess.target.linker_is_gnu {
1662+
if !sess.target.linker_flavor.is_gnu() {
16511663
sess.fatal("can only use link script when linking with GNU-like linker");
16521664
}
16531665

@@ -1890,7 +1902,7 @@ fn add_rpath_args(
18901902
out_filename: out_filename.to_path_buf(),
18911903
has_rpath: sess.target.has_rpath,
18921904
is_like_osx: sess.target.is_like_osx,
1893-
linker_is_gnu: sess.target.linker_is_gnu,
1905+
linker_is_gnu: sess.target.linker_flavor.is_gnu(),
18941906
};
18951907
cmd.args(&rpath::get_rpath_flags(&mut rpath_config));
18961908
}
@@ -2104,7 +2116,7 @@ fn add_order_independent_options(
21042116

21052117
if sess.target.os == "fuchsia"
21062118
&& crate_type == CrateType::Executable
2107-
&& flavor != LinkerFlavor::Gcc
2119+
&& !matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _))
21082120
{
21092121
let prefix = if sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::ADDRESS) {
21102122
"asan/"
@@ -2717,12 +2729,12 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
27172729
let llvm_target = &sess.target.llvm_target;
27182730
if sess.target.vendor != "apple"
27192731
|| !matches!(os.as_ref(), "ios" | "tvos" | "watchos" | "macos")
2720-
|| (flavor != LinkerFlavor::Gcc && flavor != LinkerFlavor::Lld(LldFlavor::Ld64))
2732+
|| !matches!(flavor, LinkerFlavor::Darwin(..))
27212733
{
27222734
return;
27232735
}
27242736

2725-
if os == "macos" && flavor != LinkerFlavor::Lld(LldFlavor::Ld64) {
2737+
if os == "macos" && !matches!(flavor, LinkerFlavor::Darwin(Cc::No, _)) {
27262738
return;
27272739
}
27282740

@@ -2756,10 +2768,10 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
27562768
};
27572769

27582770
match flavor {
2759-
LinkerFlavor::Gcc => {
2771+
LinkerFlavor::Darwin(Cc::Yes, _) => {
27602772
cmd.args(&["-isysroot", &sdk_root, "-Wl,-syslibroot", &sdk_root]);
27612773
}
2762-
LinkerFlavor::Lld(LldFlavor::Ld64) => {
2774+
LinkerFlavor::Darwin(Cc::No, _) => {
27632775
cmd.args(&["-syslibroot", &sdk_root]);
27642776
}
27652777
_ => unreachable!(),
@@ -2822,7 +2834,10 @@ fn get_apple_sdk_root(sdk_name: &str) -> Result<String, String> {
28222834

28232835
fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
28242836
if let Some(ld_impl) = sess.opts.unstable_opts.gcc_ld {
2825-
if let LinkerFlavor::Gcc = flavor {
2837+
if let LinkerFlavor::Gnu(Cc::Yes, _)
2838+
| LinkerFlavor::Darwin(Cc::Yes, _)
2839+
| LinkerFlavor::WasmLld(Cc::Yes) = flavor
2840+
{
28262841
match ld_impl {
28272842
LdImpl::Lld => {
28282843
// Implement the "self-contained" part of -Zgcc-ld
@@ -2837,7 +2852,7 @@ fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
28372852
// Implement the "linker flavor" part of -Zgcc-ld
28382853
// by asking cc to use some kind of lld.
28392854
cmd.arg("-fuse-ld=lld");
2840-
if sess.target.lld_flavor != LldFlavor::Ld {
2855+
if !flavor.is_gnu() {
28412856
// Tell clang to use a non-default LLD flavor.
28422857
// Gcc doesn't understand the target option, but we currently assume
28432858
// that gcc is not used for Apple and Wasm targets (#97402).

compiler/rustc_codegen_ssa/src/back/linker.rs

+37-45
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo, S
1616
use rustc_middle::ty::TyCtxt;
1717
use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
1818
use rustc_session::Session;
19-
use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor};
19+
use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, Lld};
2020

2121
use cc::windows_registry;
2222

@@ -56,8 +56,13 @@ pub fn get_linker<'a>(
5656
let mut cmd = match linker.to_str() {
5757
Some(linker) if cfg!(windows) && linker.ends_with(".bat") => Command::bat_script(linker),
5858
_ => match flavor {
59-
LinkerFlavor::Lld(f) => Command::lld(linker, f),
60-
LinkerFlavor::Msvc if sess.opts.cg.linker.is_none() && sess.target.linker.is_none() => {
59+
LinkerFlavor::Gnu(Cc::No, Lld::Yes)
60+
| LinkerFlavor::Darwin(Cc::No, Lld::Yes)
61+
| LinkerFlavor::WasmLld(Cc::No)
62+
| LinkerFlavor::Msvc(Lld::Yes) => Command::lld(linker, flavor.lld_flavor()),
63+
LinkerFlavor::Msvc(Lld::No)
64+
if sess.opts.cg.linker.is_none() && sess.target.linker.is_none() =>
65+
{
6166
Command::new(msvc_tool.as_ref().map_or(linker, |t| t.path()))
6267
}
6368
_ => Command::new(linker),
@@ -68,9 +73,7 @@ pub fn get_linker<'a>(
6873
// To comply with the Windows App Certification Kit,
6974
// MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc).
7075
let t = &sess.target;
71-
if (flavor == LinkerFlavor::Msvc || flavor == LinkerFlavor::Lld(LldFlavor::Link))
72-
&& t.vendor == "uwp"
73-
{
76+
if matches!(flavor, LinkerFlavor::Msvc(..)) && t.vendor == "uwp" {
7477
if let Some(ref tool) = msvc_tool {
7578
let original_path = tool.path();
7679
if let Some(ref root_lib_path) = original_path.ancestors().nth(4) {
@@ -126,23 +129,22 @@ pub fn get_linker<'a>(
126129
// to the linker args construction.
127130
assert!(cmd.get_args().is_empty() || sess.target.vendor == "uwp");
128131
match flavor {
129-
LinkerFlavor::Gcc => {
130-
Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: false })
131-
as Box<dyn Linker>
132-
}
133-
LinkerFlavor::Ld if sess.target.os == "l4re" => {
132+
LinkerFlavor::Unix(Cc::No) if sess.target.os == "l4re" => {
134133
Box::new(L4Bender::new(cmd, sess)) as Box<dyn Linker>
135134
}
136-
LinkerFlavor::Lld(LldFlavor::Ld)
137-
| LinkerFlavor::Lld(LldFlavor::Ld64)
138-
| LinkerFlavor::Ld => {
139-
Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: true })
140-
as Box<dyn Linker>
141-
}
142-
LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => {
143-
Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>
144-
}
145-
LinkerFlavor::Lld(LldFlavor::Wasm) => Box::new(WasmLd::new(cmd, sess)) as Box<dyn Linker>,
135+
LinkerFlavor::WasmLld(Cc::No) => Box::new(WasmLd::new(cmd, sess)) as Box<dyn Linker>,
136+
LinkerFlavor::Gnu(cc, _)
137+
| LinkerFlavor::Darwin(cc, _)
138+
| LinkerFlavor::WasmLld(cc)
139+
| LinkerFlavor::Unix(cc) => Box::new(GccLinker {
140+
cmd,
141+
sess,
142+
target_cpu,
143+
hinted_static: false,
144+
is_ld: cc == Cc::No,
145+
is_gnu: flavor.is_gnu(),
146+
}) as Box<dyn Linker>,
147+
LinkerFlavor::Msvc(..) => Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>,
146148
LinkerFlavor::EmCc => Box::new(EmLinker { cmd, sess }) as Box<dyn Linker>,
147149
LinkerFlavor::Bpf => Box::new(BpfLinker { cmd, sess }) as Box<dyn Linker>,
148150
LinkerFlavor::Ptx => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,
@@ -211,6 +213,7 @@ pub struct GccLinker<'a> {
211213
hinted_static: bool, // Keeps track of the current hinting mode.
212214
// Link as ld
213215
is_ld: bool,
216+
is_gnu: bool,
214217
}
215218

216219
impl<'a> GccLinker<'a> {
@@ -359,7 +362,7 @@ impl<'a> Linker for GccLinker<'a> {
359362
fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path) {
360363
match output_kind {
361364
LinkOutputKind::DynamicNoPicExe => {
362-
if !self.is_ld && self.sess.target.linker_is_gnu {
365+
if !self.is_ld && self.is_gnu {
363366
self.cmd.arg("-no-pie");
364367
}
365368
}
@@ -373,7 +376,7 @@ impl<'a> Linker for GccLinker<'a> {
373376
LinkOutputKind::StaticNoPicExe => {
374377
// `-static` works for both gcc wrapper and ld.
375378
self.cmd.arg("-static");
376-
if !self.is_ld && self.sess.target.linker_is_gnu {
379+
if !self.is_ld && self.is_gnu {
377380
self.cmd.arg("-no-pie");
378381
}
379382
}
@@ -432,31 +435,25 @@ impl<'a> Linker for GccLinker<'a> {
432435
// has -needed-l{} / -needed_library {}
433436
// but we have no way to detect that here.
434437
self.sess.warn("`as-needed` modifier not implemented yet for ld64");
435-
} else if self.sess.target.linker_is_gnu && !self.sess.target.is_like_windows {
438+
} else if self.is_gnu && !self.sess.target.is_like_windows {
436439
self.linker_arg("--no-as-needed");
437440
} else {
438441
self.sess.warn("`as-needed` modifier not supported for current linker");
439442
}
440443
}
441444
self.hint_dynamic();
442-
self.cmd.arg(format!(
443-
"-l{}{lib}",
444-
if verbatim && self.sess.target.linker_is_gnu { ":" } else { "" },
445-
));
445+
self.cmd.arg(format!("-l{}{lib}", if verbatim && self.is_gnu { ":" } else { "" },));
446446
if !as_needed {
447447
if self.sess.target.is_like_osx {
448448
// See above FIXME comment
449-
} else if self.sess.target.linker_is_gnu && !self.sess.target.is_like_windows {
449+
} else if self.is_gnu && !self.sess.target.is_like_windows {
450450
self.linker_arg("--as-needed");
451451
}
452452
}
453453
}
454454
fn link_staticlib(&mut self, lib: &str, verbatim: bool) {
455455
self.hint_static();
456-
self.cmd.arg(format!(
457-
"-l{}{lib}",
458-
if verbatim && self.sess.target.linker_is_gnu { ":" } else { "" },
459-
));
456+
self.cmd.arg(format!("-l{}{lib}", if verbatim && self.is_gnu { ":" } else { "" },));
460457
}
461458
fn link_rlib(&mut self, lib: &Path) {
462459
self.hint_static();
@@ -511,10 +508,7 @@ impl<'a> Linker for GccLinker<'a> {
511508
let target = &self.sess.target;
512509
if !target.is_like_osx {
513510
self.linker_arg("--whole-archive");
514-
self.cmd.arg(format!(
515-
"-l{}{lib}",
516-
if verbatim && self.sess.target.linker_is_gnu { ":" } else { "" },
517-
));
511+
self.cmd.arg(format!("-l{}{lib}", if verbatim && self.is_gnu { ":" } else { "" },));
518512
self.linker_arg("--no-whole-archive");
519513
} else {
520514
// -force_load is the macOS equivalent of --whole-archive, but it
@@ -559,21 +553,19 @@ impl<'a> Linker for GccLinker<'a> {
559553
// eliminate the metadata. If we're building an executable, however,
560554
// --gc-sections drops the size of hello world from 1.8MB to 597K, a 67%
561555
// reduction.
562-
} else if (self.sess.target.linker_is_gnu || self.sess.target.is_like_wasm)
563-
&& !keep_metadata
564-
{
556+
} else if (self.is_gnu || self.sess.target.is_like_wasm) && !keep_metadata {
565557
self.linker_arg("--gc-sections");
566558
}
567559
}
568560

569561
fn no_gc_sections(&mut self) {
570-
if self.sess.target.linker_is_gnu || self.sess.target.is_like_wasm {
562+
if self.is_gnu || self.sess.target.is_like_wasm {
571563
self.linker_arg("--no-gc-sections");
572564
}
573565
}
574566

575567
fn optimize(&mut self) {
576-
if !self.sess.target.linker_is_gnu && !self.sess.target.is_like_wasm {
568+
if !self.is_gnu && !self.sess.target.is_like_wasm {
577569
return;
578570
}
579571

@@ -587,7 +579,7 @@ impl<'a> Linker for GccLinker<'a> {
587579
}
588580

589581
fn pgo_gen(&mut self) {
590-
if !self.sess.target.linker_is_gnu {
582+
if !self.is_gnu {
591583
return;
592584
}
593585

@@ -758,13 +750,13 @@ impl<'a> Linker for GccLinker<'a> {
758750
fn add_no_exec(&mut self) {
759751
if self.sess.target.is_like_windows {
760752
self.linker_arg("--nxcompat");
761-
} else if self.sess.target.linker_is_gnu {
753+
} else if self.is_gnu {
762754
self.linker_arg("-znoexecstack");
763755
}
764756
}
765757

766758
fn add_as_needed(&mut self) {
767-
if self.sess.target.linker_is_gnu && !self.sess.target.is_like_windows {
759+
if self.is_gnu && !self.sess.target.is_like_windows {
768760
self.linker_arg("--as-needed");
769761
} else if self.sess.target.is_like_solaris {
770762
// -z ignore is the Solaris equivalent to the GNU ld --as-needed option

0 commit comments

Comments
 (0)