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:
@@ -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(|(_, ¶m)| 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(())
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user