diff --git a/cranelift/codegen/src/ir/libcall.rs b/cranelift/codegen/src/ir/libcall.rs index f4f6d941f8..6f816f4f57 100644 --- a/cranelift/codegen/src/ir/libcall.rs +++ b/cranelift/codegen/src/ir/libcall.rs @@ -24,6 +24,14 @@ pub enum LibCall { /// probe for stack overflow. These are emitted for functions which need /// when the `enable_probestack` setting is true. Probestack, + /// udiv.i64 + UdivI64, + /// sdiv.i64 + SdivI64, + /// urem.i64 + UremI64, + /// srem.i64 + SremI64, /// ceil.f32 CeilF32, /// ceil.f64 @@ -63,6 +71,10 @@ impl FromStr for LibCall { fn from_str(s: &str) -> Result { match s { "Probestack" => Ok(Self::Probestack), + "UdivI64" => Ok(Self::UdivI64), + "SdivI64" => Ok(Self::SdivI64), + "UremI64" => Ok(Self::UremI64), + "SremI64" => Ok(Self::SremI64), "CeilF32" => Ok(Self::CeilF32), "CeilF64" => Ok(Self::CeilF64), "FloorF32" => Ok(Self::FloorF32), @@ -88,6 +100,13 @@ impl LibCall { /// Returns `None` if no well-known library routine name exists for that instruction. pub fn for_inst(opcode: Opcode, ctrl_type: Type) -> Option { Some(match ctrl_type { + types::I64 => match opcode { + Opcode::Udiv => Self::UdivI64, + Opcode::Sdiv => Self::SdivI64, + Opcode::Urem => Self::UremI64, + Opcode::Srem => Self::SremI64, + _ => return None, + }, types::F32 => match opcode { Opcode::Ceil => Self::CeilF32, Opcode::Floor => Self::FloorF32, diff --git a/cranelift/filetests/filetests/wasm/i64-arith32.clif b/cranelift/filetests/filetests/wasm/i64-arith32.clif new file mode 100644 index 0000000000..d3017c23e6 --- /dev/null +++ b/cranelift/filetests/filetests/wasm/i64-arith32.clif @@ -0,0 +1,31 @@ +; Test basic code generation for i64 arithmetic WebAssembly instructions +; on 32-bit platforms. +test compile + +target i686 baseline + +; Binary operations. + +function %i64_div_s(i64, i64) -> i64 { +block0(v0: i64, v1: i64): + v2 = sdiv v0, v1 + return v2 +} + +function %i64_div_u(i64, i64) -> i64 { +block0(v0: i64, v1: i64): + v2 = udiv v0, v1 + return v2 +} + +function %i64_rem_s(i64, i64) -> i64 { +block0(v0: i64, v1: i64): + v2 = srem v0, v1 + return v2 +} + +function %i64_rem_u(i64, i64) -> i64 { +block0(v0: i64, v1: i64): + v2 = urem v0, v1 + return v2 +} diff --git a/cranelift/module/src/backend.rs b/cranelift/module/src/backend.rs index 4616791e92..205d759c5e 100644 --- a/cranelift/module/src/backend.rs +++ b/cranelift/module/src/backend.rs @@ -179,6 +179,10 @@ where pub fn default_libcall_names() -> Box String> { Box::new(move |libcall| match libcall { ir::LibCall::Probestack => "__cranelift_probestack".to_owned(), + ir::LibCall::UdivI64 => "__udivdi3".to_owned(), + ir::LibCall::SdivI64 => "__divdi3".to_owned(), + ir::LibCall::UremI64 => "__umoddi3".to_owned(), + ir::LibCall::SremI64 => "__moddi3".to_owned(), ir::LibCall::CeilF32 => "ceilf".to_owned(), ir::LibCall::CeilF64 => "ceil".to_owned(), ir::LibCall::FloorF32 => "floorf".to_owned(), diff --git a/crates/jit/src/link.rs b/crates/jit/src/link.rs index 6918b2d4b3..26a9a8833c 100644 --- a/crates/jit/src/link.rs +++ b/crates/jit/src/link.rs @@ -46,6 +46,10 @@ fn apply_reloc( RelocationTarget::LibCall(libcall) => { use cranelift_codegen::ir::LibCall::*; match libcall { + UdivI64 => wasmtime_i64_udiv as usize, + SdivI64 => wasmtime_i64_sdiv as usize, + UremI64 => wasmtime_i64_urem as usize, + SremI64 => wasmtime_i64_srem as usize, CeilF32 => wasmtime_f32_ceil as usize, FloorF32 => wasmtime_f32_floor as usize, TruncF32 => wasmtime_f32_trunc as usize, diff --git a/crates/runtime/src/libcalls.rs b/crates/runtime/src/libcalls.rs index 826e42f9c2..f651dc0d14 100644 --- a/crates/runtime/src/libcalls.rs +++ b/crates/runtime/src/libcalls.rs @@ -78,6 +78,26 @@ pub extern "C" fn wasmtime_f32_nearest(x: f32) -> f32 { } } +/// Implementation of i64.udiv +pub extern "C" fn wasmtime_i64_udiv(x: u64, y: u64) -> u64 { + x / y +} + +/// Implementation of i64.sdiv +pub extern "C" fn wasmtime_i64_sdiv(x: i64, y: i64) -> i64 { + x / y +} + +/// Implementation of i64.urem +pub extern "C" fn wasmtime_i64_urem(x: u64, y: u64) -> u64 { + x % y +} + +/// Implementation of i64.srem +pub extern "C" fn wasmtime_i64_srem(x: i64, y: i64) -> i64 { + x % y +} + /// Implementation of f64.ceil pub extern "C" fn wasmtime_f64_ceil(x: f64) -> f64 { x.ceil()