Add amdgpu target

Add target and compile the amdgpu llvm backend.
This commit is contained in:
Flakebi 2025-01-02 15:19:43 +01:00
parent a730edcd67
commit 56795fb77a
No known key found for this signature in database
GPG key ID: 38E7ED984D7DCD02
16 changed files with 220 additions and 10 deletions

View file

@ -1908,6 +1908,8 @@ supported_targets! {
("nvptx64-nvidia-cuda", nvptx64_nvidia_cuda),
("amdgcn-amd-amdhsa", amdgcn_amd_amdhsa),
("xtensa-esp32-none-elf", xtensa_esp32_none_elf),
("xtensa-esp32-espidf", xtensa_esp32_espidf),
("xtensa-esp32s2-none-elf", xtensa_esp32s2_none_elf),

View file

@ -0,0 +1,51 @@
use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, Target, TargetOptions};
pub(crate) fn target() -> Target {
Target {
arch: "amdgpu".into(),
data_layout: "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9".into(),
llvm_target: "amdgcn-amd-amdhsa".into(),
metadata: crate::spec::TargetMetadata {
description: Some("AMD GPU".into()),
tier: Some(3),
host_tools: Some(false),
std: Some(false),
},
pointer_width: 64,
options: TargetOptions {
os: "amdhsa".into(),
vendor: "amd".into(),
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
// There are many CPUs, one for each hardware generation.
// Require to set one explicitly as there is no good default.
need_explicit_cpu: true,
max_atomic_width: Some(64),
// Unwinding on GPUs is not useful.
panic_strategy: PanicStrategy::Abort,
// amdgpu backend does not support libcalls.
no_builtins: true,
simd_types_indirect: false,
// Allow `cdylib` crate type.
dynamic_linking: true,
only_cdylib: true,
executables: false,
dll_prefix: "".into(),
dll_suffix: ".elf".into(),
// The LLVM backend does not support stack canaries for this target
supports_stack_protector: false,
// Force LTO, object linking does not yet work with amdgpu.
requires_lto: true,
..Default::default()
},
}
}

View file

@ -108,7 +108,7 @@
# the resulting rustc being unable to compile for the disabled architectures.
#
# To add support for new targets, see https://rustc-dev-guide.rust-lang.org/building/new-target.html.
#targets = "AArch64;ARM;BPF;Hexagon;LoongArch;MSP430;Mips;NVPTX;PowerPC;RISCV;Sparc;SystemZ;WebAssembly;X86"
#targets = "AArch64;AMDGPU;ARM;BPF;Hexagon;LoongArch;MSP430;Mips;NVPTX;PowerPC;RISCV;Sparc;SystemZ;WebAssembly;X86"
# LLVM experimental targets to build support for. These targets are specified in
# the same format as above, but since these targets are experimental, they are

View file

@ -1,4 +1,4 @@
Change this file to make users of the `download-ci-llvm` configuration download
a new version of LLVM from CI, even if the LLVM submodule hasnt changed.
Last change is for: https://github.com/rust-lang/rust/pull/129788
Last change is for: https://github.com/rust-lang/rust/pull/134740

View file

