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_featureallows 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