1
Fork 0

Auto merge of #123656 - lqd:linker-features, r=petrochenkov

Linker flavors next steps: linker features

This is my understanding of the first step towards `@petrochenkov's` vision for the future of linker flavors, described in https://github.com/rust-lang/rust/pull/119906#issuecomment-1895693162 and the discussion that followed.

To summarize: having `Cc` and `Lld` embedded in linker flavors creates tension about naming, and a combinatorial explosion of flavors for each new linker feature we'd want to use. Linker features are an extension mechanism that is complementary to principal flavors, with benefits described in #119906.

The most immediate use of this flag would be to turn self-contained linking on and off via features instead of flavors. For example, `-Clinker-features=+/-lld` would toggle using lld instead of selecting a precise flavor, and would be "generic" and work cross-platform (whereas linker flavors are currently more tied to targets). Under this scheme, MCP510 is expected to be `-Clink-self-contained=+linker -Zlinker-features=+lld -Zunstable-options` (though for the time being, the original flags using lld-cc flavors still work).

I purposefully didn't add or document CLI support for `+/-cc`, as it would be a noop right now. I only expect that we'd initially want to stabilize `+/-lld` to begin with.

r? `@petrochenkov`

You had requested that minimal churn would be done to the 230 target specs and this does none yet: the linker features are inferred from the flavor since they're currently isomorphic. We of course expect this to change sooner rather than later.

In the future, we can allow targets to define linker features independently from their flavor, and remove the cc and lld components from the flavors to use the features instead, this actually doesn't need to block stabilization, as we discussed.

(Best reviewed per commit)
This commit is contained in:
bors 2024-04-13 11:10:01 +00:00
commit 7106800e16
6 changed files with 223 additions and 27 deletions

View file

@ -18,7 +18,7 @@ use rustc_feature::UnstableFeatures;
use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION};
use rustc_span::source_map::FilePathMapping;
use rustc_span::{FileName, FileNameDisplayPreference, RealFileName, SourceFileHashAlgorithm};
use rustc_target::spec::LinkSelfContainedComponents;
use rustc_target::spec::{LinkSelfContainedComponents, LinkerFeatures};
use rustc_target::spec::{SplitDebuginfo, Target, TargetTriple};
use std::collections::btree_map::{
Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter,
@ -292,6 +292,48 @@ impl LinkSelfContained {
}
}
/// The different values that `-Z linker-features` can take on the CLI: a list of individually
/// enabled or disabled features used during linking.
///
/// There is no need to enable or disable them in bulk. Each feature is fine-grained, and can be
/// used to turn `LinkerFeatures` on or off, without needing to change the linker flavor:
/// - using the system lld, or the self-contained `rust-lld` linker
/// - using a C/C++ compiler to drive the linker (not yet exposed on the CLI)
/// - etc.
#[derive(Default, Copy, Clone, PartialEq, Debug)]
pub struct LinkerFeaturesCli {
/// The linker features that are enabled on the CLI, using the `+feature` syntax.
pub enabled: LinkerFeatures,
/// The linker features that are disabled on the CLI, using the `-feature` syntax.
pub disabled: LinkerFeatures,
}
impl LinkerFeaturesCli {
/// Accumulates an enabled or disabled feature as specified on the CLI, if possible.
/// For example: `+lld`, and `-lld`.
pub(crate) fn handle_cli_feature(&mut self, feature: &str) -> Option<()> {
// Duplicate flags are reduced as we go, the last occurrence wins:
// `+feature,-feature,+feature` only enables the feature, and does not record it as both
// enabled and disabled on the CLI.
// We also only expose `+/-lld` at the moment, as it's currenty the only implemented linker
// feature and toggling `LinkerFeatures::CC` would be a noop.
match feature {
"+lld" => {
self.enabled.insert(LinkerFeatures::LLD);
self.disabled.remove(LinkerFeatures::LLD);
Some(())
}
"-lld" => {
self.disabled.insert(LinkerFeatures::LLD);
self.enabled.remove(LinkerFeatures::LLD);
Some(())
}
_ => None,
}
}
}
/// Used with `-Z assert-incr-state`.
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
pub enum IncrementalStateAssertion {

View file

@ -426,6 +426,8 @@ mod desc {
"one of supported split dwarf modes (`split` or `single`)";
pub const parse_link_self_contained: &str = "one of: `y`, `yes`, `on`, `n`, `no`, `off`, or a list of enabled (`+` prefix) and disabled (`-` prefix) \
components: `crto`, `libc`, `unwind`, `linker`, `sanitizers`, `mingw`";
pub const parse_linker_features: &str =
"a list of enabled (`+` prefix) and disabled (`-` prefix) features: `lld`";
pub const parse_polonius: &str = "either no value or `legacy` (the default), or `next`";
pub const parse_stack_protector: &str =
"one of (`none` (default), `basic`, `strong`, or `all`)";
@ -1269,6 +1271,22 @@ mod parse {
true
}
/// Parse a comma-separated list of enabled and disabled linker features.
pub(crate) fn parse_linker_features(slot: &mut LinkerFeaturesCli, v: Option<&str>) -> bool {
match v {
Some(s) => {
for feature in s.split(',') {
if slot.handle_cli_feature(feature).is_none() {
return false;
}
}
true
}
None => false,
}
}
pub(crate) fn parse_wasi_exec_model(slot: &mut Option<WasiExecModel>, v: Option<&str>) -> bool {
match v {
Some("command") => *slot = Some(WasiExecModel::Command),
@ -1721,6 +1739,8 @@ options! {
"link native libraries in the linker invocation (default: yes)"),
link_only: bool = (false, parse_bool, [TRACKED],
"link the `.rlink` file generated by `-Z no-link` (default: no)"),
linker_features: LinkerFeaturesCli = (LinkerFeaturesCli::default(), parse_linker_features, [UNTRACKED],
"a comma-separated list of linker features to enable (+) or disable (-): `lld`"),
lint_mir: bool = (false, parse_bool, [UNTRACKED],
"lint MIR before and after each transformation"),
llvm_module_flag: Vec<(String, u32, String)> = (Vec::new(), parse_llvm_module_flag, [TRACKED],