Implement cfg(target_abi) (RFC 2992)

Add an `abi` field to `TargetOptions`, defaulting to "". Support using
`cfg(target_abi = "...")` for conditional compilation on that field.

Gated by `feature(cfg_target_abi)`.

Add a test for `target_abi`, and a test for the feature gate.

Add `target_abi` to tidy as a platform-specific cfg.

This does not add an abi to any existing target.
This commit is contained in:
Josh Triplett 2021-07-06 20:54:54 -07:00
parent c0bd5a584d
commit 84d6e8aed3
9 changed files with 76 additions and 1 deletions

View File

@ -687,6 +687,9 @@ pub fn set(&self, features: &mut Features, span: Span) {
/// Allows qualified paths in struct expressions, struct patterns and tuple struct patterns. /// Allows qualified paths in struct expressions, struct patterns and tuple struct patterns.
(active, more_qualified_paths, "1.54.0", Some(80080), None), (active, more_qualified_paths, "1.54.0", Some(80080), None),
/// Allows `cfg(target_abi = "...")`.
(active, cfg_target_abi, "1.55.0", Some(80970), None),
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// feature-group-end: actual feature gates // feature-group-end: actual feature gates
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------

View File

@ -23,6 +23,7 @@ macro_rules! cfg_fn {
/// `cfg(...)`'s that are feature gated. /// `cfg(...)`'s that are feature gated.
const GATED_CFGS: &[GatedCfg] = &[ const GATED_CFGS: &[GatedCfg] = &[
// (name in cfg, feature, function to check if the feature is enabled) // (name in cfg, feature, function to check if the feature is enabled)
(sym::target_abi, sym::cfg_target_abi, cfg_fn!(cfg_target_abi)),
(sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)), (sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)),
(sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), (sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
(sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), (sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),

View File

@ -805,6 +805,7 @@ fn default_configuration(sess: &Session) -> CrateConfig {
let wordsz = sess.target.pointer_width.to_string(); let wordsz = sess.target.pointer_width.to_string();
let os = &sess.target.os; let os = &sess.target.os;
let env = &sess.target.env; let env = &sess.target.env;
let abi = &sess.target.abi;
let vendor = &sess.target.vendor; let vendor = &sess.target.vendor;
let min_atomic_width = sess.target.min_atomic_width(); let min_atomic_width = sess.target.min_atomic_width();
let max_atomic_width = sess.target.max_atomic_width(); let max_atomic_width = sess.target.max_atomic_width();
@ -814,7 +815,7 @@ fn default_configuration(sess: &Session) -> CrateConfig {
}); });
let mut ret = FxHashSet::default(); let mut ret = FxHashSet::default();
ret.reserve(6); // the minimum number of insertions ret.reserve(7); // the minimum number of insertions
// Target bindings. // Target bindings.
ret.insert((sym::target_os, Some(Symbol::intern(os)))); ret.insert((sym::target_os, Some(Symbol::intern(os))));
for fam in &sess.target.families { for fam in &sess.target.families {
@ -829,6 +830,7 @@ fn default_configuration(sess: &Session) -> CrateConfig {
ret.insert((sym::target_endian, Some(Symbol::intern(end.as_str())))); ret.insert((sym::target_endian, Some(Symbol::intern(end.as_str()))));
ret.insert((sym::target_pointer_width, Some(Symbol::intern(&wordsz)))); ret.insert((sym::target_pointer_width, Some(Symbol::intern(&wordsz))));
ret.insert((sym::target_env, Some(Symbol::intern(env)))); ret.insert((sym::target_env, Some(Symbol::intern(env))));
ret.insert((sym::target_abi, Some(Symbol::intern(abi))));
ret.insert((sym::target_vendor, Some(Symbol::intern(vendor)))); ret.insert((sym::target_vendor, Some(Symbol::intern(vendor))));
if sess.target.has_elf_tls { if sess.target.has_elf_tls {
ret.insert((sym::target_thread_local, None)); ret.insert((sym::target_thread_local, None));

View File

@ -353,6 +353,7 @@
cfg_eval, cfg_eval,
cfg_panic, cfg_panic,
cfg_sanitize, cfg_sanitize,
cfg_target_abi,
cfg_target_feature, cfg_target_feature,
cfg_target_has_atomic, cfg_target_has_atomic,
cfg_target_thread_local, cfg_target_thread_local,
@ -1199,6 +1200,7 @@
sync, sync,
sync_trait, sync_trait,
t32, t32,
target_abi,
target_arch, target_arch,
target_endian, target_endian,
target_env, target_env,

View File

@ -1025,6 +1025,9 @@ pub struct TargetOptions {
pub os: String, pub os: String,
/// Environment name to use for conditional compilation (`target_env`). Defaults to "". /// Environment name to use for conditional compilation (`target_env`). Defaults to "".
pub env: String, pub env: String,
/// ABI name to distinguish multiple ABIs on the same OS and architecture. For instance, `"eabi"`
/// or `"eabihf"`. Defaults to "".
pub abi: String,
/// Vendor name to use for conditional compilation (`target_vendor`). Defaults to "unknown". /// Vendor name to use for conditional compilation (`target_vendor`). Defaults to "unknown".
pub vendor: String, pub vendor: String,
/// Default linker flavor used if `-C linker-flavor` or `-C linker` are not passed /// Default linker flavor used if `-C linker-flavor` or `-C linker` are not passed
@ -1342,6 +1345,7 @@ fn default() -> TargetOptions {
c_int_width: "32".to_string(), c_int_width: "32".to_string(),
os: "none".to_string(), os: "none".to_string(),
env: String::new(), env: String::new(),
abi: String::new(),
vendor: "unknown".to_string(), vendor: "unknown".to_string(),
linker_flavor: LinkerFlavor::Gcc, linker_flavor: LinkerFlavor::Gcc,
linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.to_string()), linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.to_string()),
@ -1919,6 +1923,7 @@ macro_rules! key {
key!(c_int_width = "target-c-int-width"); key!(c_int_width = "target-c-int-width");
key!(os); key!(os);
key!(env); key!(env);
key!(abi);
key!(vendor); key!(vendor);
key!(linker_flavor, LinkerFlavor)?; key!(linker_flavor, LinkerFlavor)?;
key!(linker, optional); key!(linker, optional);
@ -2152,6 +2157,7 @@ macro_rules! target_option_val {
target_option_val!(c_int_width, "target-c-int-width"); target_option_val!(c_int_width, "target-c-int-width");
target_option_val!(os); target_option_val!(os);
target_option_val!(env); target_option_val!(env);
target_option_val!(abi);
target_option_val!(vendor); target_option_val!(vendor);
target_option_val!(linker_flavor); target_option_val!(linker_flavor);
target_option_val!(linker); target_option_val!(linker);

View File

@ -0,0 +1,10 @@
// run-pass
#![feature(cfg_target_abi)]
#[cfg(target_abi = "eabihf")]
pub fn main() {
}
#[cfg(not(target_abi = "eabihf"))]
pub fn main() {
}

View File

@ -0,0 +1,11 @@
#[cfg(target_abi = "x")] //~ ERROR `cfg(target_abi)` is experimental
#[cfg_attr(target_abi = "x", x)] //~ ERROR `cfg(target_abi)` is experimental
struct Foo(u64, u64);
#[cfg(not(any(all(target_abi = "x"))))] //~ ERROR `cfg(target_abi)` is experimental
fn foo() {}
fn main() {
cfg!(target_abi = "x");
//~^ ERROR `cfg(target_abi)` is experimental and subject to change
}

View File

@ -0,0 +1,39 @@
error[E0658]: `cfg(target_abi)` is experimental and subject to change
--> $DIR/feature-gate-cfg-target-abi.rs:2:12
|
LL | #[cfg_attr(target_abi = "x", x)]
| ^^^^^^^^^^^^^^^^
|
= note: see issue #80970 <https://github.com/rust-lang/rust/issues/80970> for more information
= help: add `#![feature(cfg_target_abi)]` to the crate attributes to enable
error[E0658]: `cfg(target_abi)` is experimental and subject to change
--> $DIR/feature-gate-cfg-target-abi.rs:1:7
|
LL | #[cfg(target_abi = "x")]
| ^^^^^^^^^^^^^^^^
|
= note: see issue #80970 <https://github.com/rust-lang/rust/issues/80970> for more information
= help: add `#![feature(cfg_target_abi)]` to the crate attributes to enable
error[E0658]: `cfg(target_abi)` is experimental and subject to change
--> $DIR/feature-gate-cfg-target-abi.rs:5:19
|
LL | #[cfg(not(any(all(target_abi = "x"))))]
| ^^^^^^^^^^^^^^^^
|
= note: see issue #80970 <https://github.com/rust-lang/rust/issues/80970> for more information
= help: add `#![feature(cfg_target_abi)]` to the crate attributes to enable
error[E0658]: `cfg(target_abi)` is experimental and subject to change
--> $DIR/feature-gate-cfg-target-abi.rs:9:10
|
LL | cfg!(target_abi = "x");
| ^^^^^^^^^^^^^^^^
|
= note: see issue #80970 <https://github.com/rust-lang/rust/issues/80970> for more information
= help: add `#![feature(cfg_target_abi)]` to the crate attributes to enable
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -122,6 +122,7 @@ fn check_cfgs(
let contains_platform_specific_cfg = cfg.contains("target_os") let contains_platform_specific_cfg = cfg.contains("target_os")
|| cfg.contains("target_env") || cfg.contains("target_env")
|| cfg.contains("target_abi")
|| cfg.contains("target_vendor") || cfg.contains("target_vendor")
|| cfg.contains("unix") || cfg.contains("unix")
|| cfg.contains("windows"); || cfg.contains("windows");