rust-lang/rust · error

prologue for {:?}

Error message

prologue for {:?}

What it means

Thrown by rustc_codegen_cranelift (the Cranelift backend, a.k.a. cg_clif) when generating the inline-asm prologue that saves the base pointer and callee-saved register before a user asm! block. The match on InlineAsmArch only implements X86_64, AArch64, and RiscV64; every other architecture falls into the `_` arm and panics with unimplemented!("prologue for {:?}", arch). It is a missing-feature panic, not a logic bug.

Source

Thrown at compiler/rustc_codegen_cranelift/src/inline_asm.rs:686

                generated_asm.push_str("    push rbx\n"); // rbx is callee saved
                // rbx is reserved by LLVM for the "base pointer", so rustc doesn't allow using it
                generated_asm.push_str("    mov rbx,rdi\n");
            }
            InlineAsmArch::AArch64 => {
                generated_asm.push_str("    stp fp, lr, [sp, #-32]!\n");
                generated_asm.push_str("    mov fp, sp\n");
                generated_asm.push_str("    str x19, [sp, #24]\n"); // x19 is callee saved
                // x19 is reserved by LLVM for the "base pointer", so rustc doesn't allow using it
                generated_asm.push_str("    mov x19, x0\n");
            }
            InlineAsmArch::RiscV64 => {
                generated_asm.push_str("    addi sp, sp, -16\n");
                generated_asm.push_str("    sd ra, 8(sp)\n");
                generated_asm.push_str("    sd s1, 0(sp)\n"); // s1 is callee saved
                // s1/x9 is reserved by LLVM for the "base pointer", so rustc doesn't allow using it
                generated_asm.push_str("    mv s1, a0\n");
            }
            _ => unimplemented!("prologue for {:?}", arch),
        }
    }

    fn epilogue(generated_asm: &mut String, arch: InlineAsmArch) {
        match arch {
            InlineAsmArch::X86_64 => {
                generated_asm.push_str("    pop rbx\n");
                generated_asm.push_str("    pop rbp\n");
                generated_asm.push_str("    ret\n");
            }
            InlineAsmArch::AArch64 => {
                generated_asm.push_str("    ldr x19, [sp, #24]\n");
                generated_asm.push_str("    ldp fp, lr, [sp], #32\n");
                generated_asm.push_str("    ret\n");
            }
            InlineAsmArch::RiscV64 => {
                generated_asm.push_str("    ld s1, 0(sp)\n");
                generated_asm.push_str("    ld ra, 8(sp)\n");

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Re-run the build with the default LLVM backend: remove -Ccodegen-backend=cranelift / RUSTC_CODEGEN_BACKEND=cranelift from your config and toolchain setup.
  2. If you must use Cranelift, target x86_64, aarch64, or riscv64 (the only arches with inline-asm prologue support implemented in this file).
  3. Eliminate or gate the asm! invocation behind a #[cfg(target_arch = "...")] so it is not codegen'd on the unsupported arch.
  4. Implement the missing arch arm in compiler/rustc_codegen_cranelift/src/inline_asm.rs prologue() (push frame pointer + the LLVM-reserved base register, mirroring the existing arms) and submit a patch upstream.

Example fix

// before
#[cfg(target_arch = "loongarch64")]
unsafe fn read_counter() -> u64 {
    let lo: u64;
    asm!("rdtime {}", out(reg) lo, options(nomem, nostack));
    lo
}

// after - guard so the asm is only compiled on a supported arch
#[cfg(any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "riscv64"))]
unsafe fn read_counter() -> u64 {
    let lo: u64;
    asm!("rdtime {}", out(reg) lo, options(nomem, nostack));
    lo
}
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "riscv64")))]
unsafe fn read_counter() -> u64 { fallback_counter() }
Defensive patterns

Strategy: validation

Validate before calling

// Detect inline asm in source before compiling with cg_clif.
// Run a pre-build scan and abort if `asm!` macros are present.
use std::process::Command;
let out = Command::new("grep").args(["-RnE", r"\basm!\s*\(", "src/"]).output()?;
if !out.stdout.is_empty() {
    eprintln!("cg_clif does not support inline asm prologue; remove asm! or use LLVM backend.");
    std::process::exit(1);
}

Try / catch

// Not catchable at runtime: this is a compiler-process panic (abort).
// Defend at the build-system level: build with default cg_llvm, not cg_clif,
// or gate inline asm behind a cfg that is off for cranelift.
// In build.rs:
fn main() {
    if std::env::var("RUSTC_CODEGEN").as_deref() == Ok("cranelift") {
        println!("cargo:rustc-cfg=no_inline_asm");
    }
}
// then in source: #[cfg(not(no_inline_asm))] { use core::arch::asm; ... }

Prevention

When it happens

Trigger: Compiling code containing asm!(...) with in/out register operands on a target whose InlineAsmArch is not X86_64/AArch64/RiscV64 (e.g. X86, Arm, RiscV32, LoongArch64, PowerPC64, S390x, Mips) while using the Cranelift codegen backend. The panic fires at codegen time, after MIR analysis, when the backend builds the surrounding assembly wrapper for the asm template.

Common situations: Cross-compiling to an uncommon or 32-bit target with cg_clif selected via -Ccodegen-backend=cranelift; nightly Rust with the cranelift component enabled on a tier-2/tier-3 target; crates that use inline asm for low-level CPU feature detection or FFI thunks.

Related errors


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