Skip to content

Commit

Permalink
fuzzgen: Enable SIMD fuzzing for RISC-V (#6949)
Browse files Browse the repository at this point in the history
  • Loading branch information
afonso360 authored Sep 2, 2023
1 parent 5e7ee8a commit f10d665
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 39 deletions.
47 changes: 22 additions & 25 deletions cranelift/fuzzgen/src/cranelift_arbitrary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,38 +11,34 @@ use target_lexicon::Architecture;

/// A trait for generating random Cranelift datastructures.
pub trait CraneliftArbitrary {
fn _type(&mut self, architecture: Architecture) -> Result<Type>;
fn _type(&mut self, simd_enabled: bool) -> Result<Type>;
fn callconv(&mut self, architecture: Architecture) -> Result<CallConv>;
fn abi_param(&mut self, architecture: Architecture) -> Result<AbiParam>;
fn abi_param(&mut self, simd_enabled: bool) -> Result<AbiParam>;
fn signature(
&mut self,
simd_enabled: bool,
architecture: Architecture,
max_params: usize,
max_rets: usize,
) -> Result<Signature>;
fn datavalue(&mut self, ty: Type) -> Result<DataValue>;
}

/// Returns the set of types that are valid for value generation, dependent on architecture.
pub fn types_for_architecture(architecture: Architecture) -> &'static [Type] {
// TODO: It would be nice if we could get these directly from cranelift
// TODO: RISCV does not support SIMD yet
let supports_simd = !matches!(architecture, Architecture::Riscv64(_));
if supports_simd {
&[
I8, I16, I32, I64, I128, // Scalar Integers
F32, F64, // Scalar Floats
I8X16, I16X8, I32X4, I64X2, // SIMD Integers
F32X4, F64X2, // SIMD Floats
]
} else {
&[I8, I16, I32, I64, I128, F32, F64]
}
}

