cranelift: Add heap support to the interpreter (#3302)

* cranelift: Add heaps to interpreter

* cranelift: Add RunTest Environment mechanism to  test interpret

* cranelift: Remove unused `MemoryError`

* cranelift: Add docs for `State::resolve_global_value`

* cranelift: Rename heap tests

* cranelift: Refactor heap address resolution

* Fix typos and clarify docs (thanks @cfallin)
This commit is contained in:
Afonso Bordado
2022-07-05 17:05:26 +01:00
committed by GitHub
parent 76a2545a7f
commit e91f493ff5
7 changed files with 531 additions and 140 deletions

View File

@@ -3,10 +3,11 @@
//! The `run` test command compiles each function on the host machine and executes it
use crate::function_runner::SingleFunctionCompiler;
use crate::runtest_environment::RuntestEnvironment;
use crate::runtest_environment::{HeapMemory, RuntestEnvironment};
use crate::subtest::{Context, SubTest};
use cranelift_codegen::data_value::DataValue;
use cranelift_codegen::ir;
use cranelift_codegen::ir::ArgumentPurpose;
use cranelift_codegen::ir::Type;
use cranelift_reader::parse_run_command;
use cranelift_reader::TestCommand;
use log::trace;
@@ -64,25 +65,13 @@ impl SubTest for TestRun {
let compiled_fn = compiler.compile(func.clone().into_owned())?;
command
.run(|_, run_args| {
let runtime_struct = test_env.runtime_struct();
let first_arg_is_vmctx = func
.signature
.params
.first()
.map(|p| p.purpose == ArgumentPurpose::VMContext)
.unwrap_or(false);
if !first_arg_is_vmctx && test_env.is_active() {
return Err(concat!(
"This test requests a heap, but the first argument is not `i64 vmctx`.\n",
"See docs/testing.md for more info on using heap annotations."
).to_string());
}
test_env.validate_signature(&func)?;
let (_heaps, _ctx_struct, vmctx_ptr) =
build_vmctx_struct(&test_env, context.isa.unwrap().pointer_type());
let mut args = Vec::with_capacity(run_args.len());
if test_env.is_active() {
args.push(runtime_struct.pointer(context.isa.unwrap().pointer_type()));
args.push(vmctx_ptr);
}
args.extend_from_slice(run_args);
@@ -94,3 +83,24 @@ impl SubTest for TestRun {
Ok(())
}
}
/// Build a VMContext struct with the layout described in docs/testing.md.
pub fn build_vmctx_struct(
test_env: &RuntestEnvironment,
ptr_ty: Type,
) -> (Vec<HeapMemory>, Vec<u64>, DataValue) {
let heaps = test_env.allocate_memory();
let context_struct: Vec<u64> = heaps
.iter()
.flat_map(|heap| [heap.as_ptr(), heap.as_ptr().wrapping_add(heap.len())])
.map(|p| p as usize as u64)
.collect();
let ptr = context_struct.as_ptr() as usize as i128;
let ptr_dv =
DataValue::from_integer(ptr, ptr_ty).expect("Failed to cast pointer to native target size");
// Return all these to make sure we don't deallocate the heaps too early
(heaps, context_struct, ptr_dv)
}