From bada17beabd7b266a21c6f6c03c89e24e599a773 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 7 Apr 2023 17:22:13 +0200 Subject: [PATCH] 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 --- cranelift/interpreter/src/frame.rs | 7 ++++- cranelift/interpreter/src/interpreter.rs | 36 ++++++------------------ cranelift/interpreter/src/state.rs | 7 ----- cranelift/interpreter/src/step.rs | 4 +-- 4 files changed, 16 insertions(+), 38 deletions(-) diff --git a/cranelift/interpreter/src/frame.rs b/cranelift/interpreter/src/frame.rs index 4270225af3..c675168231 100644 --- a/cranelift/interpreter/src/frame.rs +++ b/cranelift/interpreter/src/frame.rs @@ -12,7 +12,7 @@ pub(crate) type Entries = Vec>; #[derive(Debug)] pub struct Frame<'a> { /// 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 /// index into the Vec, meaning some slots may be unused. registers: Entries, @@ -100,6 +100,11 @@ impl<'a> Frame<'a> { pub fn entries_mut(&mut self) -> &mut [Option] { &mut self.registers } + + /// Accessor for the [`Function`] of this frame. + pub fn function(&self) -> &'a Function { + self.function + } } #[cfg(test)] diff --git a/cranelift/interpreter/src/interpreter.rs b/cranelift/interpreter/src/interpreter.rs index 06b7e5f5a2..8b4589302a 100644 --- a/cranelift/interpreter/src/interpreter.rs +++ b/cranelift/interpreter/src/interpreter.rs @@ -93,7 +93,7 @@ impl<'a> Interpreter<'a> { /// instructions, which may continue in other blocks, until the function returns. fn block(&mut self, block: Block) -> Result, InterpreterError> { trace!("Block: {}", block); - let function = self.state.current_frame_mut().function; + let function = self.state.current_frame_mut().function(); let layout = &function.layout; let mut maybe_inst = layout.first_inst(block); while let Some(inst) = maybe_inst { @@ -257,10 +257,10 @@ impl<'a> InterpreterState<'a> { impl<'a> State<'a, DataValue> for InterpreterState<'a> { fn get_function(&self, func_ref: FuncRef) -> Option<&'a Function> { 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 { - self.current_frame().function + self.current_frame().function() } fn get_libcall_handler(&self) -> LibCallHandler { @@ -269,7 +269,7 @@ impl<'a> State<'a, DataValue> for InterpreterState<'a> { fn push_frame(&mut self, function: &'a Function) { 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 @@ -282,11 +282,11 @@ impl<'a> State<'a, DataValue> for InterpreterState<'a> { if let Some(frame) = self.frame_stack.pop() { // Shorten the stack after exiting the frame 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 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 { self.pinned_reg.clone() } @@ -1054,18 +1036,18 @@ mod tests { ss0 = explicit_slot 69 ss1 = explicit_slot 69 ss2 = explicit_slot 69 - + block0: v0 = f32const -0x1.434342p-60 v1 = stack_addr.i64 ss2+24 store notrap aligned v0, v1 return v0 } - + function %u1() -> f32 system_v { sig0 = () -> f32 system_v fn0 = colocated %u2 sig0 - + block0: v57 = call fn0() return v57 diff --git a/cranelift/interpreter/src/state.rs b/cranelift/interpreter/src/state.rs index 5232bc9259..c2ad82bd01 100644 --- a/cranelift/interpreter/src/state.rs +++ b/cranelift/interpreter/src/state.rs @@ -92,9 +92,6 @@ pub trait State<'a, V> { /// in intermediate global values. fn resolve_global_value(&self, gv: GlobalValue) -> Result; - /// 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 fn get_pinned_reg(&self) -> V; /// Sets a value for the pinned reg @@ -231,10 +228,6 @@ where unimplemented!() } - fn validate_address(&self, _addr: &Address) -> Result<(), MemoryError> { - unimplemented!() - } - fn get_pinned_reg(&self) -> V { unimplemented!() } diff --git a/cranelift/interpreter/src/step.rs b/cranelift/interpreter/src/step.rs index 2233c457e9..5f21a800c7 100644 --- a/cranelift/interpreter/src/step.rs +++ b/cranelift/interpreter/src/step.rs @@ -563,15 +563,13 @@ where Opcode::DynamicStackAddr => unimplemented!("DynamicStackSlot"), Opcode::DynamicStackLoad => unimplemented!("DynamicStackLoad"), Opcode::DynamicStackStore => unimplemented!("DynamicStackStore"), - Opcode::GlobalValue => { + Opcode::GlobalValue | Opcode::SymbolValue | Opcode::TlsValue => { if let InstructionData::UnaryGlobalValue { global_value, .. } = inst { assign_or_memtrap(state.resolve_global_value(global_value)) } else { unreachable!() } } - Opcode::SymbolValue => unimplemented!("SymbolValue"), - Opcode::TlsValue => unimplemented!("TlsValue"), Opcode::GetPinnedReg => assign(state.get_pinned_reg()), Opcode::SetPinnedReg => { let arg0 = arg(0)?;