Add riscv32imfc-unknown-none-elf bare-metal target#158473
Open
sanchuanhehe wants to merge 1 commit into
Open
Conversation
Add a tier 3 bare-metal target for RV32IMFC cores that have hardware single-precision floating point (the `F` extension, `ilp32f` ABI) but no atomic (`A`) extension. This is `riscv32imafc-unknown-none-elf` minus the atomic extension, handled the same way `riscv32imc-unknown-none-elf` handles a no-`a` core: `+forced-atomics` lowers atomic load/store to plain load/store (sound on a single hart) while `atomic_cas = false` keeps RMW/CAS off, so no `lr.w`/`sc.w`/`amo*` are ever emitted and the target does not trap on a core without the `A` extension. Downstream crates use a critical-section polyfill (e.g. `portable-atomic`) for compare-and-swap. This combination has no builtin target today: cores that pair a hardware-float application core with no atomic extension otherwise need a custom target spec plus `-Zbuild-std` on nightly, which is unavailable on stable. The motivating hardware is the application core of vendor SoCs such as the HiSilicon WS63/BS2X family, but the target is vendor-neutral. Register the target, add it to the `targets-elf` assembly sanity test, and document it on the shared `riscv32-unknown-none-elf` platform-support page.
Collaborator
|
Thanks for the pull request, and welcome! The Rust Project is excited to review your changes, and you should hear from @jieyouxu (or someone else) some time within the next two weeks. Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (
Why was this reviewer chosen?The reviewer was selected based on:
|
Author
|
@rustbot label +O-riscv |
Collaborator
|
These commits modify compiler targets. Some changes occurred in src/doc/rustc/src/platform-support cc @Noratrieb |
Member
|
r? compiler_leads |
davidtwco
approved these changes
Jul 2, 2026
Member
|
@bors r+ rollup |
Contributor
JonathanBrouwer
added a commit
to JonathanBrouwer/rust
that referenced
this pull request
Jul 2, 2026
…e-elf, r=davidtwco Add `riscv32imfc-unknown-none-elf` bare-metal target This adds a new tier 3 bare-metal target for RV32IMFC cores: RISC-V 32-bit with the `M`, `F` (hardware single-precision float, `ilp32f` ABI) and `C` extensions, but **no** atomic (`A`) extension. ## Why a new builtin target No builtin target pairs **hardware single-float** with **no atomics** today: - `riscv32imafc-unknown-none-elf` (tier 2) has hard-float but *requires* `A`. - `riscv32imc-unknown-none-elf` has no atomics but is **soft-float** (`ilp32`). Cores that have an `F` unit but no `A` extension (a common shape for the application core of low-power Wi-Fi/BT SoCs, where vendor-supplied closed binary blobs are compiled with the `ilp32f` ABI, so the soft-float ABI is incompatible) currently have to ship a custom JSON target spec and build `core` with `-Zbuild-std` on nightly. There is **no stable path today**: custom target specs are nightly-only, and the spec drifts with each nightly. A builtin target lets these users stay on stable with a precompiled `core`. The motivating hardware includes the application core of SoCs such as the HiSilicon WS63/BS2X family, but the target itself is vendor-neutral. A working nightly + `-Zbuild-std` proof of concept (builds `core`/`alloc`, confirms hard-float `fmul.s`/`fadd.s`, and that atomics lower to plain `lw`/`sw` with zero `amo*`/`lr.w`/`sc.w`): https://github.com/hispark-rs/hisi-riscv-imfc-poc ## How it is defined It is `riscv32imafc-unknown-none-elf` minus the `A` extension, handled exactly the way the existing `riscv32imc-unknown-none-elf` handles a no-`a` core: - `features = "+m,+f,+c,+forced-atomics"`, `llvm_abiname = ilp32f` - `atomic_cas = false`: `lr.w`/`sc.w`/`amo*` are never emitted, so the target does not trap on a core without `A`. `+forced-atomics` lowers atomic load/store to plain load/store (sound on a single hart); compare-and-swap and other RMW atomics are off, so downstream crates use a critical-section polyfill (e.g. `portable-atomic`'s `critical-section` feature) for those. ## Changes - New target spec `riscv32imfc_unknown_none_elf.rs` + registration in `spec/mod.rs`. - Added to the `tests/assembly-llvm/targets/targets-elf.rs` sanity test (satisfies the `target_policy` and `target_specific_tests` tidy checks). - Documented on the shared `riscv32-unknown-none-elf` platform-support page and listed in `platform-support.md`. ## Verification - `./x test tidy` — passes. - `./x test tests/assembly-llvm/targets/targets-elf.rs` — passes (262 passed, 0 failed); satisfies the "must be able to produce assembly" requirement. ## Tier 3 target policy Acknowledgement of each [tier 3 target policy](https://doc.rust-lang.org/rustc/target-tier-policy.html#tier-3-target-policy) requirement: > A tier 3 target must have a designated developer or developers (the "target maintainers") on record to be CCed when issues arise regarding the target. (The mechanism to track and CC such developers may evolve over time.) Ack. @sanchuanhehe will maintain the target; recorded on the `riscv32-unknown-none-elf` platform-support page. > Targets must use naming consistent with any existing targets; for instance, a target for the same CPU or OS as an existing Rust target should use the same name for that CPU or OS. Targets should normally use the same names and naming conventions as used elsewhere in the broader ecosystem beyond Rust (such as in other toolchains), unless they have a very good reason to diverge. Changing the name of a target can be highly disruptive, especially once the target reaches a higher tier, so getting the name right is important even for a tier 3 target. > > Target names should not introduce undue confusion or ambiguity unless absolutely necessary to maintain ecosystem compatibility. For example, if the name of the target makes people extremely likely to form incorrect beliefs about what it targets, the name should be changed or augmented to disambiguate it. > > If possible, use only letters, numbers, dashes and underscores for the name. Periods (.) are known to cause issues in Cargo. Ack. The target is named `riscv32imfc-unknown-none-elf`, fitting the existing `riscv32im{,a,c,fc,ac,afc}-unknown-none-elf` family: standard RISC-V ISA-extension letters (`imfc`) and the `unknown-none-elf` triple shared by the other bare-metal RISC-V targets. The name uses only letters, numbers and dashes. > Tier 3 targets may have unusual requirements to build or use, but must not create legal issues or impose onerous legal terms for the Rust project or for Rust developers or users. > > The target must not introduce license incompatibilities. > > Anything added to the Rust repository must be under the standard Rust license (MIT OR Apache-2.0). > > The target must not cause the Rust tools or libraries built for any other host (even when supporting cross-compilation to the target) to depend on any new dependency less permissive than the Rust licensing policy. > > Compiling, linking, and emitting functional binaries, libraries, or other code for the target must not depend on proprietary (non-FOSS) libraries. Ack. Everything added is under `MIT OR Apache-2.0`. The change is a purely additive target spec plus docs and a test; it introduces no new dependency and no proprietary component. Code generation uses the in-tree LLVM RISC-V backend only. > Neither this policy nor any decisions made regarding targets shall create any binding agreement or estoppel by any party. If any member of an approving Rust team serves as one of the maintainers of a target, or has any legal or employment requirement (explicit or implicit) that might affect their decisions regarding a target, they must recuse themselves from any approval decisions regarding the target's tier status, though they may otherwise participate in discussions. Ack. > Tier 3 targets should attempt to implement as much of the standard libraries as possible and appropriate (core for most targets, alloc for targets that can support dynamic memory allocation, std for targets with an operating system or equivalent layer of system-provided functionality), but may leave some code unimplemented (either unavailable or stubbed out as appropriate), whether because the target makes it impossible to implement or challenging to implement. The authors of pull requests are not obligated to avoid calling any portions of the standard library on the basis of a tier 3 target not implementing those portions. Ack. This is a bare-metal `no_std` target (`std: false`). `core` and `alloc` build for it, the same as the sibling `riscv32imc` / `riscv32imafc` targets; `std` is not applicable as there is no operating system layer. > The target must provide documentation for the Rust community explaining how to build for the target, using cross-compilation if possible. If the target supports running binaries, or running tests (even if they do not pass), the documentation must explain how to run such binaries or tests for the target, using emulation if possible or dedicated hardware if necessary. Ack. Documented on the shared `riscv32-unknown-none-elf` platform-support page (cross-compiled, `rust-lld`, linker-script requirement). Like the other bare-metal RISC-V targets, the Rust test suite cannot be run on it; it must be run in a simulator or on hardware. > Tier 3 targets must not impose burden on the authors of pull requests, or other developers in the community, to maintain the target. In particular, do not post comments (automated or manual) on a PR that derail or suggest a block on the PR based on a tier 3 target. Do not send automated messages or notifications (via any medium, including via @) to a PR author or others involved with a PR regarding a tier 3 target, unless they have opted into such messages. Ack. > Patches adding or updating tier 3 targets must not break any existing tier 2 or tier 1 target, and must not knowingly break another tier 3 target without approval of either the compiler team or the maintainers of the other tier 3 target. In particular, this may come up when working on closely related targets, such as variations of the same architecture with different features. Avoid introducing unconditional uses of features that another variation of the target may not have; use conditional compilation or runtime detection, as appropriate, to let each target run code supported by that target. Ack. The change is additive only and touches no code shared with other targets; `./x test tidy` and the `targets-elf` assembly test pass. No unconditional use of any feature is introduced that would affect other RISC-V target variations. > Tier 3 targets must be able to produce assembly using at least one of rustc's supported backends from any host target. (Having support in a fork of the backend is not sufficient, it must be upstream.) Ack. Covered by the new `tests/assembly-llvm/targets/targets-elf.rs` revision, which passes using the upstream LLVM backend. > If a tier 3 target stops meeting these requirements [...] we may post a PR to remove it; any such PR will be CCed to the target maintainers [...] to check potential interest in improving the situation. Ack.
rust-bors Bot
pushed a commit
that referenced
this pull request
Jul 3, 2026
…uwer Rollup of 22 pull requests Successful merges: - #155429 (Support `u128`/`i128` c-variadic arguments) - #158100 (Emit retags in codegen to support BorrowSanitizer (part 4)) - #158494 (Improve E0277 diagnostics for conditionally implemented traits) - #158606 (use ProjectionPredicate instead of AliasRelate) - #158627 (Simplify option-iterator flattening in the compiler) - #158658 (Update LLVM submodule) - #158665 (Revert "Remove redundant dyn-compatibility check.") - #158021 (Remove old MinGW workaround) - #158473 (Add `riscv32imfc-unknown-none-elf` bare-metal target) - #158549 (process::exec: using appropriate exit code on vxworks.) - #158585 (Improve diagnostic for too many super keywords) - #158637 (hir_ty_lowering: avoid self type lookup for inherent aliases) - #158651 (ptr doc: reduce use of unsafe block to where needed) - #158669 (Remove `src/tools/test-float-parse/Cargo.lock`) - #158674 (library: Polish transmute's `split_at_stdlib` example) - #158677 (Add extra splat tests) - #158680 (Avoid ICE for `NonZero<char>` in improper_ctypes) - #158681 (Remove unnecessary `Hash` derives from MIR types) - #158682 (Avoid delayed bug for disabled on_type_error arguments) - #158684 (Add missing generic test coverage for ```#[splat]```) - #158687 (Streamline `MacEager`) - #158688 (Cleanup attribute docs and add links to other mentioned attributes)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This adds a new tier 3 bare-metal target for RV32IMFC cores: RISC-V 32-bit with
the
M,F(hardware single-precision float,ilp32fABI) andCextensions,but no atomic (
A) extension.Why a new builtin target
No builtin target pairs hardware single-float with no atomics today:
riscv32imafc-unknown-none-elf(tier 2) has hard-float but requiresA.riscv32imc-unknown-none-elfhas no atomics but is soft-float (ilp32).Cores that have an
Funit but noAextension (a common shape for theapplication core of low-power Wi-Fi/BT SoCs, where vendor-supplied closed binary
blobs are compiled with the
ilp32fABI, so the soft-float ABI is incompatible)currently have to ship a custom JSON target spec and build
corewith-Zbuild-stdon nightly. There is no stable path today: custom target specsare nightly-only, and the spec drifts with each nightly. A builtin target lets
these users stay on stable with a precompiled
core. The motivating hardwareincludes the application core of SoCs such as the HiSilicon WS63/BS2X family, but
the target itself is vendor-neutral.
A working nightly +
-Zbuild-stdproof of concept (buildscore/alloc,confirms hard-float
fmul.s/fadd.s, and that atomics lower to plainlw/swwith zero
amo*/lr.w/sc.w): https://github.com/hispark-rs/hisi-riscv-imfc-pocHow it is defined
It is
riscv32imafc-unknown-none-elfminus theAextension, handled exactly theway the existing
riscv32imc-unknown-none-elfhandles a no-acore:features = "+m,+f,+c,+forced-atomics",llvm_abiname = ilp32fatomic_cas = false:lr.w/sc.w/amo*are never emitted, so the target doesnot trap on a core without
A.+forced-atomicslowers atomic load/store toplain load/store (sound on a single hart); compare-and-swap and other RMW
atomics are off, so downstream crates use a critical-section polyfill (e.g.
portable-atomic'scritical-sectionfeature) for those.Changes
riscv32imfc_unknown_none_elf.rs+ registration inspec/mod.rs.tests/assembly-llvm/targets/targets-elf.rssanity test (satisfiesthe
target_policyandtarget_specific_teststidy checks).riscv32-unknown-none-elfplatform-support page andlisted in
platform-support.md.Verification
./x test tidy— passes../x test tests/assembly-llvm/targets/targets-elf.rs— passes (262 passed,0 failed); satisfies the "must be able to produce assembly" requirement.
Tier 3 target policy
Acknowledgement of each tier 3 target policy requirement:
Ack. @sanchuanhehe will maintain the target; recorded on the
riscv32-unknown-none-elfplatform-support page.Ack. The target is named
riscv32imfc-unknown-none-elf, fitting the existingriscv32im{,a,c,fc,ac,afc}-unknown-none-elffamily: standard RISC-V ISA-extensionletters (
imfc) and theunknown-none-elftriple shared by the other bare-metalRISC-V targets. The name uses only letters, numbers and dashes.
Ack. Everything added is under
MIT OR Apache-2.0. The change is a purelyadditive target spec plus docs and a test; it introduces no new dependency and no
proprietary component. Code generation uses the in-tree LLVM RISC-V backend only.
Ack.
Ack. This is a bare-metal
no_stdtarget (std: false).coreandallocbuild for it, the same as the sibling
riscv32imc/riscv32imafctargets;stdis not applicable as there is no operating system layer.
Ack. Documented on the shared
riscv32-unknown-none-elfplatform-support page(cross-compiled,
rust-lld, linker-script requirement). Like the other bare-metalRISC-V targets, the Rust test suite cannot be run on it; it must be run in a
simulator or on hardware.
Ack.
Ack. The change is additive only and touches no code shared with other targets;
./x test tidyand thetargets-elfassembly test pass. No unconditional use ofany feature is introduced that would affect other RISC-V target variations.
Ack. Covered by the new
tests/assembly-llvm/targets/targets-elf.rsrevision,which passes using the upstream LLVM backend.
Ack.