Path: blob/main/cranelift/fuzzgen/src/cranelift_arbitrary.rs
1692 views
use crate::codegen::ir::{ArgumentExtension, ArgumentPurpose};1use anyhow::Result;2use cranelift::codegen::data_value::DataValue;3use cranelift::codegen::ir::types::*;4use cranelift::codegen::ir::{AbiParam, Signature};5use cranelift::codegen::isa::CallConv;67use arbitrary::Unstructured;8use cranelift::prelude::{Ieee32, Ieee64};9use target_lexicon::Architecture;1011/// A trait for generating random Cranelift datastructures.12pub trait CraneliftArbitrary {13fn _type(&mut self, simd_enabled: bool) -> Result<Type>;14fn callconv(&mut self, architecture: Architecture) -> Result<CallConv>;15fn abi_param(&mut self, simd_enabled: bool) -> Result<AbiParam>;16fn signature(17&mut self,18simd_enabled: bool,19architecture: Architecture,20max_params: usize,21max_rets: usize,22) -> Result<Signature>;23fn datavalue(&mut self, ty: Type) -> Result<DataValue>;24}2526impl<'a> CraneliftArbitrary for &mut Unstructured<'a> {27fn _type(&mut self, simd_enabled: bool) -> Result<Type> {28// TODO: It would be nice if we could get these directly from cranelift29let choices: &[Type] = if simd_enabled {30&[31I8, I16, I32, I64, I128, // Scalar Integers32F32, F64, // Scalar Floats33I8X16, I16X8, I32X4, I64X2, // SIMD Integers34F32X4, F64X2, // SIMD Floats35]36} else {37&[I8, I16, I32, I64, I128, F32, F64]38};3940Ok(*self.choose(choices)?)41}4243fn callconv(&mut self, architecture: Architecture) -> Result<CallConv> {44// These are implemented and should work on all backends45let mut allowed_callconvs = vec![46CallConv::Fast,47CallConv::Cold,48CallConv::SystemV,49CallConv::Tail,50];5152// Fastcall is supposed to work on x86 and aarch6453if matches!(54architecture,55Architecture::X86_64 | Architecture::Aarch64(_)56) {57allowed_callconvs.push(CallConv::WindowsFastcall);58}5960// AArch64 has a few Apple specific calling conventions61if matches!(architecture, Architecture::Aarch64(_)) {62allowed_callconvs.push(CallConv::AppleAarch64);63}6465// The winch calling convention is supposed to work on x64.66if matches!(architecture, Architecture::X86_64) {67allowed_callconvs.push(CallConv::Winch);68}6970Ok(*self.choose(&allowed_callconvs[..])?)71}7273fn abi_param(&mut self, simd_enabled: bool) -> Result<AbiParam> {74let value_type = self._type(simd_enabled)?;75// TODO: There are more argument purposes to be explored...76let purpose = ArgumentPurpose::Normal;77let extension = if value_type.is_int() {78*self.choose(&[79ArgumentExtension::Sext,80ArgumentExtension::Uext,81ArgumentExtension::None,82])?83} else {84ArgumentExtension::None85};8687Ok(AbiParam {88value_type,89purpose,90extension,91})92}9394fn signature(95&mut self,96mut simd_enabled: bool,97architecture: Architecture,98max_params: usize,99max_rets: usize,100) -> Result<Signature> {101let callconv = self.callconv(architecture)?;102103// Winch doesn't support SIMD yet104// https://github.com/bytecodealliance/wasmtime/issues/8093105if callconv == CallConv::Winch {106simd_enabled = false;107}108109let mut sig = Signature::new(callconv);110111for _ in 0..max_params {112sig.params.push(self.abi_param(simd_enabled)?);113}114115for _ in 0..max_rets {116sig.returns.push(self.abi_param(simd_enabled)?);117}118119Ok(sig)120}121122fn datavalue(&mut self, ty: Type) -> Result<DataValue> {123Ok(match ty {124ty if ty.is_int() => {125let imm = match ty {126I8 => self.arbitrary::<i8>()? as i128,127I16 => self.arbitrary::<i16>()? as i128,128I32 => self.arbitrary::<i32>()? as i128,129I64 => self.arbitrary::<i64>()? as i128,130I128 => self.arbitrary::<i128>()?,131_ => unreachable!(),132};133DataValue::from_integer(imm, ty)?134}135// f{32,64}::arbitrary does not generate a bunch of important values136// such as Signaling NaN's / NaN's with payload, so generate floats from integers.137F32 => DataValue::F32(Ieee32::with_bits(self.arbitrary::<u32>()?)),138F64 => DataValue::F64(Ieee64::with_bits(self.arbitrary::<u64>()?)),139ty if ty.is_vector() && ty.bits() == 128 => {140DataValue::V128(self.arbitrary::<[u8; 16]>()?)141}142_ => unimplemented!(),143})144}145}146147148