mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-12 08:31:21 +00:00
Merge branch 'master' into feature/trace-macro
This commit is contained in:
@ -39,16 +39,26 @@ impl Token {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum MemoryBoundCheckMode {
|
||||
Default,
|
||||
Enable,
|
||||
Disable,
|
||||
}
|
||||
|
||||
impl Default for MemoryBoundCheckMode {
|
||||
fn default() -> MemoryBoundCheckMode {
|
||||
MemoryBoundCheckMode::Default
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration data for the compiler
|
||||
#[derive(Default)]
|
||||
pub struct CompilerConfig {
|
||||
/// Symbol information generated from emscripten; used for more detailed debug messages
|
||||
pub symbol_map: Option<HashMap<u32, String>>,
|
||||
}
|
||||
|
||||
impl Default for CompilerConfig {
|
||||
fn default() -> CompilerConfig {
|
||||
CompilerConfig { symbol_map: None }
|
||||
}
|
||||
pub memory_bound_check_mode: MemoryBoundCheckMode,
|
||||
pub enforce_stack_check: bool,
|
||||
}
|
||||
|
||||
pub trait Compiler {
|
||||
@ -80,6 +90,16 @@ pub trait RunnableModule: Send + Sync {
|
||||
fn get_trampoline(&self, info: &ModuleInfo, sig_index: SigIndex) -> Option<Wasm>;
|
||||
|
||||
unsafe fn do_early_trap(&self, data: Box<dyn Any>) -> !;
|
||||
|
||||
/// Returns the machine code associated with this module.
|
||||
fn get_code(&self) -> Option<&[u8]> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Returns the beginning offsets of all functions, including import trampolines.
|
||||
fn get_offsets(&self) -> Option<Vec<usize>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CacheGen: Send + Sync {
|
||||
|
@ -456,10 +456,17 @@ fn import_functions(
|
||||
});
|
||||
}
|
||||
None => {
|
||||
link_errors.push(LinkError::ImportNotFound {
|
||||
namespace: namespace.to_string(),
|
||||
name: name.to_string(),
|
||||
});
|
||||
if imports.allow_missing_functions {
|
||||
functions.push(vm::ImportedFunc {
|
||||
func: ::std::ptr::null(),
|
||||
vmctx: ::std::ptr::null_mut(),
|
||||
});
|
||||
} else {
|
||||
link_errors.push(LinkError::ImportNotFound {
|
||||
namespace: namespace.to_string(),
|
||||
name: name.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,21 +42,29 @@ impl fmt::Debug for InternalEvent {
|
||||
pub struct BkptInfo {}
|
||||
|
||||
pub trait ModuleCodeGenerator<FCG: FunctionCodeGenerator<E>, RM: RunnableModule, E: Debug> {
|
||||
/// Creates a new module code generator.
|
||||
fn new() -> Self;
|
||||
|
||||
/// Returns the backend id associated with this MCG.
|
||||
fn backend_id() -> Backend;
|
||||
fn check_precondition(&mut self, module_info: &ModuleInfo) -> Result<(), E>;
|
||||
|
||||
/// Creates a new function and returns the function-scope code generator for it.
|
||||
fn next_function(&mut self) -> Result<&mut FCG, E>;
|
||||
fn finalize(self, module_info: &ModuleInfo) -> Result<(RM, Box<dyn CacheGen>), E>;
|
||||
fn feed_signatures(&mut self, signatures: Map<SigIndex, FuncSig>) -> Result<(), E>;
|
||||
|
||||
/// Sets function signatures.
|
||||
fn feed_function_signatures(&mut self, assoc: Map<FuncIndex, SigIndex>) -> Result<(), E>;
|
||||
|
||||
/// Feeds the compiler config.
|
||||
fn feed_compiler_config(&mut self, _config: &CompilerConfig) -> Result<(), E> {
|
||||
Ok(())
|
||||
}
|
||||
/// Adds an import function.
|
||||
fn feed_import_function(&mut self) -> Result<(), E>;
|
||||
fn feed_signatures(&mut self, signatures: Map<SigIndex, FuncSig>) -> Result<(), E>;
|
||||
/// Sets function signatures.
|
||||
fn feed_function_signatures(&mut self, assoc: Map<FuncIndex, SigIndex>) -> Result<(), E>;
|
||||
/// Checks the precondition for a module.
|
||||
fn check_precondition(&mut self, module_info: &ModuleInfo) -> Result<(), E>;
|
||||
/// Creates a new function and returns the function-scope code generator for it.
|
||||
fn next_function(&mut self) -> Result<&mut FCG, E>;
|
||||
/// Finalizes this module.
|
||||
fn finalize(self, module_info: &ModuleInfo) -> Result<(RM, Box<dyn CacheGen>), E>;
|
||||
|
||||
/// Creates a module from cache.
|
||||
unsafe fn from_cache(cache: Artifact, _: Token) -> Result<ModuleInner, CacheError>;
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,7 @@ impl IsExport for Export {
|
||||
pub struct ImportObject {
|
||||
map: Rc<RefCell<HashMap<String, Box<dyn LikeNamespace>>>>,
|
||||
state_creator: Option<Rc<Fn() -> (*mut c_void, fn(*mut c_void))>>,
|
||||
pub allow_missing_functions: bool,
|
||||
}
|
||||
|
||||
impl ImportObject {
|
||||
@ -55,6 +56,7 @@ impl ImportObject {
|
||||
Self {
|
||||
map: Rc::new(RefCell::new(HashMap::new())),
|
||||
state_creator: None,
|
||||
allow_missing_functions: false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,6 +67,7 @@ impl ImportObject {
|
||||
Self {
|
||||
map: Rc::new(RefCell::new(HashMap::new())),
|
||||
state_creator: Some(Rc::new(state_creator)),
|
||||
allow_missing_functions: false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,6 +119,7 @@ impl ImportObject {
|
||||
Self {
|
||||
map: Rc::clone(&self.map),
|
||||
state_creator: self.state_creator.clone(),
|
||||
allow_missing_functions: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,9 +5,11 @@ use crate::{
|
||||
export::{Context, Export, ExportIter, FuncPointer},
|
||||
global::Global,
|
||||
import::{ImportObject, LikeNamespace},
|
||||
loader::Loader,
|
||||
memory::Memory,
|
||||
module::{ExportIndex, Module, ModuleInfo, ModuleInner},
|
||||
sig_registry::SigRegistry,
|
||||
structures::TypedIndex,
|
||||
table::Table,
|
||||
typed_func::{Func, Wasm, WasmTrapInfo, WasmTypeList},
|
||||
types::{FuncIndex, FuncSig, GlobalIndex, LocalOrImport, MemoryIndex, TableIndex, Type, Value},
|
||||
@ -38,7 +40,7 @@ impl Drop for InstanceInner {
|
||||
///
|
||||
/// [`ImportObject`]: struct.ImportObject.html
|
||||
pub struct Instance {
|
||||
module: Arc<ModuleInner>,
|
||||
pub module: Arc<ModuleInner>,
|
||||
inner: Box<InstanceInner>,
|
||||
#[allow(dead_code)]
|
||||
import_object: ImportObject,
|
||||
@ -127,6 +129,12 @@ impl Instance {
|
||||
Ok(instance)
|
||||
}
|
||||
|
||||
pub fn load<T: Loader>(&self, loader: T) -> ::std::result::Result<T::Instance, T::Error> {
|
||||
loader.load(&*self.module.runnable_module, &self.module.info, unsafe {
|
||||
&*self.inner.vmctx
|
||||
})
|
||||
}
|
||||
|
||||
/// Through generic magic and the awe-inspiring power of traits, we bring you...
|
||||
///
|
||||
/// # "Func"
|
||||
@ -214,6 +222,26 @@ impl Instance {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_func(&self, name: &str) -> ResolveResult<usize> {
|
||||
let export_index =
|
||||
self.module
|
||||
.info
|
||||
.exports
|
||||
.get(name)
|
||||
.ok_or_else(|| ResolveError::ExportNotFound {
|
||||
name: name.to_string(),
|
||||
})?;
|
||||
|
||||
if let ExportIndex::Func(func_index) = export_index {
|
||||
Ok(func_index.index())
|
||||
} else {
|
||||
Err(ResolveError::ExportWrongType {
|
||||
name: name.to_string(),
|
||||
}
|
||||
.into())
|
||||
}
|
||||
}
|
||||
|
||||
/// This returns the representation of a function that can be called
|
||||
/// safely.
|
||||
///
|
||||
|
@ -21,6 +21,7 @@ pub mod export;
|
||||
pub mod global;
|
||||
pub mod import;
|
||||
pub mod instance;
|
||||
pub mod loader;
|
||||
pub mod memory;
|
||||
pub mod module;
|
||||
pub mod parse;
|
||||
|
169
lib/runtime-core/src/loader.rs
Normal file
169
lib/runtime-core/src/loader.rs
Normal file
@ -0,0 +1,169 @@
|
||||
use crate::{backend::RunnableModule, module::ModuleInfo, types::Value, vm::Ctx};
|
||||
#[cfg(unix)]
|
||||
use libc::{mmap, mprotect, munmap, MAP_ANON, MAP_PRIVATE, PROT_EXEC, PROT_READ, PROT_WRITE};
|
||||
use std::{
|
||||
fmt::Debug,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
pub trait Loader {
|
||||
type Instance: Instance;
|
||||
type Error: Debug;
|
||||
|
||||
fn load(
|
||||
&self,
|
||||
rm: &dyn RunnableModule,
|
||||
module: &ModuleInfo,
|
||||
ctx: &Ctx,
|
||||
) -> Result<Self::Instance, Self::Error>;
|
||||
}
|
||||
|
||||
pub trait Instance {
|
||||
type Error: Debug;
|
||||
fn call(&mut self, id: usize, args: &[Value]) -> Result<u64, Self::Error>;
|
||||
fn read_memory(&mut self, _offset: u32, _len: u32) -> Result<Vec<u8>, Self::Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn write_memory(&mut self, _offset: u32, _len: u32, _buf: &[u8]) -> Result<(), Self::Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LocalLoader;
|
||||
|
||||
impl Loader for LocalLoader {
|
||||
type Instance = LocalInstance;
|
||||
type Error = String;
|
||||
|
||||
fn load(
|
||||
&self,
|
||||
rm: &dyn RunnableModule,
|
||||
_module: &ModuleInfo,
|
||||
_ctx: &Ctx,
|
||||
) -> Result<Self::Instance, Self::Error> {
|
||||
let code = rm.get_code().unwrap();
|
||||
let mut code_mem = CodeMemory::new(code.len());
|
||||
code_mem[..code.len()].copy_from_slice(code);
|
||||
code_mem.make_executable();
|
||||
|
||||
Ok(LocalInstance {
|
||||
code: code_mem,
|
||||
offsets: rm.get_offsets().unwrap(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LocalInstance {
|
||||
code: CodeMemory,
|
||||
offsets: Vec<usize>,
|
||||
}
|
||||
|
||||
impl Instance for LocalInstance {
|
||||
type Error = String;
|
||||
fn call(&mut self, id: usize, args: &[Value]) -> Result<u64, Self::Error> {
|
||||
let offset = self.offsets[id];
|
||||
let addr: *const u8 = unsafe { self.code.as_ptr().offset(offset as isize) };
|
||||
use std::mem::transmute;
|
||||
Ok(unsafe {
|
||||
match args.len() {
|
||||
0 => (transmute::<_, extern "C" fn() -> u64>(addr))(),
|
||||
1 => (transmute::<_, extern "C" fn(u64) -> u64>(addr))(args[0].to_u64()),
|
||||
2 => (transmute::<_, extern "C" fn(u64, u64) -> u64>(addr))(
|
||||
args[0].to_u64(),
|
||||
args[1].to_u64(),
|
||||
),
|
||||
3 => (transmute::<_, extern "C" fn(u64, u64, u64) -> u64>(addr))(
|
||||
args[0].to_u64(),
|
||||
args[1].to_u64(),
|
||||
args[2].to_u64(),
|
||||
),
|
||||
4 => (transmute::<_, extern "C" fn(u64, u64, u64, u64) -> u64>(addr))(
|
||||
args[0].to_u64(),
|
||||
args[1].to_u64(),
|
||||
args[2].to_u64(),
|
||||
args[3].to_u64(),
|
||||
),
|
||||
5 => (transmute::<_, extern "C" fn(u64, u64, u64, u64, u64) -> u64>(addr))(
|
||||
args[0].to_u64(),
|
||||
args[1].to_u64(),
|
||||
args[2].to_u64(),
|
||||
args[3].to_u64(),
|
||||
args[4].to_u64(),
|
||||
),
|
||||
_ => return Err("too many arguments".into()),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CodeMemory {
|
||||
ptr: *mut u8,
|
||||
size: usize,
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
impl CodeMemory {
|
||||
pub fn new(_size: usize) -> CodeMemory {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
pub fn make_executable(&mut self) {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl CodeMemory {
|
||||
pub fn new(size: usize) -> CodeMemory {
|
||||
fn round_up_to_page_size(size: usize) -> usize {
|
||||
(size + (4096 - 1)) & !(4096 - 1)
|
||||
}
|
||||
let size = round_up_to_page_size(size);
|
||||
let ptr = unsafe {
|
||||
mmap(
|
||||
::std::ptr::null_mut(),
|
||||
size,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANON,
|
||||
-1,
|
||||
0,
|
||||
)
|
||||
};
|
||||
if ptr as isize == -1 {
|
||||
panic!("cannot allocate code memory");
|
||||
}
|
||||
CodeMemory {
|
||||
ptr: ptr as _,
|
||||
size: size,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_executable(&mut self) {
|
||||
if unsafe { mprotect(self.ptr as _, self.size, PROT_READ | PROT_EXEC) } != 0 {
|
||||
panic!("cannot set code memory to executable");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
impl Drop for CodeMemory {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
munmap(self.ptr as _, self.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for CodeMemory {
|
||||
type Target = [u8];
|
||||
fn deref(&self) -> &[u8] {
|
||||
unsafe { ::std::slice::from_raw_parts(self.ptr, self.size) }
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for CodeMemory {
|
||||
fn deref_mut(&mut self) -> &mut [u8] {
|
||||
unsafe { ::std::slice::from_raw_parts_mut(self.ptr, self.size) }
|
||||
}
|
||||
}
|
@ -53,6 +53,8 @@ pub fn read_module<
|
||||
middlewares: &mut MiddlewareChain,
|
||||
compiler_config: &CompilerConfig,
|
||||
) -> Result<ModuleInfo, LoadError> {
|
||||
mcg.feed_compiler_config(compiler_config)
|
||||
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||
let mut info = ModuleInfo {
|
||||
memories: Map::new(),
|
||||
globals: Map::new(),
|
||||
|
@ -45,6 +45,15 @@ impl Value {
|
||||
Value::F64(_) => Type::F64,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_u64(&self) -> u64 {
|
||||
match *self {
|
||||
Value::I32(x) => x as u32 as u64,
|
||||
Value::I64(x) => x as u64,
|
||||
Value::F32(x) => f32::to_bits(x) as u64,
|
||||
Value::F64(x) => f64::to_bits(x),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i32> for Value {
|
||||
|
@ -1,9 +1,10 @@
|
||||
pub use crate::backing::{ImportBacking, LocalBacking};
|
||||
use crate::{
|
||||
memory::Memory,
|
||||
module::ModuleInner,
|
||||
memory::{Memory, MemoryType},
|
||||
module::{ModuleInfo, ModuleInner},
|
||||
structures::TypedIndex,
|
||||
types::{LocalOrImport, MemoryIndex},
|
||||
vmcalls,
|
||||
};
|
||||
use std::{ffi::c_void, mem, ptr};
|
||||
|
||||
@ -25,7 +26,7 @@ use hashbrown::HashMap;
|
||||
#[repr(C)]
|
||||
pub struct Ctx {
|
||||
// `internal` must be the first field of `Ctx`.
|
||||
pub(crate) internal: InternalCtx,
|
||||
pub internal: InternalCtx,
|
||||
|
||||
pub(crate) local_functions: *const *const Func,
|
||||
|
||||
@ -84,6 +85,83 @@ pub struct InternalCtx {
|
||||
/// signature id. This is used to allow call-indirect to other
|
||||
/// modules safely.
|
||||
pub dynamic_sigindices: *const SigId,
|
||||
|
||||
pub intrinsics: *const Intrinsics,
|
||||
|
||||
pub stack_lower_bound: *mut u8,
|
||||
|
||||
pub memory_base: *mut u8,
|
||||
pub memory_bound: usize,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Intrinsics {
|
||||
pub memory_grow: *const Func,
|
||||
pub memory_size: *const Func,
|
||||
/*pub memory_grow: unsafe extern "C" fn(
|
||||
ctx: &mut Ctx,
|
||||
memory_index: usize,
|
||||
delta: Pages,
|
||||
) -> i32,
|
||||
pub memory_size: unsafe extern "C" fn(
|
||||
ctx: &Ctx,
|
||||
memory_index: usize,
|
||||
) -> Pages,*/
|
||||
}
|
||||
|
||||
unsafe impl Send for Intrinsics {}
|
||||
unsafe impl Sync for Intrinsics {}
|
||||
|
||||
impl Intrinsics {
|
||||
#[allow(clippy::erasing_op)]
|
||||
pub fn offset_memory_grow() -> u8 {
|
||||
(0 * ::std::mem::size_of::<usize>()) as u8
|
||||
}
|
||||
pub fn offset_memory_size() -> u8 {
|
||||
(1 * ::std::mem::size_of::<usize>()) as u8
|
||||
}
|
||||
}
|
||||
|
||||
pub static INTRINSICS_LOCAL_STATIC_MEMORY: Intrinsics = Intrinsics {
|
||||
memory_grow: vmcalls::local_static_memory_grow as _,
|
||||
memory_size: vmcalls::local_static_memory_size as _,
|
||||
};
|
||||
pub static INTRINSICS_LOCAL_DYNAMIC_MEMORY: Intrinsics = Intrinsics {
|
||||
memory_grow: vmcalls::local_dynamic_memory_grow as _,
|
||||
memory_size: vmcalls::local_dynamic_memory_size as _,
|
||||
};
|
||||
pub static INTRINSICS_IMPORTED_STATIC_MEMORY: Intrinsics = Intrinsics {
|
||||
memory_grow: vmcalls::imported_static_memory_grow as _,
|
||||
memory_size: vmcalls::imported_static_memory_size as _,
|
||||
};
|
||||
pub static INTRINSICS_IMPORTED_DYNAMIC_MEMORY: Intrinsics = Intrinsics {
|
||||
memory_grow: vmcalls::imported_dynamic_memory_grow as _,
|
||||
memory_size: vmcalls::imported_dynamic_memory_size as _,
|
||||
};
|
||||
|
||||
fn get_intrinsics_for_module(m: &ModuleInfo) -> *const Intrinsics {
|
||||
if m.memories.len() == 0 && m.imported_memories.len() == 0 {
|
||||
::std::ptr::null()
|
||||
} else {
|
||||
match MemoryIndex::new(0).local_or_import(m) {
|
||||
LocalOrImport::Local(local_mem_index) => {
|
||||
let mem_desc = &m.memories[local_mem_index];
|
||||
match mem_desc.memory_type() {
|
||||
MemoryType::Dynamic => &INTRINSICS_LOCAL_DYNAMIC_MEMORY,
|
||||
MemoryType::Static => &INTRINSICS_LOCAL_STATIC_MEMORY,
|
||||
MemoryType::SharedStatic => unimplemented!(),
|
||||
}
|
||||
}
|
||||
LocalOrImport::Import(import_mem_index) => {
|
||||
let mem_desc = &m.imported_memories[import_mem_index].1;
|
||||
match mem_desc.memory_type() {
|
||||
MemoryType::Dynamic => &INTRINSICS_IMPORTED_DYNAMIC_MEMORY,
|
||||
MemoryType::Static => &INTRINSICS_IMPORTED_STATIC_MEMORY,
|
||||
MemoryType::SharedStatic => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Ctx {
|
||||
@ -93,6 +171,16 @@ impl Ctx {
|
||||
import_backing: &mut ImportBacking,
|
||||
module: &ModuleInner,
|
||||
) -> Self {
|
||||
let (mem_base, mem_bound): (*mut u8, usize) =
|
||||
if module.info.memories.len() == 0 && module.info.imported_memories.len() == 0 {
|
||||
(::std::ptr::null_mut(), 0)
|
||||
} else {
|
||||
let mem = match MemoryIndex::new(0).local_or_import(&module.info) {
|
||||
LocalOrImport::Local(index) => local_backing.vm_memories[index],
|
||||
LocalOrImport::Import(index) => import_backing.vm_memories[index],
|
||||
};
|
||||
((*mem).base, (*mem).bound)
|
||||
};
|
||||
Self {
|
||||
internal: InternalCtx {
|
||||
memories: local_backing.vm_memories.as_mut_ptr(),
|
||||
@ -105,6 +193,13 @@ impl Ctx {
|
||||
imported_funcs: import_backing.vm_functions.as_mut_ptr(),
|
||||
|
||||
dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(),
|
||||
|
||||
intrinsics: get_intrinsics_for_module(&module.info),
|
||||
|
||||
stack_lower_bound: ::std::ptr::null_mut(),
|
||||
|
||||
memory_base: mem_base,
|
||||
memory_bound: mem_bound,
|
||||
},
|
||||
local_functions: local_backing.local_functions.as_ptr(),
|
||||
|
||||
@ -125,6 +220,16 @@ impl Ctx {
|
||||
data: *mut c_void,
|
||||
data_finalizer: fn(*mut c_void),
|
||||
) -> Self {
|
||||
let (mem_base, mem_bound): (*mut u8, usize) =
|
||||
if module.info.memories.len() == 0 && module.info.imported_memories.len() == 0 {
|
||||
(::std::ptr::null_mut(), 0)
|
||||
} else {
|
||||
let mem = match MemoryIndex::new(0).local_or_import(&module.info) {
|
||||
LocalOrImport::Local(index) => local_backing.vm_memories[index],
|
||||
LocalOrImport::Import(index) => import_backing.vm_memories[index],
|
||||
};
|
||||
((*mem).base, (*mem).bound)
|
||||
};
|
||||
Self {
|
||||
internal: InternalCtx {
|
||||
memories: local_backing.vm_memories.as_mut_ptr(),
|
||||
@ -137,6 +242,13 @@ impl Ctx {
|
||||
imported_funcs: import_backing.vm_functions.as_mut_ptr(),
|
||||
|
||||
dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(),
|
||||
|
||||
intrinsics: get_intrinsics_for_module(&module.info),
|
||||
|
||||
stack_lower_bound: ::std::ptr::null_mut(),
|
||||
|
||||
memory_base: mem_base,
|
||||
memory_bound: mem_bound,
|
||||
},
|
||||
local_functions: local_backing.local_functions.as_ptr(),
|
||||
|
||||
@ -186,6 +298,11 @@ impl Ctx {
|
||||
pub unsafe fn borrow_symbol_map(&self) -> &Option<HashMap<u32, String>> {
|
||||
&(*self.module).info.em_symbol_map
|
||||
}
|
||||
|
||||
/// Returns the number of dynamic sigindices.
|
||||
pub fn dynamic_sigindice_count(&self) -> usize {
|
||||
unsafe { (*self.local_backing).dynamic_sigindices.len() }
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
@ -223,9 +340,25 @@ impl Ctx {
|
||||
7 * (mem::size_of::<usize>() as u8)
|
||||
}
|
||||
|
||||
pub fn offset_local_functions() -> u8 {
|
||||
pub fn offset_intrinsics() -> u8 {
|
||||
8 * (mem::size_of::<usize>() as u8)
|
||||
}
|
||||
|
||||
pub fn offset_stack_lower_bound() -> u8 {
|
||||
9 * (mem::size_of::<usize>() as u8)
|
||||
}
|
||||
|
||||
pub fn offset_memory_base() -> u8 {
|
||||
10 * (mem::size_of::<usize>() as u8)
|
||||
}
|
||||
|
||||
pub fn offset_memory_bound() -> u8 {
|
||||
11 * (mem::size_of::<usize>() as u8)
|
||||
}
|
||||
|
||||
pub fn offset_local_functions() -> u8 {
|
||||
12 * (mem::size_of::<usize>() as u8)
|
||||
}
|
||||
}
|
||||
|
||||
enum InnerFunc {}
|
||||
@ -419,6 +552,26 @@ mod vm_offset_tests {
|
||||
offset_of!(InternalCtx => imported_funcs).get_byte_offset(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Ctx::offset_intrinsics() as usize,
|
||||
offset_of!(InternalCtx => intrinsics).get_byte_offset(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Ctx::offset_stack_lower_bound() as usize,
|
||||
offset_of!(InternalCtx => stack_lower_bound).get_byte_offset(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Ctx::offset_memory_base() as usize,
|
||||
offset_of!(InternalCtx => memory_base).get_byte_offset(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Ctx::offset_memory_bound() as usize,
|
||||
offset_of!(InternalCtx => memory_bound).get_byte_offset(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
Ctx::offset_local_functions() as usize,
|
||||
offset_of!(Ctx => local_functions).get_byte_offset(),
|
||||
|
@ -20,10 +20,15 @@ pub unsafe extern "C" fn local_static_memory_grow(
|
||||
let local_memory = *ctx.internal.memories.add(memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut StaticMemory;
|
||||
|
||||
match (*memory).grow(delta, &mut *local_memory) {
|
||||
let ret = match (*memory).grow(delta, &mut *local_memory) {
|
||||
Ok(old) => old.0 as i32,
|
||||
Err(_) => -1,
|
||||
}
|
||||
};
|
||||
|
||||
ctx.internal.memory_base = (*local_memory).base;
|
||||
ctx.internal.memory_bound = (*local_memory).bound;
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn local_static_memory_size(
|
||||
@ -44,10 +49,15 @@ pub unsafe extern "C" fn local_dynamic_memory_grow(
|
||||
let local_memory = *ctx.internal.memories.add(memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut DynamicMemory;
|
||||
|
||||
match (*memory).grow(delta, &mut *local_memory) {
|
||||
let ret = match (*memory).grow(delta, &mut *local_memory) {
|
||||
Ok(old) => old.0 as i32,
|
||||
Err(_) => -1,
|
||||
}
|
||||
};
|
||||
|
||||
ctx.internal.memory_base = (*local_memory).base;
|
||||
ctx.internal.memory_bound = (*local_memory).bound;
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn local_dynamic_memory_size(
|
||||
@ -75,10 +85,15 @@ pub unsafe extern "C" fn imported_static_memory_grow(
|
||||
.add(import_memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut StaticMemory;
|
||||
|
||||
match (*memory).grow(delta, &mut *local_memory) {
|
||||
let ret = match (*memory).grow(delta, &mut *local_memory) {
|
||||
Ok(old) => old.0 as i32,
|
||||
Err(_) => -1,
|
||||
}
|
||||
};
|
||||
|
||||
ctx.internal.memory_base = (*local_memory).base;
|
||||
ctx.internal.memory_bound = (*local_memory).bound;
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn imported_static_memory_size(
|
||||
@ -102,10 +117,15 @@ pub unsafe extern "C" fn imported_dynamic_memory_grow(
|
||||
let local_memory = *ctx.internal.imported_memories.add(memory_index.index());
|
||||
let memory = (*local_memory).memory as *mut DynamicMemory;
|
||||
|
||||
match (*memory).grow(delta, &mut *local_memory) {
|
||||
let ret = match (*memory).grow(delta, &mut *local_memory) {
|
||||
Ok(old) => old.0 as i32,
|
||||
Err(_) => -1,
|
||||
}
|
||||
};
|
||||
|
||||
ctx.internal.memory_base = (*local_memory).base;
|
||||
ctx.internal.memory_bound = (*local_memory).bound;
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn imported_dynamic_memory_size(
|
||||
|
Reference in New Issue
Block a user