cranelift: add i64.[us]{div,rem} libcalls.
These libcalls are useful for 32-bit platforms.
This commit is contained in:
@@ -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<Self, Self::Err> {
|
||||
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<Self> {
|
||||
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,
|
||||
|
||||
31
cranelift/filetests/filetests/wasm/i64-arith32.clif
Normal file
31
cranelift/filetests/filetests/wasm/i64-arith32.clif
Normal file
@@ -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
|
||||
}
|
||||
@@ -179,6 +179,10 @@ where
|
||||
pub fn default_libcall_names() -> Box<dyn Fn(ir::LibCall) -> 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(),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user