impl<'a> CraneliftArbitrary for &mut Unstructured<'a> {
fn _type(&mut self, architecture: Architecture) -> Result<Type> {
Ok(*self.choose(types_for_architecture(architecture))?)
fn _type(&mut self, simd_enabled: bool) -> Result<Type> {
// TODO: It would be nice if we could get these directly from cranelift
let choices: &[Type] = if simd_enabled {
&[
I8, I16, I32, I64, I128, // Scalar Integers
F32, F64, // Scalar Floats
I8X16, I16X8, I32X4, I64X2, // SIMD Integers
F32X4, F64X2, // SIMD Floats
]
} else {
&[I8, I16, I32, I64, I128, F32, F64]
};

Ok(*self.choose(choices)?)
}

fn callconv(&mut self, architecture: Architecture) -> Result<CallConv> {
Expand Down Expand Up @@ -71,8 +67,8 @@ impl<'a> CraneliftArbitrary for &mut Unstructured<'a> {
Ok(*self.choose(&allowed_callconvs[..])?)
}

fn abi_param(&mut self, architecture: Architecture) -> Result<AbiParam> {
let value_type = self._type(architecture)?;
fn abi_param(&mut self, simd_enabled: bool) -> Result<AbiParam> {
let value_type = self._type(simd_enabled)?;
// TODO: There are more argument purposes to be explored...
let purpose = ArgumentPurpose::Normal;
let extension = if value_type.is_int() {
Expand All @@ -94,6 +90,7 @@ impl<'a> CraneliftArbitrary for &mut Unstructured<'a> {

fn signature(
&mut self,
simd_enabled: bool,
architecture: Architecture,
max_params: usize,
max_rets: usize,
Expand All @@ -102,11 +99,11 @@ impl<'a> CraneliftArbitrary for &mut Unstructured<'a> {
let mut sig = Signature::new(callconv);

for _ in 0..max_params {
sig.params.push(self.abi_param(architecture)?);
sig.params.push(self.abi_param(simd_enabled)?);
}

for _ in 0..max_rets {
sig.returns.push(self.abi_param(architecture)?);
sig.returns.push(self.abi_param(simd_enabled)?);
}

Ok(sig)
Expand Down
21 changes: 12 additions & 9 deletions cranelift/fuzzgen/src/function_generator.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::config::Config;
use crate::cranelift_arbitrary::CraneliftArbitrary;
use crate::target_isa_extras::TargetIsaExtras;
use anyhow::Result;
use arbitrary::{Arbitrary, Unstructured};
use cranelift::codegen::data_value::DataValue;
Expand Down Expand Up @@ -717,12 +718,6 @@ fn valid_for_target(triple: &Triple, op: Opcode, args: &[Type], rets: &[Type]) -
}

Architecture::Riscv64(_) => {
// RISC-V Does not support SIMD at all
let is_simd = args.iter().chain(rets).any(|t| t.is_vector());
if is_simd {
return false;
}

exceptions!(
op,
args,
Expand Down Expand Up @@ -761,9 +756,17 @@ fn valid_for_target(triple: &Triple, op: Opcode, args: &[Type], rets: &[Type]) -
(Opcode::Bitcast, &[I128], &[_]),
(Opcode::Bitcast, &[_], &[I128]),
// TODO
(Opcode::SelectSpectreGuard, &[_, _, _], &[F32 | F64]),
(
Opcode::SelectSpectreGuard,
&[_, _, _],
&[F32 | F64 | I8X16 | I16X8 | I32X4 | I64X2 | F64X2 | F32X4]
),
// TODO
(Opcode::Bitselect, &[_, _, _], &[F32 | F64]),
(
Opcode::Rotr | Opcode::Rotl,
&[I8X16 | I16X8 | I32X4 | I64X2, _]
),
)
}

Expand Down Expand Up @@ -1823,7 +1826,7 @@ where

let mut params = Vec::with_capacity(param_count);
for _ in 0..param_count {
params.push(self.u._type(self.isa.triple().architecture)?);
params.push(self.u._type((&*self.isa).supports_simd())?);
}
Ok(params)
}
Expand All @@ -1843,7 +1846,7 @@ where

// Create a pool of vars that are going to be used in this function
for _ in 0..self.param(&self.config.vars_per_function)? {
let ty = self.u._type(self.isa.triple().architecture)?;
let ty = self.u._type((&*self.isa).supports_simd())?;
let value = self.generate_const(builder, ty)?;
vars.push((ty, value));
}
Expand Down
15 changes: 11 additions & 4 deletions cranelift/fuzzgen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,20 @@ use cranelift::codegen::ir::{types::*, UserExternalName, UserFuncName};
use cranelift::codegen::ir::{Function, LibCall};
use cranelift::codegen::isa::{self, Builder};
use cranelift::codegen::Context;
use cranelift::prelude::isa::OwnedTargetIsa;
use cranelift::prelude::isa::{OwnedTargetIsa, TargetIsa};
use cranelift::prelude::settings::SettingKind;
use cranelift::prelude::*;
use cranelift_arbitrary::CraneliftArbitrary;
use cranelift_native::builder_with_options;
use target_isa_extras::TargetIsaExtras;
use target_lexicon::Architecture;

mod config;
mod cranelift_arbitrary;
mod function_generator;
mod passes;
mod print;
mod target_isa_extras;

pub use print::PrintableTestCase;

Expand Down Expand Up @@ -53,10 +55,15 @@ where
}
}

pub fn generate_signature(&mut self, architecture: Architecture) -> Result<Signature> {
pub fn generate_signature(&mut self, isa: &dyn TargetIsa) -> Result<Signature> {
let max_params = self.u.int_in_range(self.config.signature_params.clone())?;
let max_rets = self.u.int_in_range(self.config.signature_rets.clone())?;
Ok(self.u.signature(architecture, max_params, max_rets)?)
Ok(self.u.signature(
isa.supports_simd(),
isa.triple().architecture,
max_params,
max_rets,
)?)
}

pub fn generate_test_inputs(mut self, signature: &Signature) -> Result<Vec<TestCaseInput>> {
Expand Down Expand Up @@ -144,7 +151,7 @@ where
usercalls: Vec<(UserExternalName, Signature)>,
libcalls: Vec<LibCall>,
) -> Result<Function> {
let sig = self.generate_signature(isa.triple().architecture)?;
let sig = self.generate_signature(&*isa)?;

let func = FunctionGenerator::new(
&mut self.u,
Expand Down
21 changes: 21 additions & 0 deletions cranelift/fuzzgen/src/target_isa_extras.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use cranelift::prelude::isa::TargetIsa;
use target_lexicon::Architecture;

pub trait TargetIsaExtras {
fn supports_simd(&self) -> bool;
}

impl TargetIsaExtras for &dyn TargetIsa {
fn supports_simd(&self) -> bool {
match self.triple().architecture {
// RISC-V only supports SIMD with the V extension.
Architecture::Riscv64(_) => self
.isa_flags()
.iter()
.find(|f| f.name == "has_v")
.and_then(|f| f.as_bool())
.unwrap_or(false),
_ => true,
}
}
}
2 changes: 1 addition & 1 deletion fuzz/fuzz_targets/cranelift-icache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ impl FunctionWithIsa {
let usercalls = (0..func_count)
.map(|i| {
let name = UserExternalName::new(2, i as u32);
let sig = gen.generate_signature(architecture)?;
let sig = gen.generate_signature(&*isa)?;
Ok((name, sig))
})
.collect::<anyhow::Result<Vec<(UserExternalName, Signature)>>>()
Expand Down

0 comments on commit f10d665

Please sign in to comment.