rust-lang / rust-lang/rust

Deal with ABI-incompatible features by considering them "never enabled"

Open
#160,301 2 comments 4 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

needs-triage
Dominant language
Rust
Stars
119k
Forks
16.2k
PR merge metrics
PR metrics pending

Description

Some target features cannot be enabled because telling LLVM about them would change the ABI. For instance, on an aarch64-softfloat target, if you turn on neon things becomes unsound. Other target features cannot be enabled because they crash LLVM, e.g. on an x86-softfloat target this happens if one enables AVX2.

The "obvious" way to deal with this is to just hard error if someone tries to enable a target feature that's effectively not supported on the current target. For -Ctarget-features that's the right call IMO, but for #[target_feature] it has been brought up that this is not great. Crates would really like to be able to do something like

#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "avx2")]
fn avx2(...) {}

#[cfg(target_arch = "aarch64")]
#[target_feature(enable = "neon")]
fn neon(...) {}

fn do_the_thing(...) {
  cfg_select! {
    target_arch = "x86_64" => {
      if is_x86_feature_detected!("avx2") { return avx2(...); }
    }
    target_arch = "aarch64" => {
      if is_aarch64_feature_detected!("neon") { return neon(...); }
    }
  }

  scalar_fallback(...)
}

Under the hard error scheme, such code fails to build on a softfloat target. What would work better there is if we said that we consider these target features to be never available on softfloat targets, meaning that calling the corresponding functions is always UB and is_feature_detected! always returns false. Then we don't have ABI issues either, and we can avoid the LLVM crashes by not even generating LLVM IR for the body of these functions (they can't be called anyway).

Basically, we'd say that depending on your target, some target features are just off-limits no matter what your hardware can do.
This was suggested by @newpavlov and affected users seem to like it.

This would not be a hard guarantee, if LLVM eventually gains support for generating AVX2 code with a softfloat ABI then we could allow that target feature to behave normally again. But today that's just not something LLVM supports so there's no point in us pretending otherwise.

@workingjubilee @Amanieu do you think this scheme makes any sense? How hard would it be to ensure that is_feature_detected! always returns false for such features on the relevant targets? Everything else happens in the compiler and I think it can be done with relative ease, but is_feature_detected! is a black magic box for me. Also how bad of an idea would it be to decouple "this target feature can be used in my Rust program" from "this target feature is supported by the underlying hardware"? This has the potential to cause some confusion, though in code that properly uses is_feature_detected! it cannot cause UB.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing how #[target_feature] and is_feature_detected! handle target features, especially on aarch64-softfloat and x86-softfloat targets. Determine where unsupported features are validated and how feature-detection results are generated; done means such features are treated as unavailable without ABI issues or LLVM crashes, while supported targets retain existing behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.