Skip to content

Commit 853ff78

Browse files
authored
fuzzgen: Refactor name and signature generation (#5764)
* fuzzgen: Move cranelift type generation into CraneliftArbitrary * fuzzgen: Deduplicate DataValue generation * fuzzgen: Remove unused code * fuzzgen: Pass allowed function calls into `FunctionGenerator`
1 parent a7bd65d commit 853ff78

File tree

4 files changed

+213
-161
lines changed

4 files changed

+213
-161
lines changed

cranelift/fuzzgen/src/config.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ pub struct Config {
3030
pub switch_cases: RangeInclusive<usize>,
3131
pub switch_max_range_size: RangeInclusive<usize>,
3232

33-
pub funcrefs_per_function: RangeInclusive<usize>,
33+
/// Number of distinct functions in the same testsuite that we allow calling per function.
34+
pub usercalls: RangeInclusive<usize>,
3435

3536
/// Stack slots.
3637
/// The combination of these two determines stack usage per function
@@ -79,7 +80,7 @@ impl Default for Config {
7980
switch_cases: 0..=64,
8081
// Ranges smaller than 2 don't make sense.
8182
switch_max_range_size: 2..=32,
82-
funcrefs_per_function: 0..=8,
83+
usercalls: 0..=8,
8384
static_stack_slots_per_function: 0..=8,
8485
static_stack_slot_size: 0..=128,
8586
// We need the mix of sizes that allows us to:
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
use crate::codegen::ir::{ArgumentExtension, ArgumentPurpose};
2+
use anyhow::Result;
3+
use cranelift::codegen::data_value::DataValue;
4+
use cranelift::codegen::ir::types::*;
5+
use cranelift::codegen::ir::{AbiParam, Signature, Type};
6+
use cranelift::codegen::isa::CallConv;
7+
8+
use arbitrary::Unstructured;
9+
use cranelift::prelude::{Ieee32, Ieee64};
10+
11+
/// A trait for generating random Cranelift datastructures.
12+
pub trait CraneliftArbitrary {
13+
fn _type(&mut self) -> Result<Type>;
14+
fn callconv(&mut self) -> Result<CallConv>;
15+
fn abi_param(&mut self) -> Result<AbiParam>;
16+
fn signature(&mut self, max_params: usize, max_rets: usize) -> Result<Signature>;
17+
fn datavalue(&mut self, ty: Type) -> Result<DataValue>;
18+
}
19+
20+
impl<'a> CraneliftArbitrary for &mut Unstructured<'a> {
21+
fn _type(&mut self) -> Result<Type> {
22+
// TODO: It would be nice if we could get these directly from cranelift
23+
let scalars = [
24+
I8, I16, I32, I64, I128, F32, F64,
25+
// R32, R64,
26+
];
27+
// TODO: vector types
28+
29+
let ty = self.choose(&scalars[..])?;
30+
Ok(*ty)
31+
}
32+
33+
fn callconv(&mut self) -> Result<CallConv> {
34+
// TODO: Generate random CallConvs per target
35+
Ok(CallConv::SystemV)
36+
}
37+
38+
fn abi_param(&mut self) -> Result<AbiParam> {
39+
let value_type = self._type()?;
40+
// TODO: There are more argument purposes to be explored...
41+
let purpose = ArgumentPurpose::Normal;
42+
let extension = if value_type.is_int() {
43+
*self.choose(&[
44+
ArgumentExtension::Sext,
45+
ArgumentExtension::Uext,
46+
ArgumentExtension::None,
47+
])?
48+
} else {
49+
ArgumentExtension::None
50+
};
51+
52+
Ok(AbiParam {
53+
value_type,
54+
purpose,
55+
extension,
56+
})
57+
}
58+
59+
fn signature(&mut self, max_params: usize, max_rets: usize) -> Result<Signature> {
60+
let callconv = self.callconv()?;
61+
let mut sig = Signature::new(callconv);
62+
63+
for _ in 0..max_params {
64+
sig.params.push(self.abi_param()?);
65+
}
66+
67+
for _ in 0..max_rets {
68+
sig.returns.push(self.abi_param()?);
69+
}
70+
71+
Ok(sig)
72+
}
73+
74+
fn datavalue(&mut self, ty: Type) -> Result<DataValue> {
75+
Ok(match ty {
76+
ty if ty.is_int() => {
77+
let imm = match ty {
78+
I8 => self.arbitrary::<i8>()? as i128,
79+
I16 => self.arbitrary::<i16>()? as i128,
80+
I32 => self.arbitrary::<i32>()? as i128,
81+
I64 => self.arbitrary::<i64>()? as i128,
82+
I128 => self.arbitrary::<i128>()?,
83+
_ => unreachable!(),
84+
};
85+
DataValue::from_integer(imm, ty)?
86+
}
87+
// f{32,64}::arbitrary does not generate a bunch of important values
88+
// such as Signaling NaN's / NaN's with payload, so generate floats from integers.
89+
F32 => DataValue::F32(Ieee32::with_bits(self.arbitrary::<u32>()?)),
90+
F64 => DataValue::F64(Ieee64::with_bits(self.arbitrary::<u64>()?)),
91+
_ => unimplemented!(),
92+
})
93+
}
94+
}

0 commit comments

Comments
 (0)