{"record":{"id":"dce14c93019b864f","repo":"rust-lang/rust","slug":"cannot-allocate-registers","errorCode":null,"errorMessage":"cannot allocate registers","messagePattern":"cannot allocate registers","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/rustc_codegen_cranelift/src/inline_asm.rs","lineNumber":321,"sourceCode":"                | CInlineAsmOperand::InOut {\n                    reg: InlineAsmRegOrRegClass::RegClass(class), ..\n                } => {\n                    let mut alloc_reg = None;\n                    for &reg in &map[&class] {\n                        let mut used = false;\n                        reg.overlapping_regs(|r| {\n                            if allocated.contains_key(&r) {\n                                used = true;\n                            }\n                        });\n\n                        if !used {\n                            alloc_reg = Some(reg);\n                            break;\n                        }\n                    }\n\n                    let reg = alloc_reg.expect(\"cannot allocate registers\");\n                    regs[i] = Some(reg);\n                    allocated.insert(reg, (true, true));\n                }\n                _ => (),\n            }\n        }\n\n        // Allocate in/lateout.\n        for (i, operand) in self.operands.iter().enumerate() {\n            match *operand {\n                CInlineAsmOperand::In { reg: InlineAsmRegOrRegClass::RegClass(class), .. } => {\n                    let mut alloc_reg = None;\n                    for &reg in &map[&class] {\n                        let mut used = false;\n                        reg.overlapping_regs(|r| {\n                            if allocated.get(&r).copied().unwrap_or_default().0 {\n                                used = true;\n                            }","sourceCodeStart":303,"sourceCodeEnd":339,"githubUrl":"https://github.com/rust-lang/rust/blob/7088e4b63a9516ebfbfe2ab2d999cf01a528ac14/compiler/rustc_codegen_cranelift/src/inline_asm.rs#L303-L339","documentation":"This fires in Cranelift codegen's inline assembly register allocator. When processing `out`/`inout` operands with register-class constraints (e.g., `{reg}` for a register class like `reg` on x86), the code iterates all available registers in the class and checks for overlap with already-allocated registers. If every register in the class is already taken, `alloc_reg` stays `None` and `.expect(\"cannot allocate registers\")` panics. This means the inline asm has more register-class operands than the target architecture has physical registers.","triggerScenarios":"Using `asm!` with more register-class-constrained operands (e.g., `out(\"reg\")`, `in(\"reg\")`) than the target has available registers. For example, on x86-64, requesting more than ~14 general-purpose registers in a single `asm!` block via `in(reg)` / `out(reg)` operands. On register-poor targets like x86 (32-bit) or certain RISC-V configurations, the limit is even lower.","commonSituations":"Inline assembly blocks with many in/out register operands, especially on 32-bit x86 (only 6-8 general registers) or when many operands use the unconstrained `reg` class. Also triggered by register-pressure-heavy code surrounding the asm block that spills into the allocator. Unlike the LLVM backend which reports a graceful error, cg_clif panics.","solutions":["Reduce the number of register-class operands in the `asm!` block — reuse registers with `inlateout` where possible.","Use specific named registers (e.g., `out(\"rax\")`) for operands where the specific register is known.","Move some operands to memory: load/store around the asm block instead of using registers.","Use the LLVM backend (`-Zcodegen-backend=llvm`) which reports this as a proper error rather than an ICE.","Split the asm block into multiple smaller blocks to reduce per-block register pressure."],"exampleFix":"// before (too many reg-class operands on x86-32 → register exhaustion → panic)\nunsafe {\n    asm!(\n        \"\",\n        out(\"reg\") a, out(\"reg\") b, out(\"reg\") c,\n        out(\"reg\") d, out(\"reg\") e, out(\"reg\") f,\n        out(\"reg\") g, out(\"reg\") h,  // too many!\n    );\n}\n\n// after (use inlateout to reuse registers, or spill to memory)\nunsafe {\n    asm!(\"\", inlateout(\"reg\") a, inlateout(\"reg\") b);\n    asm!(\"\", inlateout(\"reg\") c, inlateout(\"reg\") d);\n    // fewer regs per block\n}","handlingStrategy":"validation","validationCode":"// Before using asm! with many reg-class operands, count them:\n// (Manual check) Count in(reg)/out(reg)/inout(reg) operands.\n// On x86-64: keep total reg-class operands under ~12.\n// On x86-32: keep under ~5.\n// In build.rs, warn if compiling inline asm for register-poor targets:\n// if cfg!(target_arch = \"x86\") {\n//     println!(\"cargo:warning=x86 has few GP registers; limit asm! reg operands\");\n// }","typeGuard":"// No language-level guard for register count, but a documentation comment\n// and lint can help:\n// SAFETY: This asm block uses N reg-class operands. Maximum for x86-64 is ~12.\n// If N exceeds the target limit, cg_clif panics with 'cannot allocate registers'.\n// Use inlateout to reuse registers, or named registers for specific ones.","tryCatchPattern":null,"preventionTips":["Count register-class operands in each asm! block; keep below target limits.","Use inlateout(reg) to reuse the same register for input and output.","Use specific named registers (out(\"rax\")) to reduce class-based allocation pressure.","Split large asm blocks into multiple smaller ones.","Use the LLVM backend for asm-heavy code — it reports register exhaustion as an error, not an ICE."],"tags":["rustc","cranelift","codegen","inline-asm","register-allocation","x86","cg-clif"],"backgroundTag":null,"analyzedSha":"7088e4b63a9516ebfbfe2ab2d999cf01a528ac14","analyzedAt":"2026-08-10T14:17:03.603Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}