@ -331,7 +331,7 @@ impl Step for Llvm {
let llvm_targets = match &builder.config.llvm_targets {
Some(s) => s,
None => {
"AArch64;ARM;BPF;Hexagon;LoongArch;MSP430;Mips;NVPTX;PowerPC;RISCV;\
"AArch64;AMDGPU;ARM;BPF;Hexagon;LoongArch;MSP430;Mips;NVPTX;PowerPC;RISCV;\
Sparc;SystemZ;WebAssembly;X86"
}
};

View file

@ -29,6 +29,7 @@
- [\*-apple-watchos](platform-support/apple-watchos.md)
- [\*-apple-visionos](platform-support/apple-visionos.md)
- [aarch64-nintendo-switch-freestanding](platform-support/aarch64-nintendo-switch-freestanding.md)
- [amdgcn-amd-amdhsa](platform-support/amdgcn-amd-amdhsa.md)
- [armeb-unknown-linux-gnueabi](platform-support/armeb-unknown-linux-gnueabi.md)
- [arm-none-eabi](platform-support/arm-none-eabi.md)
- [armv4t-none-eabi](platform-support/armv4t-none-eabi.md)

View file

@ -272,6 +272,7 @@ target | std | host | notes
`aarch64_be-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (big-endian)
`aarch64_be-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (big-endian, ILP32 ABI)
[`aarch64_be-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD (big-endian)
[`amdgcn-amd-amdhsa`](platform-support/amdgcn-amd-amdhsa.md) | * | | `-Ctarget-cpu=gfx...` to specify [the AMD GPU] to compile for
[`arm64_32-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | Arm Apple WatchOS 64-bit with 32-bit pointers
[`arm64e-apple-darwin`](platform-support/arm64e-apple-darwin.md) | ✓ | ✓ | ARM64e Apple Darwin
[`arm64e-apple-ios`](platform-support/arm64e-apple-ios.md) | ✓ | | ARM64e Apple iOS
@ -432,3 +433,4 @@ target | std | host | notes
[`xtensa-esp32s3-none-elf`](platform-support/xtensa.md) | * | | Xtensa ESP32-S3
[runs on NVIDIA GPUs]: https://github.com/japaric-archived/nvptx#targets
[the AMD GPU]: https://llvm.org/docs/AMDGPUUsage.html#processors

View file

@ -0,0 +1,111 @@
# `amdgcn-amd-amdhsa`
**Tier: 3**
AMD GPU target for compute/HSA (Heterogeneous System Architecture).
## Target maintainers
- [@Flakebi](https://github.com/Flakebi)
## Requirements
AMD GPUs can be targeted via cross-compilation.
Supported GPUs depend on the LLVM version that is used by Rust.
In general, most GPUs starting from gfx7 (Sea Islands/CI) are supported as compilation targets, though older GPUs are not supported by the latest host runtime.
Details about supported GPUs can be found in [LLVMs documentation] and [ROCm documentation].
Binaries can be loaded by [HIP] or by the HSA runtime implemented in [ROCR-Runtime].
The format of binaries is a linked ELF.
Binaries must be built with no-std.
They can use `core` and `alloc` (`alloc` only if an allocator is supplied).
At least one function needs to use the `"gpu-kernel"` calling convention and should be marked with `no_mangle` for simplicity.
Functions using the `"gpu-kernel"` calling convention are kernel entrypoints and can be used from the host runtime.
## Building the target
The target is included in rustc.
## Building Rust programs
The amdgpu target supports many hardware generations, which need different binaries.
The generations are exposed as different target-cpus in the backend.
As there are many, Rust does not ship pre-compiled libraries for this target.
Therefore, you have to build your own copy of `core` by using `cargo -Zbuild-std=core` or similar.
To build a binary, create a no-std library:
```rust,ignore (platform-specific)
// src/lib.rs
#![feature(abi_gpu_kernel)]
#![no_std]
#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! {
loop {}
}
#[no_mangle]
pub extern "gpu-kernel" fn kernel(/* Arguments */) {
// Code
}
```
Build the library as `cdylib`:
```toml
# Cargo.toml
[lib]
crate-type = ["cdylib"]
[profile.dev]
lto = true # LTO must be explicitly enabled for now
[profile.release]
lto = true
```
The target-cpu must be from the list [supported by LLVM] (or printed with `rustc --target amdgcn-amd-amdhsa --print target-cpus`).
The GPU version on the current system can be found e.g. with [`rocminfo`].
Example `.cargo/config.toml` file to set the target and GPU generation:
```toml
# .cargo/config.toml
[build]
target = "amdgcn-amd-amdhsa"
rustflags = ["-Ctarget-cpu=gfx1100"]
[unstable]
build-std = ["core"] # Optional: "alloc"
```
## Running Rust programs
To run a binary on an AMD GPU, a host runtime is needed.
On Linux and Windows, [HIP] can be used to load and run binaries.
Example code on how to load a compiled binary and run it is available in [ROCm examples].
On Linux, binaries can also run through the HSA runtime as implemented in [ROCR-Runtime].
<!-- Mention an allocator once a suitable one exists for amdgpu -->
<!--
## Testing
Does the target support running binaries, or do binaries have varying
expectations that prevent having a standard way to run them? If users can run
binaries, can they do so in some common emulator, or do they need native
hardware? Does the target support running the Rust testsuite?
-->
## Additional information
More information can be found on the [LLVM page for amdgpu].
[LLVMs documentation]: https://llvm.org/docs/AMDGPUUsage.html#processors
[ROCm documentation]: https://rocmdocs.amd.com
[HIP]: https://rocm.docs.amd.com/projects/HIP/
[ROCR-Runtime]: https://github.com/ROCm/ROCR-Runtime
[supported by LLVM]: https://llvm.org/docs/AMDGPUUsage.html#processors
[LLVM page for amdgpu]: https://llvm.org/docs/AMDGPUUsage.html
[`rocminfo`]: https://github.com/ROCm/rocminfo
[ROCm examples]: https://github.com/ROCm/rocm-examples/tree/ca8ef5b6f1390176616cd1c18fbc98785cbc73f6/HIP-Basic/module_api

View file

@ -67,6 +67,7 @@ static TARGETS: &[&str] = &[
"aarch64-unknown-none-softfloat",
"aarch64-unknown-redox",
"aarch64-unknown-uefi",
"amdgcn-amd-amdhsa",
"arm64e-apple-darwin",
"arm64e-apple-ios",
"arm64e-apple-tvos",

View file

@ -0,0 +1,21 @@
//@ assembly-output: emit-asm
// ignore-tidy-linelength
//@ revisions: amdgcn_amd_amdhsa
//@ [amdgcn_amd_amdhsa] compile-flags: --target amdgcn-amd-amdhsa -Ctarget-cpu=gfx900
//@ [amdgcn_amd_amdhsa] needs-llvm-components: amdgpu
// Sanity-check that each target can produce assembly code.
#![feature(no_core, lang_items)]
#![no_std]
#![no_core]
#![crate_type = "lib"]
#[lang = "sized"]
trait Sized {}
pub fn test() -> u8 {
42
}
// CHECK: .version

View file

@ -0,0 +1,4 @@
error: target requires explicitly specifying a cpu with `-C target-cpu`
error: aborting due to 1 previous error

View file

@ -0,0 +1,17 @@
//@ revisions: nocpu cpu
//@ no-prefer-dynamic
//@ compile-flags: --crate-type=cdylib --target=amdgcn-amd-amdhsa
//@ needs-llvm-components: amdgpu
//@ needs-rust-lld
//@[nocpu] error-pattern: target requires explicitly specifying a cpu
//@[nocpu] build-fail
//@[cpu] compile-flags: -Ctarget-cpu=gfx900
//@[cpu] build-pass
#![feature(no_core, lang_items)]
#![no_core]
#[lang="sized"]
trait Sized {}
pub fn foo() {}

View file

@ -14,7 +14,7 @@ warning: unexpected `cfg` condition value: `value`
LL | #[cfg(target_vendor = "value")]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: expected values for `target_vendor` are: `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
= note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: unexpected `cfg` condition name: `feature`

View file

@ -15,7 +15,7 @@ warning: unexpected `cfg` condition value: `value`
LL | #[cfg(target_vendor = "value")]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: expected values for `target_vendor` are: `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
= note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: unexpected `cfg` condition value: `unk`

View file

@ -15,7 +15,7 @@ warning: unexpected `cfg` condition value: `value`
LL | #[cfg(target_vendor = "value")]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: expected values for `target_vendor` are: `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
= note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: unexpected `cfg` condition value: `unk`

View file

@ -138,7 +138,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
LL | target_arch = "_UNEXPECTED_VALUE",
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: expected values for `target_arch` are: `aarch64`, `arm`, `arm64ec`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64`, and `xtensa`
= note: expected values for `target_arch` are: `aarch64`, `amdgpu`, `arm`, `arm64ec`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64`, and `xtensa`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@ -201,7 +201,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
LL | target_os = "_UNEXPECTED_VALUE",
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
= note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@ -230,7 +230,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
LL | target_vendor = "_UNEXPECTED_VALUE",
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: expected values for `target_vendor` are: `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
= note: expected values for `target_vendor` are: `amd`, `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `mti`, `nintendo`, `nvidia`, `pc`, `risc0`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, and `wrs`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
@ -274,7 +274,7 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux`
| |
| help: there is a expected value with a similar name: `"linux"`
|
= note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
= note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: 28 warnings emitted