diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index ef5c98642e9f8..8fe2a58ffbd64 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1686,6 +1686,7 @@ supported_targets! { ("riscv32im-unknown-none-elf", riscv32im_unknown_none_elf), ("riscv32ima-unknown-none-elf", riscv32ima_unknown_none_elf), ("riscv32imc-unknown-none-elf", riscv32imc_unknown_none_elf), + ("riscv32imfc-unknown-none-elf", riscv32imfc_unknown_none_elf), ("riscv32imc-esp-espidf", riscv32imc_esp_espidf), ("riscv32imac-esp-espidf", riscv32imac_esp_espidf), ("riscv32imafc-esp-espidf", riscv32imafc_esp_espidf), diff --git a/compiler/rustc_target/src/spec/targets/riscv32imfc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imfc_unknown_none_elf.rs new file mode 100644 index 0000000000000..da88f860b3935 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/riscv32imfc_unknown_none_elf.rs @@ -0,0 +1,44 @@ +use crate::spec::{ + Arch, Cc, LinkerFlavor, Lld, LlvmAbi, PanicStrategy, RelocModel, Target, TargetMetadata, + TargetOptions, +}; + +// Bare-metal RV32IMFC for cores that have hardware single-precision float (the `F` +// extension, with the `ilp32f` ABI) but NO atomic ('a') extension. +// This is `riscv32imafc-unknown-none-elf` MINUS the atomic extension, handled the +// same way the in-tree `riscv32imc-unknown-none-elf` handles a no-`a` core: +// `+forced-atomics` makes atomic load/store lower to plain ld/st (sound on a single +// hart) while `atomic_cas = false` keeps RMW/CAS off — downstream crates use a +// critical-section polyfill (e.g. portable-atomic) for those. No lr.w/sc.w/amo* are +// ever emitted, so it does not trap on a core without the A extension. +pub(crate) fn target() -> Target { + Target { + data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(), + llvm_target: "riscv32".into(), + metadata: TargetMetadata { + description: Some( + "Bare RISC-V (RV32IMFC ISA, hardware single-float, no atomics)".into(), + ), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 32, + arch: Arch::RiscV32, + + options: TargetOptions { + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("rust-lld".into()), + cpu: "generic-rv32".into(), + max_atomic_width: Some(32), + atomic_cas: false, + features: "+m,+f,+c,+forced-atomics".into(), + llvm_abiname: LlvmAbi::Ilp32f, + panic_strategy: PanicStrategy::Abort, + relocation_model: RelocModel::Static, + emit_debug_gdb_scripts: false, + eh_frame_header: false, + ..Default::default() + }, + } +} diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 0bc90e2a14008..1014c360f4973 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -397,6 +397,7 @@ target | std | host | notes `riscv32gc-unknown-linux-musl` | ? | | RISC-V Linux (kernel 5.4, musl 1.2.5) [`riscv32im-risc0-zkvm-elf`](platform-support/riscv32im-risc0-zkvm-elf.md) | ? | | RISC Zero's zero-knowledge Virtual Machine (RV32IM ISA) [`riscv32ima-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | | Bare RISC-V (RV32IMA ISA) +[`riscv32imfc-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | | Bare RISC-V (RV32IMFC ISA, hardware single-float, no atomics) [`riscv32imac-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF [`riscv32imac-unknown-nuttx-elf`](platform-support/nuttx.md) | ✓ | | RISC-V 32bit with NuttX [`riscv32imac-unknown-xous-elf`](platform-support/riscv32imac-unknown-xous-elf.md) | ? | | RISC-V Xous (RV32IMAC ISA) diff --git a/src/doc/rustc/src/platform-support/riscv32-unknown-none-elf.md b/src/doc/rustc/src/platform-support/riscv32-unknown-none-elf.md index 38742143c4ba2..f76a981bd281a 100644 --- a/src/doc/rustc/src/platform-support/riscv32-unknown-none-elf.md +++ b/src/doc/rustc/src/platform-support/riscv32-unknown-none-elf.md @@ -1,4 +1,4 @@ -# `riscv32{i,im,ima,imc,imac,imafc}-unknown-none-elf` +# `riscv32{i,im,ima,imc,imfc,imac,imafc}-unknown-none-elf` **Tier: 2** @@ -6,12 +6,25 @@ Bare-metal target for RISC-V CPUs with the RV32I, RV32IM, RV32IMC, RV32IMAFC and **Tier: 3** -Bare-metal target for RISC-V CPUs with the RV32IMA ISA. +Bare-metal target for RISC-V CPUs with the RV32IMA and RV32IMFC ISAs. + +The `riscv32imfc-unknown-none-elf` target covers RV32IMFC cores that have +hardware single-precision floating point (the `F` extension, using the `ilp32f` +ABI) but *no* atomic (`A`) extension. Like `riscv32imc-unknown-none-elf`, it is +built with `+forced-atomics`: atomic loads/stores lower to plain loads/stores +(sound on a single hart) and `lr`/`sc`/`amo*` instructions are never emitted, so +it does not trap on a core without the `A` extension. Compare-and-swap and other +read-modify-write atomics are disabled (`atomic_cas = false`); downstream crates +that need them use a critical-section polyfill (e.g. `portable-atomic`). ## Target maintainers * Rust Embedded Working Group, [RISC-V team](https://github.com/rust-embedded/wg#the-risc-v-team) +The `riscv32imfc-unknown-none-elf` target is additionally maintained by: + +* [@sanchuanhehe](https://github.com/sanchuanhehe) + ## Requirements The target is cross-compiled, and uses static linking. No external toolchain diff --git a/tests/assembly-llvm/targets/targets-elf.rs b/tests/assembly-llvm/targets/targets-elf.rs index 7cc7cb037d4ce..941866b341a79 100644 --- a/tests/assembly-llvm/targets/targets-elf.rs +++ b/tests/assembly-llvm/targets/targets-elf.rs @@ -496,6 +496,9 @@ //@ revisions: riscv32imc_unknown_none_elf //@ [riscv32imc_unknown_none_elf] compile-flags: --target riscv32imc-unknown-none-elf //@ [riscv32imc_unknown_none_elf] needs-llvm-components: riscv +//@ revisions: riscv32imfc_unknown_none_elf +//@ [riscv32imfc_unknown_none_elf] compile-flags: --target riscv32imfc-unknown-none-elf +//@ [riscv32imfc_unknown_none_elf] needs-llvm-components: riscv //@ revisions: riscv64_linux_android //@ [riscv64_linux_android] compile-flags: --target riscv64-linux-android //@ [riscv64_linux_android] needs-llvm-components: riscv