cranelift: Forbid argument extensions for floats and SIMD vectors (#5536)

* fuzzgen: Generate argument extensions only for integer argumetns

* cranelift: Add verifier check for argument extensions
This commit is contained in:
Afonso Bordado
2023-01-10 18:26:30 +00:00
committed by GitHub
parent 23ea435a91
commit 9556cb190f
3 changed files with 74 additions and 32 deletions

View File

@@ -61,9 +61,9 @@ use crate::dbg::DisplayList;
use crate::dominator_tree::DominatorTree;
use crate::entity::SparseSet;
use crate::flowgraph::{BlockPredecessor, ControlFlowGraph};
use crate::ir;
use crate::ir::entities::AnyEntity;
use crate::ir::instructions::{BranchInfo, CallInfo, InstructionFormat, ResolvedConstraint};
use crate::ir::{self, ArgumentExtension};
use crate::ir::{
types, ArgumentPurpose, Block, Constant, DynamicStackSlot, FuncRef, Function, GlobalValue,
Inst, JumpTable, MemFlags, Opcode, SigRef, StackSlot, Type, Value, ValueDef, ValueList,
@@ -1648,45 +1648,57 @@ impl<'a> Verifier<'a> {
}
fn typecheck_function_signature(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
self.func
let params = self
.func
.signature
.params
.iter()
.enumerate()
.filter(|(_, &param)| param.value_type == types::INVALID)
.for_each(|(i, _)| {
.map(|p| (true, p));
let returns = self
.func
.signature
.returns
.iter()
.enumerate()
.map(|p| (false, p));
for (is_argument, (i, param)) in params.chain(returns) {
let is_return = !is_argument;
let item = if is_argument {
"Parameter"
} else {
"Return value"
};
if param.value_type == types::INVALID {
errors.report((
AnyEntity::Function,
format!("Parameter at position {} has an invalid type", i),
format!("{item} at position {i} has an invalid type"),
));
});
}
self.func
.signature
.returns
.iter()
.enumerate()
.filter(|(_, &ret)| ret.value_type == types::INVALID)
.for_each(|(i, _)| {
if let ArgumentPurpose::StructArgument(_) = param.purpose {
if is_return {
errors.report((
AnyEntity::Function,
format!("Return value at position {} has an invalid type", i),
))
});
self.func
.signature
.returns
.iter()
.enumerate()
.for_each(|(i, ret)| {
if let ArgumentPurpose::StructArgument(_) = ret.purpose {
errors.report((
AnyEntity::Function,
format!("Return value at position {} can't be an struct argument", i),
format!("{item} at position {i} can't be an struct argument"),
))
}
});
}
let ty_allows_extension = param.value_type.is_int();
let has_extension = param.extension != ArgumentExtension::None;
if !ty_allows_extension && has_extension {
errors.report((
AnyEntity::Function,
format!(
"{} at position {} has invalid extension {:?}",
item, i, param.extension
),
));
}
}
if errors.has_error() {
Err(())

View File

@@ -0,0 +1,26 @@
test verifier
function %float_with_sext(f32 sext) -> f32 { ; error: Parameter at position 0 has invalid extension Sext
block0(v0: f32):
return v0
}
function %float_with_uext(f32 uext) -> f32 { ; error: Parameter at position 0 has invalid extension Uext
block0(v0: f32):
return v0
}
function %float_ret_with_sext(f32) -> f32 sext { ; error: Return value at position 0 has invalid extension Sext
block0(v0: f32):
return v0
}
function %float_ret_with_uext(f32) -> f32 uext { ; error: Return value at position 0 has invalid extension Uext
block0(v0: f32):
return v0
}
function %simd_ext(i32x4 sext) -> i32x4 { ; error: Parameter at position 0 has invalid extension Sext
block0(v0: i32x4):
return v0
}

View File

@@ -1230,10 +1230,14 @@ where
let value_type = self.generate_type()?;
// TODO: There are more argument purposes to be explored...
let purpose = ArgumentPurpose::Normal;
let extension = match self.u.int_in_range(0..=2)? {
2 => ArgumentExtension::Sext,
1 => ArgumentExtension::Uext,
_ => ArgumentExtension::None,
let extension = if value_type.is_int() {
*self.u.choose(&[
ArgumentExtension::Sext,
ArgumentExtension::Uext,
ArgumentExtension::None,
])?
} else {
ArgumentExtension::None
};
Ok(AbiParam {