Skip to content

Port compiler-rt intrinsics to Rust #35437

Closed
@japaric

Description

@japaric

Rationale

Porting compiler-rt to Rust is one of the remaining obstacles towards the intersection of our "on the fly compilation of std" and "rust everywhere" dreams.

For our goal of "on the fly compilation of std" (or any other set of "standard" crates), we want to minimize the number of C dependencies required to build std as these complicate the compilation process: users need a C (cross) compiler and we (rust-lang/rust) have to support (cross) compiling each of these C dependencies, which are wrapped in crates, to every target (even custom ones!) that downstream users may use -- this last part leads to complicated build.rs scripts that need to handle conditional compilation logic and deal with obscure gcc flags . On Linux, there are three C dependencies that we have to deal with: backtrace, jemalloc and compiler-rt. backtrace and jemalloc are optional on Linux and not available on some other platforms but compiler-rt is mandatory on most (all?) the targets we support.

This issue is about porting compiler-rt to Rust. Once ported, we can say goodbye to its complicated build.rs and make std easier to (cross) compile! An extra advantage is that, with this change, the compiler-rt intrinsics will receive the same optimizations as the std crate. This is not done today because it would make the build.rs even more complicated: flags like -march and -mcpu would have to be conditionally passed to gcc according to $TARGET.

The process

The goal is simple: We have to port each and every compiler-rt intrinsic along with their tests to the rustc-builtins crate.

The process could go two ways:

  1. Using a "wholesale" approach: We can develop the new rustc-builtins crate out of tree: porting intrinsics and unit tests over time. Once all the intrinsics and unit tests are ported we can replace the in-tree rustc-builtins crate with the out-of-tree one and have the buildbots (and probably crater) serve as an integration test.
  2. Using an incremental approach: We can rely on the fact that gcc_s provides the same intrinsics as compiler-rt and simply remove rustc-builtins's build.rs. This effectively means that rustc-builtins will no longer provide any intrinsic and that std programs will instead use gcc_s' intrinsics. Then we can start porting intrinsics + unit tests and adding them to rustc-builtins one by one. Each time a intrinsic is added, Rust programs will start using that intrinsic instead of the gcc_s' one.

The advantage of (2) is that we get an std that's easy to cross compile early on (because rustc-builtins is essentially empty!). Its disadvantage is that no_std programs which don't link to gcc_s and that depend on compiler-rt intrinsics will abruptly stop to compile because of linker errors (undefined reference to $intrinsic).

Prioritization

Some Rust targets use more or different intrinsics than others. If we take the incremental approach mentioned in the previous section, it makes sense to prioritize porting the intrinsics required by tier-1 platforms. This gist contains a "hack" to yields the list of intrinsics required to link rustc for a certain target plus lists of intrinsics generated with this "hack" for a few (right now, two) targets. The lists contained therein can be used to decide which intrinsics to prioritize.

Drawbacks

On each LLVM upgrade, we would have to carefully check if any compiler-rt intrinsics have been added (we already have to do this today) and the upgrade would be blocked on porting those new intrinsics to Rust first (this is the extra work that this change would create).

Unresolved questions

  • Pick an approach to implement this change.

compilerrt_abort

Some intrinsics can fail (e.g. absvdi2). compiler-rt handles the failures by "aborting" -- it calls a compilerrt_abort() function. Should this function be ported to Rust? Or should the intrinsics, instead, panic! on failure?


cc @alexcrichton @brson

Metadata

Metadata

Assignees

No one assigned

    Labels

    T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions