Various cranelift interpreter improvements (#6176)
* Remove the validate_address State trait method It isn't used anywhere * Expose the inner Function of a Frame This is necessary to create your own interpreter that reuses most of cranelift-interpreter. For example to use a different State implementation. * Support the symbol_value and tls_value instructions in the interpreter
This commit is contained in:
@@ -12,7 +12,7 @@ pub(crate) type Entries = Vec<Option<DataValue>>;
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Frame<'a> {
|
pub struct Frame<'a> {
|
||||||
/// The currently executing function.
|
/// The currently executing function.
|
||||||
pub(crate) function: &'a Function,
|
function: &'a Function,
|
||||||
/// The current mapping of SSA value-references to their actual values. For efficiency, each SSA value is used as an
|
/// The current mapping of SSA value-references to their actual values. For efficiency, each SSA value is used as an
|
||||||
/// index into the Vec, meaning some slots may be unused.
|
/// index into the Vec, meaning some slots may be unused.
|
||||||
registers: Entries,
|
registers: Entries,
|
||||||
@@ -100,6 +100,11 @@ impl<'a> Frame<'a> {
|
|||||||
pub fn entries_mut(&mut self) -> &mut [Option<DataValue>] {
|
pub fn entries_mut(&mut self) -> &mut [Option<DataValue>] {
|
||||||
&mut self.registers
|
&mut self.registers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Accessor for the [`Function`] of this frame.
|
||||||
|
pub fn function(&self) -> &'a Function {
|
||||||
|
self.function
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ impl<'a> Interpreter<'a> {
|
|||||||
/// instructions, which may continue in other blocks, until the function returns.
|
/// instructions, which may continue in other blocks, until the function returns.
|
||||||
fn block(&mut self, block: Block) -> Result<ControlFlow<'a, DataValue>, InterpreterError> {
|
fn block(&mut self, block: Block) -> Result<ControlFlow<'a, DataValue>, InterpreterError> {
|
||||||
trace!("Block: {}", block);
|
trace!("Block: {}", block);
|
||||||
let function = self.state.current_frame_mut().function;
|
let function = self.state.current_frame_mut().function();
|
||||||
let layout = &function.layout;
|
let layout = &function.layout;
|
||||||
let mut maybe_inst = layout.first_inst(block);
|
let mut maybe_inst = layout.first_inst(block);
|
||||||
while let Some(inst) = maybe_inst {
|
while let Some(inst) = maybe_inst {
|
||||||
@@ -257,10 +257,10 @@ impl<'a> InterpreterState<'a> {
|
|||||||
impl<'a> State<'a, DataValue> for InterpreterState<'a> {
|
impl<'a> State<'a, DataValue> for InterpreterState<'a> {
|
||||||
fn get_function(&self, func_ref: FuncRef) -> Option<&'a Function> {
|
fn get_function(&self, func_ref: FuncRef) -> Option<&'a Function> {
|
||||||
self.functions
|
self.functions
|
||||||
.get_from_func_ref(func_ref, self.frame_stack.last().unwrap().function)
|
.get_from_func_ref(func_ref, self.frame_stack.last().unwrap().function())
|
||||||
}
|
}
|
||||||
fn get_current_function(&self) -> &'a Function {
|
fn get_current_function(&self) -> &'a Function {
|
||||||
self.current_frame().function
|
self.current_frame().function()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_libcall_handler(&self) -> LibCallHandler<DataValue> {
|
fn get_libcall_handler(&self) -> LibCallHandler<DataValue> {
|
||||||
@@ -269,7 +269,7 @@ impl<'a> State<'a, DataValue> for InterpreterState<'a> {
|
|||||||
|
|
||||||
fn push_frame(&mut self, function: &'a Function) {
|
fn push_frame(&mut self, function: &'a Function) {
|
||||||
if let Some(frame) = self.frame_stack.iter().last() {
|
if let Some(frame) = self.frame_stack.iter().last() {
|
||||||
self.frame_offset += frame.function.fixed_stack_size() as usize;
|
self.frame_offset += frame.function().fixed_stack_size() as usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grow the stack by the space necessary for this frame
|
// Grow the stack by the space necessary for this frame
|
||||||
@@ -282,11 +282,11 @@ impl<'a> State<'a, DataValue> for InterpreterState<'a> {
|
|||||||
if let Some(frame) = self.frame_stack.pop() {
|
if let Some(frame) = self.frame_stack.pop() {
|
||||||
// Shorten the stack after exiting the frame
|
// Shorten the stack after exiting the frame
|
||||||
self.stack
|
self.stack
|
||||||
.truncate(self.stack.len() - frame.function.fixed_stack_size() as usize);
|
.truncate(self.stack.len() - frame.function().fixed_stack_size() as usize);
|
||||||
|
|
||||||
// Reset frame_offset to the start of this function
|
// Reset frame_offset to the start of this function
|
||||||
if let Some(frame) = self.frame_stack.iter().last() {
|
if let Some(frame) = self.frame_stack.iter().last() {
|
||||||
self.frame_offset -= frame.function.fixed_stack_size() as usize;
|
self.frame_offset -= frame.function().fixed_stack_size() as usize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -550,24 +550,6 @@ impl<'a> State<'a, DataValue> for InterpreterState<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_address(&self, addr: &Address) -> Result<(), MemoryError> {
|
|
||||||
match addr.region {
|
|
||||||
AddressRegion::Stack => {
|
|
||||||
let stack_len = self.stack.len() as u64;
|
|
||||||
|
|
||||||
if addr.offset > stack_len {
|
|
||||||
return Err(MemoryError::InvalidEntry {
|
|
||||||
entry: addr.entry,
|
|
||||||
max: self.stack.len() as u64,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => unimplemented!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_pinned_reg(&self) -> DataValue {
|
fn get_pinned_reg(&self) -> DataValue {
|
||||||
self.pinned_reg.clone()
|
self.pinned_reg.clone()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,9 +92,6 @@ pub trait State<'a, V> {
|
|||||||
/// in intermediate global values.
|
/// in intermediate global values.
|
||||||
fn resolve_global_value(&self, gv: GlobalValue) -> Result<V, MemoryError>;
|
fn resolve_global_value(&self, gv: GlobalValue) -> Result<V, MemoryError>;
|
||||||
|
|
||||||
/// Checks if an address is valid and within a known region of memory
|
|
||||||
fn validate_address(&self, address: &Address) -> Result<(), MemoryError>;
|
|
||||||
|
|
||||||
/// Retrieves the current pinned reg value
|
/// Retrieves the current pinned reg value
|
||||||
fn get_pinned_reg(&self) -> V;
|
fn get_pinned_reg(&self) -> V;
|
||||||
/// Sets a value for the pinned reg
|
/// Sets a value for the pinned reg
|
||||||
@@ -231,10 +228,6 @@ where
|
|||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_address(&self, _addr: &Address) -> Result<(), MemoryError> {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_pinned_reg(&self) -> V {
|
fn get_pinned_reg(&self) -> V {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -563,15 +563,13 @@ where
|
|||||||
Opcode::DynamicStackAddr => unimplemented!("DynamicStackSlot"),
|
Opcode::DynamicStackAddr => unimplemented!("DynamicStackSlot"),
|
||||||
Opcode::DynamicStackLoad => unimplemented!("DynamicStackLoad"),
|
Opcode::DynamicStackLoad => unimplemented!("DynamicStackLoad"),
|
||||||
Opcode::DynamicStackStore => unimplemented!("DynamicStackStore"),
|
Opcode::DynamicStackStore => unimplemented!("DynamicStackStore"),
|
||||||
Opcode::GlobalValue => {
|
Opcode::GlobalValue | Opcode::SymbolValue | Opcode::TlsValue => {
|
||||||
if let InstructionData::UnaryGlobalValue { global_value, .. } = inst {
|
if let InstructionData::UnaryGlobalValue { global_value, .. } = inst {
|
||||||
assign_or_memtrap(state.resolve_global_value(global_value))
|
assign_or_memtrap(state.resolve_global_value(global_value))
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Opcode::SymbolValue => unimplemented!("SymbolValue"),
|
|
||||||
Opcode::TlsValue => unimplemented!("TlsValue"),
|
|
||||||
Opcode::GetPinnedReg => assign(state.get_pinned_reg()),
|
Opcode::GetPinnedReg => assign(state.get_pinned_reg()),
|
||||||
Opcode::SetPinnedReg => {
|
Opcode::SetPinnedReg => {
|
||||||
let arg0 = arg(0)?;
|
let arg0 = arg(0)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user