This pre-RFC proposes a path to stabilize cfg_target_feature
and target_feature
. It proposes the minimal set of functionality required to allow other RFCs to progress, and sketches some implementation work that needs to happen before that.
Recall: target features
Some CPUs of the x86 architecture family support bit manipulation algorithms directly as single hardware instructions (e.g. via BMI/BMI2/TBM/ABM instruction sets). Many CPUs of the ARM architecture family support SIMD algorithms via the NEON vector extensions.
While different architectures cannot be easily mixed in the same binary, a binary can still contain code for target features not supported for the CPU it runs on, as long as this code is not executed on that CPU (otherwise a SIGILL exception is typically thrown).
The unstable “target feature” functionality in rustc supports this via two mechanisms:
-
cfg_target_feature
allows conditional compilation based on which target features are passed to rustc via cli arguments; this allows providing different implementations of some algorithms, depending on whether a target feature is enabled or not. -
[target_feature]
allows rustc to emit code that uses some target features; this allows rustc to emit code for target features not supported by the current target.
Stabilization proposal
1. White-listed target features
This RFC proposes to not stabilize any target feature names.
The stabilization of the target feature names themselves is left for follow-up RFCs (on SIMD, bit manipulation, …). However, stabilizing target features without stabilizing any target feature names necessarily introduces a split between stable and unstable target features. This requires changes to the current white-listing solution (see here for x86). Also, in the current white-listing solution, trying to use an unknown target feature results in an LLVM error/warning. This is not acceptable for a stable feature.
This RFC specifies the behavior of rustc for stabilized, unstable, and unknown target features with the objective of:
- eliminate all LLVM errors related to unknown/unavailable target features
- allow the stabilization of unstable crates relying on target features.
To achieve this, the current per-architecture target feature white-list should be split into two list for stabilized and unstable target features (per architecture). Rustc should implement the following semantics:
-
- Stable target features can be used on stable, beta, and nightly.
-
- Unstable target features can only be used on nightly.
-
- Unknown target features must be rejected by rustc (and not LLVM like it is currently the case).
-
- Unstable target features on stable must be rejected by rustc.
- 5.Suppressing these hard errors results in the feature being disabled.
The mechanism to suppress these hard errors can follow that of warnings:
#[allow(unstable_target_feature = "feature")]
#[allow(unknown_target_feature = "feature")]
And the semantics should be that on stable for unstable or unknown target features explicitly suppressed:
- conditional compilation returns false (the feature is disabled),
- the function attribute does nothing.
This should happen prior to stabilization.
2. Conditional compilation: cfg_target_feature
The cfg_target_feature
allows using target_feature
configuration option via cfg
to query specific hardware features of the target at compile-time. This information can be used for conditional compilation or via the cfg!
macro like this:
if cfg!(target_feature = "bmi2") {
// if target has the BMI2 instruction set, use a BMI2 instruction:
unsafe { intrinsic::bmi2::bzhi(x, bit_position) }
} else {
// otherwise call an algorithm that emulates the instruction:
software_fallback::bzhi(x, bit_position)
}
The features supported by the target can be either manually passed to rustc using -C target-feature=+bmi2
or automatically detected by LLVM using, e.g., RUSTFLAGS="-C target-cpu=native"
.
3. Generating code for target features: the target_feature
attribute
The target_feature
function attribute allows the compiler to emit target specific code independently of the target features supported by the current target:
#[target_feature = "+sse4.2"]
fn foo() { ... } // might contain SSE4.2 instructions even on targets that do not support SSE4.2
4. Minimal stabilization proposal
The discussion of stabilization was kickstarted by @alexcrichton on the tracking issue. This is an extended version of his proposal.
It proposes to stabilize the following:
- Stabilize passing
-C target-feature="..."
and-C target-cpu="..."
. to rustc where:
-
-C target-feature=""
has the current semantics of enabling/disabling target features -
-C target-cpu=""
has the semantics of enabling all features supported by the CPU architecture menthioned (CPU architecture names are not stabilized)
- Stabilize conditional compilation:
#[cfg(target_feature = "...")]
,cfg!(target_feature = "...")
, … - Stabilize function attribute:
[target_feature = "..."]
- Stabilize the semantics proposed in section 1. white-listing w.r.t. stable, unstable, and unknown target features and how to disable them in stable
- Stabilize
--print cfg
. - Stabilize the reference documentation for all of the above.
It does not propose to stabilize any target feature names or target CPU names. This should be done in follow-up RFCs (e.g. for SIMD, bit manipulation, cpu architectures, …).
5. Remaining work to be done prior to stabilization
- Implement the stable, unstable, unknown semantics for target features
- Document these semantics,
cfg_target_feature
, and[target_feature]
in the language reference
Pinging: @burntsushi , @alexcrichton