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:
@@ -7,11 +7,12 @@ use crate::value::{Value, ValueConversionKind, ValueError, ValueResult};
|
||||
use cranelift_codegen::data_value::DataValue;
|
||||
use cranelift_codegen::ir::condcodes::{FloatCC, IntCC};
|
||||
use cranelift_codegen::ir::{
|
||||
types, Block, FuncRef, Function, InstructionData, Opcode, TrapCode, Value as ValueRef,
|
||||
types, Block, FuncRef, Function, InstructionData, Opcode, TrapCode, Type, Value as ValueRef,
|
||||
};
|
||||
use log::trace;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::fmt::Debug;
|
||||
use std::ops::RangeFrom;
|
||||
use thiserror::Error;
|
||||
|
||||
@@ -135,11 +136,11 @@ where
|
||||
Err(e) => ControlFlow::Trap(CraneliftTrap::User(memerror_to_trap(e))),
|
||||
};
|
||||
|
||||
let calculate_addr = |imm: V, args: SmallVec<[V; 1]>| -> ValueResult<u64> {
|
||||
let imm = imm.convert(ValueConversionKind::ZeroExtend(ctrl_ty))?;
|
||||
let calculate_addr = |addr_ty: Type, imm: V, args: SmallVec<[V; 1]>| -> ValueResult<u64> {
|
||||
let imm = imm.convert(ValueConversionKind::ZeroExtend(addr_ty))?;
|
||||
let args = args
|
||||
.into_iter()
|
||||
.map(|v| v.convert(ValueConversionKind::ZeroExtend(ctrl_ty)))
|
||||
.map(|v| v.convert(ValueConversionKind::ZeroExtend(addr_ty)))
|
||||
.collect::<ValueResult<SmallVec<[V; 1]>>>()?;
|
||||
|
||||
Ok(sum(imm, args)? as u64)
|
||||
@@ -315,7 +316,7 @@ where
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let addr_value = calculate_addr(imm(), args()?)?;
|
||||
let addr_value = calculate_addr(types::I64, imm(), args()?)?;
|
||||
let loaded = assign_or_memtrap(
|
||||
Address::try_from(addr_value).and_then(|addr| state.checked_load(addr, load_ty)),
|
||||
);
|
||||
@@ -338,7 +339,7 @@ where
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let addr_value = calculate_addr(imm(), args_range(1..)?)?;
|
||||
let addr_value = calculate_addr(types::I64, imm(), args_range(1..)?)?;
|
||||
let reduced = if let Some(c) = kind {
|
||||
arg(0)?.convert(c)?
|
||||
} else {
|
||||
@@ -383,7 +384,21 @@ where
|
||||
Opcode::GlobalValue => unimplemented!("GlobalValue"),
|
||||
Opcode::SymbolValue => unimplemented!("SymbolValue"),
|
||||
Opcode::TlsValue => unimplemented!("TlsValue"),
|
||||
Opcode::HeapAddr => unimplemented!("HeapAddr"),
|
||||
Opcode::HeapAddr => {
|
||||
if let InstructionData::HeapAddr { heap, .. } = inst {
|
||||
let load_ty = inst_context.controlling_type().unwrap();
|
||||
let offset = calculate_addr(ctrl_ty, imm(), args()?)? as u64;
|
||||
assign_or_memtrap({
|
||||
AddressSize::try_from(load_ty).and_then(|addr_size| {
|
||||
let addr = state.heap_address(addr_size, heap, offset)?;
|
||||
let dv = DataValue::try_from(addr)?;
|
||||
Ok(dv.into())
|
||||
})
|
||||
})
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
Opcode::GetPinnedReg => unimplemented!("GetPinnedReg"),
|
||||
Opcode::SetPinnedReg => unimplemented!("SetPinnedReg"),
|
||||
Opcode::TableAddr => unimplemented!("TableAddr"),
|
||||
|
||||
Reference in New Issue
Block a user