diff --git a/cranelift-codegen/src/verifier/mod.rs b/cranelift-codegen/src/verifier/mod.rs index 21f0c72ca..02cc3f0c5 100644 --- a/cranelift-codegen/src/verifier/mod.rs +++ b/cranelift-codegen/src/verifier/mod.rs @@ -1838,12 +1838,51 @@ impl<'a> Verifier<'a> { Ok(()) } + fn typecheck_function_signature(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> { + self.func + .signature + .params + .iter() + .enumerate() + .filter(|(_, ¶m)| param.value_type == types::INVALID) + .for_each(|(i, _)| { + report!( + errors, + AnyEntity::Function, + "Parameter at position {} has an invalid type", + i + ); + }); + + self.func + .signature + .returns + .iter() + .enumerate() + .filter(|(_, &ret)| ret.value_type == types::INVALID) + .for_each(|(i, _)| { + report!( + errors, + AnyEntity::Function, + "Return value at position {} has an invalid type", + i + ) + }); + + if errors.has_error() { + Err(()) + } else { + Ok(()) + } + } + pub fn run(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> { self.verify_global_values(errors)?; self.verify_heaps(errors)?; self.verify_tables(errors)?; self.verify_jump_tables(errors)?; self.typecheck_entry_block_params(errors)?; + self.typecheck_function_signature(errors)?; for ebb in self.func.layout.ebbs() { for inst in self.func.layout.ebb_insts(ebb) { @@ -1870,7 +1909,7 @@ mod tests { use super::{Verifier, VerifierError, VerifierErrors}; use crate::entity::EntityList; use crate::ir::instructions::{InstructionData, Opcode}; - use crate::ir::Function; + use crate::ir::{types, AbiParam, Function}; use crate::settings; macro_rules! assert_err_with_msg { @@ -1929,4 +1968,30 @@ mod tests { assert_err_with_msg!(errors, "instruction format"); } + + #[test] + fn test_function_invalid_param() { + let mut func = Function::new(); + func.signature.params.push(AbiParam::new(types::INVALID)); + + let mut errors = VerifierErrors::default(); + let flags = &settings::Flags::new(settings::builder()); + let verifier = Verifier::new(&func, flags.into()); + + let _ = verifier.typecheck_function_signature(&mut errors); + assert_err_with_msg!(errors, "Parameter at position 0 has an invalid type"); + } + + #[test] + fn test_function_invalid_return_value() { + let mut func = Function::new(); + func.signature.returns.push(AbiParam::new(types::INVALID)); + + let mut errors = VerifierErrors::default(); + let flags = &settings::Flags::new(settings::builder()); + let verifier = Verifier::new(&func, flags.into()); + + let _ = verifier.typecheck_function_signature(&mut errors); + assert_err_with_msg!(errors, "Return value at position 0 has an invalid type"); + } }