diff --git a/cranelift/codegen/src/ir/condcodes.rs b/cranelift/codegen/src/ir/condcodes.rs index 00e9717ca0f8..8954867a4896 100644 --- a/cranelift/codegen/src/ir/condcodes.rs +++ b/cranelift/codegen/src/ir/condcodes.rs @@ -100,6 +100,24 @@ impl CondCode for 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. /// For conditions without a zero component, this is a no-op. pub fn without_equal(self) -> Self { @@ -227,6 +245,28 @@ pub enum FloatCC { 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 { fn inverse(self) -> Self { use self::FloatCC::*; @@ -320,24 +360,9 @@ mod tests { use super::*; 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] fn int_inverse() { - for r in &INT_ALL { + for r in IntCC::all() { let cc = *r; let inv = cc.inverse(); assert!(cc != inv); @@ -347,7 +372,7 @@ mod tests { #[test] fn int_reverse() { - for r in &INT_ALL { + for r in IntCC::all() { let cc = *r; let rev = cc.reverse(); assert_eq!(rev.reverse(), cc); @@ -356,33 +381,16 @@ mod tests { #[test] fn int_display() { - for r in &INT_ALL { + for r in IntCC::all() { let cc = *r; assert_eq!(cc.to_string().parse(), Ok(cc)); } assert_eq!("bogus".parse::(), 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] fn float_inverse() { - for r in &FLOAT_ALL { + for r in FloatCC::all() { let cc = *r; let inv = cc.inverse(); assert!(cc != inv); @@ -392,7 +400,7 @@ mod tests { #[test] fn float_reverse() { - for r in &FLOAT_ALL { + for r in FloatCC::all() { let cc = *r; let rev = cc.reverse(); assert_eq!(rev.reverse(), cc); @@ -401,7 +409,7 @@ mod tests { #[test] fn float_display() { - for r in &FLOAT_ALL { + for r in FloatCC::all() { let cc = *r; assert_eq!(cc.to_string().parse(), Ok(cc)); } diff --git a/cranelift/fuzzgen/src/function_generator.rs b/cranelift/fuzzgen/src/function_generator.rs index 17614cb1d89b..c15a496fc007 100644 --- a/cranelift/fuzzgen/src/function_generator.rs +++ b/cranelift/fuzzgen/src/function_generator.rs @@ -9,7 +9,8 @@ use cranelift::codegen::ir::{ use cranelift::codegen::isa::CallConv; use cranelift::frontend::{FunctionBuilder, FunctionBuilderContext, Switch, Variable}; use cranelift::prelude::{ - EntityRef, ExtFuncData, InstBuilder, IntCC, JumpTableData, StackSlotData, StackSlotKind, + EntityRef, ExtFuncData, FloatCC, InstBuilder, IntCC, JumpTableData, StackSlotData, + StackSlotKind, }; use std::collections::HashMap; use std::ops::RangeInclusive; @@ -110,6 +111,32 @@ fn insert_stack_store( 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( fgen: &mut FunctionGenerator, builder: &mut FunctionBuilder, @@ -391,6 +418,17 @@ const OPCODE_SIGNATURES: &'static [( // Nearest (Opcode::Nearest, &[F32], &[F32], 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 (Opcode::StackStore, &[I8], &[], insert_stack_store), (Opcode::StackStore, &[I16], &[], insert_stack_store), @@ -458,25 +496,6 @@ where Ok(CallConv::SystemV) } - fn generate_intcc(&mut self) -> Result { - 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 { // TODO: It would be nice if we could get these directly from cranelift let scalars = [ @@ -681,7 +700,7 @@ where fn generate_bricmp(&mut self, builder: &mut FunctionBuilder) -> Result<()> { let (block, args) = self.generate_target_block(builder)?; - let cond = self.generate_intcc()?; + let cond = *self.u.choose(IntCC::all())?; let bricmp_types = [ I8, I16, I32,