cranelift: add i64.[us]{div,rem} libcalls.

These libcalls are useful for 32-bit platforms.
This commit is contained in:
whitequark
2020-05-22 07:32:22 +00:00
parent 26ee986c2f
commit b2e8ed4dc9
5 changed files with 78 additions and 0 deletions

View File

@@ -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,

View 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
}

View File

@@ -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(),

View File

@@ -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,

View File

@@ -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()