rust-lang/rust · error

Architecture {arch} does not support GpuKernel calling conve

Error message

Architecture {arch} does not support GpuKernel calling convention

What it means

`panic!("Architecture {arch} does not support GpuKernel calling convention")` in `to_llvm_calling_convention` for `CanonAbi::GpuKernel`. LLVM only assigns a kernel calling convention for `Arch::AmdGpu` (`llvm::AmdgpuKernel`) and `Arch::Nvptx64` (`llvm::PtxKernel`); any other target arch hits the catch-all and aborts. It fires when source declares `extern "gpu-kernel"` (the kernel ABI used by `rustc`'s GPU targets) but is being compiled for a non-GPU target.

Source

Thrown at compiler/rustc_codegen_llvm/src/abi.rs:740

        CanonAbi::C | CanonAbi::Rust => llvm::CCallConv,
        CanonAbi::RustCold => llvm::PreserveMost,
        CanonAbi::RustPreserveNone => match &sess.target.arch {
            Arch::X86_64 | Arch::AArch64 => llvm::PreserveNone,
            _ => llvm::CCallConv,
        },
        CanonAbi::RustTail => match &sess.target.arch {
            Arch::X86 | Arch::X86_64 | Arch::AArch64 => llvm::Tail,
            _ => sess.dcx().fatal("extern \"tail\" is only supported on x86, x86_64 and aarch64"),
        },
        // Functions with this calling convention can only be called from assembly, but it is
        // possible to declare an `extern "custom"` block, so the backend still needs a calling
        // convention for declaring foreign functions.
        CanonAbi::Custom => llvm::CCallConv,
        CanonAbi::Swift => llvm::SwiftCallConv,
        CanonAbi::GpuKernel => match &sess.target.arch {
            Arch::AmdGpu => llvm::AmdgpuKernel,
            Arch::Nvptx64 => llvm::PtxKernel,
            arch => panic!("Architecture {arch} does not support GpuKernel calling convention"),
        },
        CanonAbi::Interrupt(interrupt_kind) => match interrupt_kind {
            InterruptKind::Avr => llvm::AvrInterrupt,
            InterruptKind::AvrNonBlocking => llvm::AvrNonBlockingInterrupt,
            InterruptKind::Msp430 => llvm::Msp430Intr,
            InterruptKind::RiscvMachine | InterruptKind::RiscvSupervisor => llvm::CCallConv,
            InterruptKind::X86 => llvm::X86_Intr,
        },
        CanonAbi::Arm(arm_call) => match arm_call {
            ArmCall::Aapcs => llvm::ArmAapcsCallConv,
            ArmCall::CCmseNonSecureCall | ArmCall::CCmseNonSecureEntry => llvm::CCallConv,
        },
        CanonAbi::X86(x86_call) => match x86_call {
            X86Call::Fastcall => llvm::X86FastcallCallConv,
            X86Call::Stdcall => llvm::X86StdcallCallConv,
            X86Call::SysV64 => llvm::X86_64_SysV,
            X86Call::Thiscall => llvm::X86_ThisCall,
            X86Call::Vectorcall => llvm::X86_VectorCall,

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Set the target triple to a GPU target: `--target amdgcn-amd-amdhsa` or `--target nvptx64-nvidia-cuda`.
  2. Gate `extern "gpu-kernel"` items behind `#[cfg(target_arch = "amdgpu")]` / `#[cfg(target_arch = "nvptx64")]`.
  3. Split GPU kernel code into a separate crate compiled only for the GPU target; keep host crates free of the ABI.
  4. If using rust-gpu / a build script, ensure it emits the kernel target and does not also build for the host arch.

Example fix

// before
extern "gpu-kernel" fn add(a: f32, b: f32) -> f32 { a + b }

// after — only emit the kernel ABI on GPU targets
#[cfg(any(target_arch = "amdgpu", target_arch = "nvptx64"))]
extern "gpu-kernel" fn add(a: f32, b: f32) -> f32 { a + b }

#[cfg(not(any(target_arch = "amdgpu", target_arch = "nvptx64")))]
compile_error!("`add` is a GPU kernel; compile with a gpu target");
Defensive patterns

Strategy: validation

Validate before calling

// Validate target architecture before using extern "gpu-kernel" ABI
fn supports_gpu_kernel(arch: &str) -> bool {
    matches!(arch, "amdgcn" | "nvptx64")
}

fn validate_gpu_target() -> Result<(), String> {
    let arch = std::env::var("CARGO_CFG_TARGET_ARCH")
        .or_else(|_| std::env::var("TARGET_ARCH"))
        .map_err(|_| "TARGET_ARCH not set")?;
    if !supports_gpu_kernel(&arch) {
        return Err(format!(
            "Architecture '{}' does not support GpuKernel calling convention. \
             Supported: amdgcn, nvptx64. Compile with --target nvptx64-nvidia-cuda \
             or amdgcn-amd-amdhsa.",
            arch
        ));
    }
    Ok(())
}

Prevention

When it happens

Trigger: An `extern "gpu-kernel" fn` (or a crate that exposes one) is compiled with `--target` set to x86_64, aarch64, wasm32, etc. instead of an `amdgcn-*` or `nvptx64-*` target triple. Also triggered by proc-macro/host builds of GPU kernel crates that don't gate the ABI behind `#[cfg(target_arch = "amdgpu" | "nvptx64")]`.

Common situations: Building a GPU crate (e.g. a `rust-gpu`/CUDA/ROCm kernel) without setting the right `--target`; CI building the host crate graph and accidentally compiling GPU-only code; a generic library that re-exports a `gpu-kernel` ABI symbol for all targets.

Related errors


AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03). Data as JSON: /data/errors/1a9d0641084b954a.json. Report an issue: GitHub.