cranelift-interpreter: Implement call_indirect and return_call_indirect (#5877)
* cranelift-interpreter: Implement `call_indirect` * cranelift: Fix typo * riscv64: Enable `call_indirect` tests
This commit is contained in:
@@ -3,7 +3,10 @@
|
||||
use crate::address::{Address, AddressSize};
|
||||
use crate::interpreter::LibCallHandler;
|
||||
use cranelift_codegen::data_value::DataValue;
|
||||
use cranelift_codegen::ir::{FuncRef, Function, GlobalValue, StackSlot, Type, Value};
|
||||
use cranelift_codegen::ir::{
|
||||
ExternalName, FuncRef, Function, GlobalValue, LibCall, Signature, StackSlot, Type, Value,
|
||||
};
|
||||
use cranelift_codegen::isa::CallConv;
|
||||
use cranelift_entity::PrimaryMap;
|
||||
use smallvec::SmallVec;
|
||||
use thiserror::Error;
|
||||
@@ -64,6 +67,16 @@ pub trait State<'a, V> {
|
||||
/// stack or to one of the heaps; the number of bytes stored corresponds to the specified [Type].
|
||||
fn checked_store(&mut self, address: Address, v: V) -> Result<(), MemoryError>;
|
||||
|
||||
/// Compute the address of a function given its name.
|
||||
fn function_address(
|
||||
&self,
|
||||
size: AddressSize,
|
||||
name: &ExternalName,
|
||||
) -> Result<Address, MemoryError>;
|
||||
|
||||
/// Retrieve a reference to a [Function] given its address.
|
||||
fn get_function_from_address(&self, address: Address) -> Option<InterpreterFunctionRef<'a>>;
|
||||
|
||||
/// Given a global value, compute the final value for that global value, applying all operations
|
||||
/// in intermediate global values.
|
||||
fn resolve_global_value(&self, gv: GlobalValue) -> Result<V, MemoryError>;
|
||||
@@ -77,6 +90,33 @@ pub trait State<'a, V> {
|
||||
fn set_pinned_reg(&mut self, v: V);
|
||||
}
|
||||
|
||||
pub enum InterpreterFunctionRef<'a> {
|
||||
Function(&'a Function),
|
||||
LibCall(LibCall),
|
||||
}
|
||||
|
||||
impl<'a> InterpreterFunctionRef<'a> {
|
||||
pub fn signature(&self) -> Signature {
|
||||
match self {
|
||||
InterpreterFunctionRef::Function(f) => f.stencil.signature.clone(),
|
||||
// CallConv here is sort of irrelevant, since we don't use it for anything
|
||||
InterpreterFunctionRef::LibCall(lc) => lc.signature(CallConv::SystemV),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a Function> for InterpreterFunctionRef<'a> {
|
||||
fn from(f: &'a Function) -> Self {
|
||||
InterpreterFunctionRef::Function(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LibCall> for InterpreterFunctionRef<'_> {
|
||||
fn from(lc: LibCall) -> Self {
|
||||
InterpreterFunctionRef::LibCall(lc)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum MemoryError {
|
||||
#[error("Invalid DataValue passed as an address: {0}")]
|
||||
@@ -150,6 +190,18 @@ where
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn function_address(
|
||||
&self,
|
||||
_size: AddressSize,
|
||||
_name: &ExternalName,
|
||||
) -> Result<Address, MemoryError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_function_from_address(&self, _address: Address) -> Option<InterpreterFunctionRef<'a>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn resolve_global_value(&self, _gv: GlobalValue) -> Result<V, MemoryError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user