{"record":{"id":"7e93bbce0f972d4b","repo":"wasmerio/wasmer","slug":"internal-error-entered-unreachable-code-7e93bb","errorCode":null,"errorMessage":"internal error: entered unreachable code","messagePattern":"internal error: entered unreachable code","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/compiler-singlepass/src/emitter_arm64.rs","lineNumber":1197,"sourceCode":"        src1: Location,\n        src2: Location,\n        dst: Location,\n    ) -> Result<(), CompileError> {\n        match (sz, src1, src2, dst) {\n            (Size::S64, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {\n                dynasm!(self ; add XSP(dst), XSP(src1), X(src2), UXTX);\n            }\n            (Size::S32, Location::GPR(src1), Location::GPR(src2), Location::GPR(dst)) => {\n                dynasm!(self ; add WSP(dst), WSP(src1), W(src2), UXTX);\n            }\n            (Size::S64, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst))\n            | (Size::S64, Location::Imm8(imm), Location::GPR(src1), Location::GPR(dst)) => {\n                dynasm!(self ; add XSP(dst), XSP(src1), imm as _);\n            }\n            (Size::S64, Location::GPR(src1), Location::Imm32(imm), Location::GPR(dst))\n            | (Size::S64, Location::Imm32(imm), Location::GPR(src1), Location::GPR(dst)) => {\n                if imm >= 0x1000 {\n                    unreachable!();\n                }\n                dynasm!(self ; add XSP(dst), XSP(src1), imm);\n            }\n            (Size::S64, Location::GPR(src1), Location::Imm64(imm), Location::GPR(dst))\n            | (Size::S64, Location::Imm64(imm), Location::GPR(src1), Location::GPR(dst)) => {\n                if imm >= 0x1000 {\n                    unreachable!();\n                }\n                let imm = imm as u32;\n                dynasm!(self ; add XSP(dst), XSP(src1), imm);\n            }\n            (Size::S32, Location::GPR(src1), Location::Imm8(imm), Location::GPR(dst))\n            | (Size::S32, Location::Imm8(imm), Location::GPR(src1), Location::GPR(dst)) => {\n                dynasm!(self ; add WSP(dst), WSP(src1), imm as u32);\n            }\n            (Size::S32, Location::GPR(src1), Location::Imm32(imm), Location::GPR(dst))\n            | (Size::S32, Location::Imm32(imm), Location::GPR(src1), Location::GPR(dst)) => {\n                if imm >= 0x1000 {","sourceCodeStart":1179,"sourceCodeEnd":1215,"githubUrl":"https://github.com/wasmerio/wasmer/blob/8c4b9ee9d33fb2068863fbb3d328683e7e6ff7f5/lib/compiler-singlepass/src/emitter_arm64.rs#L1179-L1215","documentation":"`emit_add` in singlepass's ARM64 emitter panics with `unreachable!()` when asked to add an `Imm32` immediate of 0x1000 (4096) or larger. ARM64 `add` encoded via this path only supports small immediates; larger constants must be loaded into a register first. The emitter asserts the invariant instead of materializing the constant, so any caller that hands it a big immediate crashes the compiler.","triggerScenarios":"Any singlepass codegen path (stack adjust `emit_pop`, trampolines like `gen_std_trampoline_*`, `gen_import_call_trampoline_*`, dynamic import trampolines) that performs `emit_add` with a GPR destination and an `Imm32` operand >= 0x1000 — e.g. frame/stack adjustments or trampoline offsets larger than 4096 bytes.","commonSituations":"Modules with very large stack frames (big locals/slots) exceeding the 4096-byte immediate window when using `Strategy::Singlepass` on arm64/riscv; deep recursion setups with oversized configured stacks causing large SP adjustments.","solutions":["Upgrade wasmtime — newer singlepass versions split large immediates into register-loaded constants","Reduce the module's stack frame size (fewer/smaller locals, fewer spilled slots)","Lower `StackListing`/slot pressure by splitting the function or reducing inlined code size","Use the Cranelift backend (`Strategy::Cranelift`) which handles large immediates correctly","File an upstream issue with the module; this is a compiler limitation hit at an internal boundary"],"exampleFix":"// before\nconfig.strategy(Strategy::Singlepass);\n// after\nconfig.strategy(Strategy::Cranelift); // handles imm >= 0x1000 in add/sub","handlingStrategy":"validation","validationCode":"// keep frames small enough that SP adjustments stay below the 4096 immediate limit\nconst MAX_FRAME: i64 = 0x1000;\n// estimate from module locals/params before choosing singlepass on arm64\nif estimated_frame_size(bytes) >= MAX_FRAME {\n    config.strategy(wasmtime::Strategy::Cranelift);\n}","typeGuard":"fn imm_fits_encoding(imm: i64) -> bool { (0..0x1000).contains(&imm) }","tryCatchPattern":"let module = std::panic::catch_unwind(|| Module::new(&engine, &bytes).map_err(|e| anyhow::anyhow!(e)))\n    .map_err(|_| anyhow::anyhow!(\"singlepass emit_add immediate panic\"))??; // then retry with Cranelift","preventionTips":["On arm64/riscv targets prefer Cranelift over singlepass for large or generated modules","Upgrade wasmtime before deploying singlepass — large-immediate handling improves over time","Limit function size and local counts when targeting singlepass","Compile off the main thread and catch_unwind so panics are recoverable"],"tags":["wasmtime","singlepass","arm64","code-generation","panic","immediate-overflow"],"backgroundTag":"immediate-out-of-range","analyzedSha":"8c4b9ee9d33fb2068863fbb3d328683e7e6ff7f5","analyzedAt":"2026-09-01T23:06:31.009Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}