Check trap code in test suite assertions
This commit is contained in:
@@ -203,6 +203,11 @@ fn handle_module(
|
||||
}),
|
||||
};
|
||||
let mut flag_builder = settings::builder();
|
||||
|
||||
// There are two possible traps for division, and this way
|
||||
// we get the proper one if code traps.
|
||||
flag_builder.enable("avoid_div_traps").unwrap();
|
||||
|
||||
if enable_simd {
|
||||
flag_builder.enable("enable_simd").unwrap();
|
||||
}
|
||||
|
||||
@@ -258,6 +258,10 @@ fn rmain() -> Result<(), Error> {
|
||||
let mut flag_builder = settings::builder();
|
||||
let mut features: Features = Default::default();
|
||||
|
||||
// There are two possible traps for division, and this way
|
||||
// we get the proper one if code traps.
|
||||
flag_builder.enable("avoid_div_traps")?;
|
||||
|
||||
// Enable/disable producing of debug info.
|
||||
let debug_info = args.flag_g;
|
||||
|
||||
|
||||
@@ -128,6 +128,10 @@ fn main() {
|
||||
let mut flag_builder = settings::builder();
|
||||
let mut features: Features = Default::default();
|
||||
|
||||
// There are two possible traps for division, and this way
|
||||
// we get the proper one if code traps.
|
||||
flag_builder.enable("avoid_div_traps").unwrap();
|
||||
|
||||
// Enable verifier passes in debug mode.
|
||||
if cfg!(debug_assertions) {
|
||||
flag_builder.enable("enable_verifier").unwrap();
|
||||
|
||||
@@ -13,6 +13,7 @@ include!(concat!(env!("OUT_DIR"), "/wast_testsuite_tests.rs"));
|
||||
fn native_isa() -> Box<dyn isa::TargetIsa> {
|
||||
let mut flag_builder = settings::builder();
|
||||
flag_builder.enable("enable_verifier").unwrap();
|
||||
flag_builder.enable("avoid_div_traps").unwrap();
|
||||
|
||||
let isa_builder = cranelift_native::builder().unwrap_or_else(|_| {
|
||||
panic!("host machine is not a supported target");
|
||||
|
||||
@@ -569,6 +569,18 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
|
||||
|
||||
let table_entry_addr = pos.ins().table_addr(pointer_type, table, callee, 0);
|
||||
|
||||
// Dereference table_entry_addr to get the function address.
|
||||
let mem_flags = ir::MemFlags::trusted();
|
||||
let func_addr = pos.ins().load(
|
||||
pointer_type,
|
||||
mem_flags,
|
||||
table_entry_addr,
|
||||
i32::from(self.offsets.vmcaller_checked_anyfunc_func_ptr()),
|
||||
);
|
||||
|
||||
// Check whether `func_addr` is null.
|
||||
pos.ins().trapz(func_addr, ir::TrapCode::IndirectCallToNull);
|
||||
|
||||
// If necessary, check the signature.
|
||||
match self.module.table_plans[table_index].style {
|
||||
TableStyle::CallerChecksSignature => {
|
||||
@@ -599,15 +611,6 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
|
||||
}
|
||||
}
|
||||
|
||||
// Dereference table_entry_addr to get the function address.
|
||||
let mem_flags = ir::MemFlags::trusted();
|
||||
let func_addr = pos.ins().load(
|
||||
pointer_type,
|
||||
mem_flags,
|
||||
table_entry_addr,
|
||||
i32::from(self.offsets.vmcaller_checked_anyfunc_func_ptr()),
|
||||
);
|
||||
|
||||
let mut real_call_args = Vec::with_capacity(call_args.len() + 1);
|
||||
|
||||
// First append the callee vmctx address.
|
||||
|
||||
@@ -86,13 +86,30 @@ fn trap_message() -> String {
|
||||
.expect("trap_message must be called after trap occurred");
|
||||
|
||||
format!(
|
||||
"wasm trap: code {:?}, source location: {}",
|
||||
// todo print the error message from wast tests
|
||||
trap_desc.trap_code,
|
||||
"wasm trap: {}, source location: {}",
|
||||
trap_code_to_expected_string(trap_desc.trap_code),
|
||||
trap_desc.source_loc,
|
||||
)
|
||||
}
|
||||
|
||||
fn trap_code_to_expected_string(trap_code: ir::TrapCode) -> String {
|
||||
use ir::TrapCode::*;
|
||||
match trap_code {
|
||||
StackOverflow => "call stack exhausted".to_string(),
|
||||
HeapOutOfBounds => "out of bounds memory access".to_string(),
|
||||
TableOutOfBounds => "undefined element".to_string(),
|
||||
OutOfBounds => "out of bounds".to_string(), // Note: not covered by the test suite
|
||||
IndirectCallToNull => "uninitialized element".to_string(),
|
||||
BadSignature => "indirect call type mismatch".to_string(),
|
||||
IntegerOverflow => "integer overflow".to_string(),
|
||||
IntegerDivisionByZero => "integer divide by zero".to_string(),
|
||||
BadConversionToInteger => "invalid conversion to integer".to_string(),
|
||||
UnreachableCodeReached => "unreachable".to_string(),
|
||||
Interrupt => "interrupt".to_string(), // Note: not covered by the test suite
|
||||
User(x) => format!("user trap {}", x), // Note: not covered by the test suite
|
||||
}
|
||||
}
|
||||
|
||||
/// Call the wasm function pointed to by `callee`. `values_vec` points to
|
||||
/// a buffer which holds the incoming arguments, and to which the outgoing
|
||||
/// return values will be written.
|
||||
|
||||
@@ -289,10 +289,16 @@ impl WastContext {
|
||||
ActionOutcome::Trapped {
|
||||
message: trap_message,
|
||||
} => {
|
||||
println!(
|
||||
"{}:{}: TODO: Check the assert_trap message: expected {}, got {}",
|
||||
filename, line, message, trap_message
|
||||
);
|
||||
if !trap_message.contains(&message) {
|
||||
return Err(WastFileError {
|
||||
filename: filename.to_string(),
|
||||
line,
|
||||
error: WastError::Assert(format!(
|
||||
"expected {}, got {}",
|
||||
message, trap_message
|
||||
)),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -315,10 +321,16 @@ impl WastContext {
|
||||
ActionOutcome::Trapped {
|
||||
message: trap_message,
|
||||
} => {
|
||||
println!(
|
||||
"{}:{}: TODO: Check the assert_exhaustion message: expected {}, got {}",
|
||||
filename, line, message, trap_message
|
||||
);
|
||||
if !trap_message.contains(&message) {
|
||||
return Err(WastFileError {
|
||||
filename: filename.to_string(),
|
||||
line,
|
||||
error: WastError::Assert(format!(
|
||||
"expected exhaustion with {}, got {}",
|
||||
message, trap_message
|
||||
)),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user