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
|
/// probe for stack overflow. These are emitted for functions which need
|
||||||
/// when the `enable_probestack` setting is true.
|
/// when the `enable_probestack` setting is true.
|
||||||
Probestack,
|
Probestack,
|
||||||
|
/// udiv.i64
|
||||||
|
UdivI64,
|
||||||
|
/// sdiv.i64
|
||||||
|
SdivI64,
|
||||||
|
/// urem.i64
|
||||||
|
UremI64,
|
||||||
|
/// srem.i64
|
||||||
|
SremI64,
|
||||||
/// ceil.f32
|
/// ceil.f32
|
||||||
CeilF32,
|
CeilF32,
|
||||||
/// ceil.f64
|
/// ceil.f64
|
||||||
@@ -63,6 +71,10 @@ impl FromStr for LibCall {
|
|||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
match s {
|
match s {
|
||||||
"Probestack" => Ok(Self::Probestack),
|
"Probestack" => Ok(Self::Probestack),
|
||||||
|
"UdivI64" => Ok(Self::UdivI64),
|
||||||
|
"SdivI64" => Ok(Self::SdivI64),
|
||||||
|
"UremI64" => Ok(Self::UremI64),
|
||||||
|
"SremI64" => Ok(Self::SremI64),
|
||||||
"CeilF32" => Ok(Self::CeilF32),
|
"CeilF32" => Ok(Self::CeilF32),
|
||||||
"CeilF64" => Ok(Self::CeilF64),
|
"CeilF64" => Ok(Self::CeilF64),
|
||||||
"FloorF32" => Ok(Self::FloorF32),
|
"FloorF32" => Ok(Self::FloorF32),
|
||||||
@@ -88,6 +100,13 @@ impl LibCall {
|
|||||||
/// Returns `None` if no well-known library routine name exists for that instruction.
|
/// Returns `None` if no well-known library routine name exists for that instruction.
|
||||||
pub fn for_inst(opcode: Opcode, ctrl_type: Type) -> Option<Self> {
|
pub fn for_inst(opcode: Opcode, ctrl_type: Type) -> Option<Self> {
|
||||||
Some(match ctrl_type {
|
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 {
|
types::F32 => match opcode {
|
||||||
Opcode::Ceil => Self::CeilF32,
|
Opcode::Ceil => Self::CeilF32,
|
||||||
Opcode::Floor => Self::FloorF32,
|
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> {
|
pub fn default_libcall_names() -> Box<dyn Fn(ir::LibCall) -> String> {
|
||||||
Box::new(move |libcall| match libcall {
|
Box::new(move |libcall| match libcall {
|
||||||
ir::LibCall::Probestack => "__cranelift_probestack".to_owned(),
|
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::CeilF32 => "ceilf".to_owned(),
|
||||||
ir::LibCall::CeilF64 => "ceil".to_owned(),
|
ir::LibCall::CeilF64 => "ceil".to_owned(),
|
||||||
ir::LibCall::FloorF32 => "floorf".to_owned(),
|
ir::LibCall::FloorF32 => "floorf".to_owned(),
|
||||||
|
|||||||
@@ -46,6 +46,10 @@ fn apply_reloc(
|
|||||||
RelocationTarget::LibCall(libcall) => {
|
RelocationTarget::LibCall(libcall) => {
|
||||||
use cranelift_codegen::ir::LibCall::*;
|
use cranelift_codegen::ir::LibCall::*;
|
||||||
match 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,
|
CeilF32 => wasmtime_f32_ceil as usize,
|
||||||
FloorF32 => wasmtime_f32_floor as usize,
|
FloorF32 => wasmtime_f32_floor as usize,
|
||||||
TruncF32 => wasmtime_f32_trunc 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
|
/// Implementation of f64.ceil
|
||||||
pub extern "C" fn wasmtime_f64_ceil(x: f64) -> f64 {
|
pub extern "C" fn wasmtime_f64_ceil(x: f64) -> f64 {
|
||||||
x.ceil()
|
x.ceil()
|
||||||
|
|||||||
Reference in New Issue
Block a user