wasmerio/wasmer · critical
unsupported move: {size:?} {source:?} {dest:?}
Error message
unsupported move: {size:?} {source:?} {dest:?} What it means
emit_move_location in the RISC-V singlepass backend panics when it sees a (size, source, dest) combination it cannot move between, i.e. a Location pair not covered by the GPR/SIMD match arms above. This is a codegen completeness gap: the move instruction selector lacks an arm for that operand pairing.
Source
Thrown at lib/compiler-singlepass/src/machine_riscv.rs:2395
let addr = if ImmType::Bits12.compatible_imm(offset as _) {
source
} else {
self.assembler
.emit_mov_imm(Location::GPR(SCRATCH_REG), offset as _)?;
self.assembler.emit_add(
Size::S64,
Location::GPR(addr),
Location::GPR(SCRATCH_REG),
Location::GPR(SCRATCH_REG),
)?;
Location::Memory(SCRATCH_REG, 0)
};
self.assembler.emit_ld(size, false, dest, addr)
}
(Location::GPR(_), Location::SIMD(_)) => self.assembler.emit_mov(size, source, dest),
(Location::SIMD(_), Location::GPR(_)) => self.assembler.emit_mov(size, source, dest),
(Location::SIMD(_), Location::SIMD(_)) => self.assembler.emit_mov(size, source, dest),
_ => todo!("unsupported move: {size:?} {source:?} {dest:?}"),
}
}
fn move_location_extend(
&mut self,
size_val: Size,
signed: bool,
source: Location,
size_op: Size,
dest: Location,
) -> Result<(), CompileError> {
if size_op != Size::S64 {
codegen_error!("singlepass move_location_extend unreachable");
}
let mut temps = vec![];
let dst = self.location_to_reg(size_op, dest, &mut temps, ImmType::None, false, None)?;
let src = match (size_val, signed, source) {
(Size::S64, _, _) => source,View on GitHub (pinned to 8c4b9ee9d3)
Solutions
- Use the cranelift compiler on riscv64 instead of singlepass
- Upgrade wasmer to a build where this match in machine_riscv.rs is complete
- For backend developers: add the missing (source, dest) arm emitting the appropriate RISC-V move sequence
- Report the triggering module/opcode combination upstream
Example fix
// before
_ => todo!("unsupported move: {size:?} {source:?} {dest:?}"),
// after
(Location::Imm(v), Location::GPR(_)) => self.assembler.emit_load_const(size, v, dest),
pair => Err(CompileError::Codegen(format!("unsupported move {pair:?}"))), Defensive patterns
Strategy: fallback
Validate before calling
// select a backend that supports moves on riscv
let cfg: Box<dyn CompilerConfig> = if target_is_riscv() { Box::new(Cranelift::new()) } else { Box::new(Singlepass::new()) }; Type guard
fn move_is_supported(source: &Location, dest: &Location) -> bool {
matches!(source, Location::GPR(_) | Location::SIMD(_)) && matches!(dest, Location::GPR(_) | Location::SIMD(_))
} Prevention
- Avoid singlepass on riscv64; use cranelift
- Run a canary suite of modules covering constant moves and register shuffles before enabling riscv singlepass
- Keep backend match arms exhaustive; replace todo! with CompileError so failures are reportable
- Track upstream RISC-V singlepass milestones before opting in
When it happens
Trigger: Compiling wasm via singlepass on riscv64 when a move is requested with a source/dest pairing outside (GPR,GPR), (GPR,SIMD), (SIMD,GPR), (SIMD,SIMD) — e.g. Immediate/label locations in get_move_location — during any instruction-emitting compile (compile_wasm path).
Common situations: Early/alpha RISC-V singlepass support; modules with constant-heavy or unusual register-assignment patterns hitting the unhandled arm; mixing wasmer versions where the RISC-V backend is still behind x86 completeness.
Related errors
- unsupported location
- not yet implemented
- not yet implemented
- Cannot store reference type
- Symbol {} in DWARF not recognized
AI-assisted analysis of wasmerio/wasmer@8c4b9ee9d3 (2026-09-01).
Data as JSON: /api/errors/78a99f54bd42cc6a.
Report an issue: GitHub.