cranelift: Fuzz icmp and fcmp (#4713)
* cranelift: Add `fcmp` to fuzzer * cranelift: Add IntCC::all() * cranelift: Add `icmp` to fuzzer
This commit is contained in:
@@ -100,6 +100,24 @@ impl CondCode for IntCC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl IntCC {
|
impl IntCC {
|
||||||
|
/// Returns a slice with all possible [IntCC] values.
|
||||||
|
pub fn all() -> &'static [IntCC] {
|
||||||
|
&[
|
||||||
|
IntCC::Equal,
|
||||||
|
IntCC::NotEqual,
|
||||||
|
IntCC::SignedLessThan,
|
||||||
|
IntCC::SignedGreaterThanOrEqual,
|
||||||
|
IntCC::SignedGreaterThan,
|
||||||
|
IntCC::SignedLessThanOrEqual,
|
||||||
|
IntCC::UnsignedLessThan,
|
||||||
|
IntCC::UnsignedGreaterThanOrEqual,
|
||||||
|
IntCC::UnsignedGreaterThan,
|
||||||
|
IntCC::UnsignedLessThanOrEqual,
|
||||||
|
IntCC::Overflow,
|
||||||
|
IntCC::NotOverflow,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the corresponding IntCC with the equal component removed.
|
/// Get the corresponding IntCC with the equal component removed.
|
||||||
/// For conditions without a zero component, this is a no-op.
|
/// For conditions without a zero component, this is a no-op.
|
||||||
pub fn without_equal(self) -> Self {
|
pub fn without_equal(self) -> Self {
|
||||||
@@ -227,6 +245,28 @@ pub enum FloatCC {
|
|||||||
UnorderedOrGreaterThanOrEqual,
|
UnorderedOrGreaterThanOrEqual,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FloatCC {
|
||||||
|
/// Returns a slice with all possible [FloatCC] values.
|
||||||
|
pub fn all() -> &'static [FloatCC] {
|
||||||
|
&[
|
||||||
|
FloatCC::Ordered,
|
||||||
|
FloatCC::Unordered,
|
||||||
|
FloatCC::Equal,
|
||||||
|
FloatCC::NotEqual,
|
||||||
|
FloatCC::OrderedNotEqual,
|
||||||
|
FloatCC::UnorderedOrEqual,
|
||||||
|
FloatCC::LessThan,
|
||||||
|
FloatCC::LessThanOrEqual,
|
||||||
|
FloatCC::GreaterThan,
|
||||||
|
FloatCC::GreaterThanOrEqual,
|
||||||
|
FloatCC::UnorderedOrLessThan,
|
||||||
|
FloatCC::UnorderedOrLessThanOrEqual,
|
||||||
|
FloatCC::UnorderedOrGreaterThan,
|
||||||
|
FloatCC::UnorderedOrGreaterThanOrEqual,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl CondCode for FloatCC {
|
impl CondCode for FloatCC {
|
||||||
fn inverse(self) -> Self {
|
fn inverse(self) -> Self {
|
||||||
use self::FloatCC::*;
|
use self::FloatCC::*;
|
||||||
@@ -320,24 +360,9 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use std::string::ToString;
|
use std::string::ToString;
|
||||||
|
|
||||||
static INT_ALL: [IntCC; 12] = [
|
|
||||||
IntCC::Equal,
|
|
||||||
IntCC::NotEqual,
|
|
||||||
IntCC::SignedLessThan,
|
|
||||||
IntCC::SignedGreaterThanOrEqual,
|
|
||||||
IntCC::SignedGreaterThan,
|
|
||||||
IntCC::SignedLessThanOrEqual,
|
|
||||||
IntCC::UnsignedLessThan,
|
|
||||||
IntCC::UnsignedGreaterThanOrEqual,
|
|
||||||
IntCC::UnsignedGreaterThan,
|
|
||||||
IntCC::UnsignedLessThanOrEqual,
|
|
||||||
IntCC::Overflow,
|
|
||||||
IntCC::NotOverflow,
|
|
||||||
];
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn int_inverse() {
|
fn int_inverse() {
|
||||||
for r in &INT_ALL {
|
for r in IntCC::all() {
|
||||||
let cc = *r;
|
let cc = *r;
|
||||||
let inv = cc.inverse();
|
let inv = cc.inverse();
|
||||||
assert!(cc != inv);
|
assert!(cc != inv);
|
||||||
@@ -347,7 +372,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn int_reverse() {
|
fn int_reverse() {
|
||||||
for r in &INT_ALL {
|
for r in IntCC::all() {
|
||||||
let cc = *r;
|
let cc = *r;
|
||||||
let rev = cc.reverse();
|
let rev = cc.reverse();
|
||||||
assert_eq!(rev.reverse(), cc);
|
assert_eq!(rev.reverse(), cc);
|
||||||
@@ -356,33 +381,16 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn int_display() {
|
fn int_display() {
|
||||||
for r in &INT_ALL {
|
for r in IntCC::all() {
|
||||||
let cc = *r;
|
let cc = *r;
|
||||||
assert_eq!(cc.to_string().parse(), Ok(cc));
|
assert_eq!(cc.to_string().parse(), Ok(cc));
|
||||||
}
|
}
|
||||||
assert_eq!("bogus".parse::<IntCC>(), Err(()));
|
assert_eq!("bogus".parse::<IntCC>(), Err(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
static FLOAT_ALL: [FloatCC; 14] = [
|
|
||||||
FloatCC::Ordered,
|
|
||||||
FloatCC::Unordered,
|
|
||||||
FloatCC::Equal,
|
|
||||||
FloatCC::NotEqual,
|
|
||||||
FloatCC::OrderedNotEqual,
|
|
||||||
FloatCC::UnorderedOrEqual,
|
|
||||||
FloatCC::LessThan,
|
|
||||||
FloatCC::LessThanOrEqual,
|
|
||||||
FloatCC::GreaterThan,
|
|
||||||
FloatCC::GreaterThanOrEqual,
|
|
||||||
FloatCC::UnorderedOrLessThan,
|
|
||||||
FloatCC::UnorderedOrLessThanOrEqual,
|
|
||||||
FloatCC::UnorderedOrGreaterThan,
|
|
||||||
FloatCC::UnorderedOrGreaterThanOrEqual,
|
|
||||||
];
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn float_inverse() {
|
fn float_inverse() {
|
||||||
for r in &FLOAT_ALL {
|
for r in FloatCC::all() {
|
||||||
let cc = *r;
|
let cc = *r;
|
||||||
let inv = cc.inverse();
|
let inv = cc.inverse();
|
||||||
assert!(cc != inv);
|
assert!(cc != inv);
|
||||||
@@ -392,7 +400,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn float_reverse() {
|
fn float_reverse() {
|
||||||
for r in &FLOAT_ALL {
|
for r in FloatCC::all() {
|
||||||
let cc = *r;
|
let cc = *r;
|
||||||
let rev = cc.reverse();
|
let rev = cc.reverse();
|
||||||
assert_eq!(rev.reverse(), cc);
|
assert_eq!(rev.reverse(), cc);
|
||||||
@@ -401,7 +409,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn float_display() {
|
fn float_display() {
|
||||||
for r in &FLOAT_ALL {
|
for r in FloatCC::all() {
|
||||||
let cc = *r;
|
let cc = *r;
|
||||||
assert_eq!(cc.to_string().parse(), Ok(cc));
|
assert_eq!(cc.to_string().parse(), Ok(cc));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ use cranelift::codegen::ir::{
|
|||||||
use cranelift::codegen::isa::CallConv;
|
use cranelift::codegen::isa::CallConv;
|
||||||
use cranelift::frontend::{FunctionBuilder, FunctionBuilderContext, Switch, Variable};
|
use cranelift::frontend::{FunctionBuilder, FunctionBuilderContext, Switch, Variable};
|
||||||
use cranelift::prelude::{
|
use cranelift::prelude::{
|
||||||
EntityRef, ExtFuncData, InstBuilder, IntCC, JumpTableData, StackSlotData, StackSlotKind,
|
EntityRef, ExtFuncData, FloatCC, InstBuilder, IntCC, JumpTableData, StackSlotData,
|
||||||
|
StackSlotKind,
|
||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
@@ -110,6 +111,32 @@ fn insert_stack_store(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn insert_cmp(
|
||||||
|
fgen: &mut FunctionGenerator,
|
||||||
|
builder: &mut FunctionBuilder,
|
||||||
|
opcode: Opcode,
|
||||||
|
args: &'static [Type],
|
||||||
|
rets: &'static [Type],
|
||||||
|
) -> Result<()> {
|
||||||
|
let lhs = fgen.get_variable_of_type(args[0])?;
|
||||||
|
let lhs = builder.use_var(lhs);
|
||||||
|
|
||||||
|
let rhs = fgen.get_variable_of_type(args[1])?;
|
||||||
|
let rhs = builder.use_var(rhs);
|
||||||
|
|
||||||
|
let res = if opcode == Opcode::Fcmp {
|
||||||
|
let cc = *fgen.u.choose(FloatCC::all())?;
|
||||||
|
builder.ins().fcmp(cc, lhs, rhs)
|
||||||
|
} else {
|
||||||
|
let cc = *fgen.u.choose(IntCC::all())?;
|
||||||
|
builder.ins().icmp(cc, lhs, rhs)
|
||||||
|
};
|
||||||
|
|
||||||
|
let var = fgen.get_variable_of_type(rets[0])?;
|
||||||
|
builder.def_var(var, res);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn insert_const(
|
fn insert_const(
|
||||||
fgen: &mut FunctionGenerator,
|
fgen: &mut FunctionGenerator,
|
||||||
builder: &mut FunctionBuilder,
|
builder: &mut FunctionBuilder,
|
||||||
@@ -391,6 +418,17 @@ const OPCODE_SIGNATURES: &'static [(
|
|||||||
// Nearest
|
// Nearest
|
||||||
(Opcode::Nearest, &[F32], &[F32], insert_opcode),
|
(Opcode::Nearest, &[F32], &[F32], insert_opcode),
|
||||||
(Opcode::Nearest, &[F64], &[F64], insert_opcode),
|
(Opcode::Nearest, &[F64], &[F64], insert_opcode),
|
||||||
|
// Fcmp
|
||||||
|
(Opcode::Fcmp, &[F32, F32], &[B1], insert_cmp),
|
||||||
|
(Opcode::Fcmp, &[F64, F64], &[B1], insert_cmp),
|
||||||
|
// Icmp
|
||||||
|
(Opcode::Icmp, &[I8, I8], &[B1], insert_cmp),
|
||||||
|
(Opcode::Icmp, &[I16, I16], &[B1], insert_cmp),
|
||||||
|
(Opcode::Icmp, &[I32, I32], &[B1], insert_cmp),
|
||||||
|
(Opcode::Icmp, &[I64, I64], &[B1], insert_cmp),
|
||||||
|
// TODO: icmp of/nof broken for i128 on x86_64
|
||||||
|
// See: https://github.com/bytecodealliance/wasmtime/issues/4406
|
||||||
|
// (Opcode::Icmp, &[I128, I128], &[B1], insert_cmp),
|
||||||
// Stack Access
|
// Stack Access
|
||||||
(Opcode::StackStore, &[I8], &[], insert_stack_store),
|
(Opcode::StackStore, &[I8], &[], insert_stack_store),
|
||||||
(Opcode::StackStore, &[I16], &[], insert_stack_store),
|
(Opcode::StackStore, &[I16], &[], insert_stack_store),
|
||||||
@@ -458,25 +496,6 @@ where
|
|||||||
Ok(CallConv::SystemV)
|
Ok(CallConv::SystemV)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_intcc(&mut self) -> Result<IntCC> {
|
|
||||||
Ok(*self.u.choose(
|
|
||||||
&[
|
|
||||||
IntCC::Equal,
|
|
||||||
IntCC::NotEqual,
|
|
||||||
IntCC::SignedLessThan,
|
|
||||||
IntCC::SignedGreaterThanOrEqual,
|
|
||||||
IntCC::SignedGreaterThan,
|
|
||||||
IntCC::SignedLessThanOrEqual,
|
|
||||||
IntCC::UnsignedLessThan,
|
|
||||||
IntCC::UnsignedGreaterThanOrEqual,
|
|
||||||
IntCC::UnsignedGreaterThan,
|
|
||||||
IntCC::UnsignedLessThanOrEqual,
|
|
||||||
IntCC::Overflow,
|
|
||||||
IntCC::NotOverflow,
|
|
||||||
][..],
|
|
||||||
)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate_type(&mut self) -> Result<Type> {
|
fn generate_type(&mut self) -> Result<Type> {
|
||||||
// TODO: It would be nice if we could get these directly from cranelift
|
// TODO: It would be nice if we could get these directly from cranelift
|
||||||
let scalars = [
|
let scalars = [
|
||||||
@@ -681,7 +700,7 @@ where
|
|||||||
|
|
||||||
fn generate_bricmp(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
|
fn generate_bricmp(&mut self, builder: &mut FunctionBuilder) -> Result<()> {
|
||||||
let (block, args) = self.generate_target_block(builder)?;
|
let (block, args) = self.generate_target_block(builder)?;
|
||||||
let cond = self.generate_intcc()?;
|
let cond = *self.u.choose(IntCC::all())?;
|
||||||
|
|
||||||
let bricmp_types = [
|
let bricmp_types = [
|
||||||
I8, I16, I32,
|
I8, I16, I32,
|
||||||
|
|||||||
Reference in New Issue
Block a user