This commit is contained in:
Sergey Pepyakin
2017-11-27 18:35:28 +03:00
parent e85a8dec42
commit 61c2197bd8
2 changed files with 74 additions and 58 deletions

View File

@ -7,7 +7,7 @@ use builder::module;
use elements::{Module, ExportEntry, Internal, GlobalEntry, GlobalType, use elements::{Module, ExportEntry, Internal, GlobalEntry, GlobalType,
ValueType, InitExpr, Opcode, Opcodes}; ValueType, InitExpr, Opcode, Opcodes};
use interpreter::Error; use interpreter::Error;
use interpreter::native::NATIVE_INDEX_FUNC_MIN; use interpreter::native::{NATIVE_INDEX_FUNC_MIN, UserFunctionExecutor, UserDefinedElements, UserFunctionDescriptor, native_module};
use interpreter::module::{ModuleInstanceInterface, ModuleInstance, ExecutionParams, use interpreter::module::{ModuleInstanceInterface, ModuleInstance, ExecutionParams,
ItemIndex, CallerContext, ExportEntryType, InternalFunctionReference, InternalFunction, FunctionSignature}; ItemIndex, CallerContext, ExportEntryType, InternalFunctionReference, InternalFunction, FunctionSignature};
use interpreter::memory::{MemoryInstance, LINEAR_MEMORY_PAGE_SIZE}; use interpreter::memory::{MemoryInstance, LINEAR_MEMORY_PAGE_SIZE};
@ -74,7 +74,8 @@ const INDEX_FUNC_MIN_NONUSED: u32 = 4;
const INDEX_FUNC_MAX: u32 = NATIVE_INDEX_FUNC_MIN - 1; const INDEX_FUNC_MAX: u32 = NATIVE_INDEX_FUNC_MIN - 1;
/// Emscripten environment parameters. /// Emscripten environment parameters.
pub struct EmscriptenParams { #[derive(Clone)]
pub struct EnvParams {
/// Stack size in bytes. /// Stack size in bytes.
pub total_stack: u32, pub total_stack: u32,
/// Total memory size in bytes. /// Total memory size in bytes.
@ -87,13 +88,29 @@ pub struct EmscriptenParams {
pub static_size: Option<u32>, pub static_size: Option<u32>,
} }
pub struct EmscriptenModuleInstance { struct EmscriptenFunctionExecutor {
_params: EmscriptenParams, params: EnvParams,
}
impl UserFunctionExecutor for EmscriptenFunctionExecutor {
fn execute(
&mut self,
name: &str,
context: CallerContext,
) -> Result<Option<RuntimeValue>, Error> {
match name {
_ => Err(Error::Trap("not implemented".into()).into()),
}
}
}
struct EmscriptenModuleInstance {
_params: EnvParams,
instance: ModuleInstance, instance: ModuleInstance,
} }
impl EmscriptenModuleInstance { impl EmscriptenModuleInstance {
pub fn new(params: EmscriptenParams, module: Module) -> Result<Self, Error> { pub fn new(params: EnvParams, module: Module) -> Result<Self, Error> {
let mut instance = ModuleInstance::new(Weak::default(), "env".into(), module)?; let mut instance = ModuleInstance::new(Weak::default(), "env".into(), module)?;
instance.instantiate(None)?; instance.instantiate(None)?;
@ -176,7 +193,7 @@ impl ModuleInstanceInterface for EmscriptenModuleInstance {
} }
} }
pub fn env_module(params: EmscriptenParams) -> Result<EmscriptenModuleInstance, Error> { pub fn env_module(params: EnvParams) -> Result<Arc<ModuleInstanceInterface>, Error> {
debug_assert!(params.total_stack < params.total_memory); debug_assert!(params.total_stack < params.total_memory);
debug_assert!((params.total_stack % LINEAR_MEMORY_PAGE_SIZE) == 0); debug_assert!((params.total_stack % LINEAR_MEMORY_PAGE_SIZE) == 0);
debug_assert!((params.total_memory % LINEAR_MEMORY_PAGE_SIZE) == 0); debug_assert!((params.total_memory % LINEAR_MEMORY_PAGE_SIZE) == 0);
@ -191,65 +208,64 @@ pub fn env_module(params: EmscriptenParams) -> Result<EmscriptenModuleInstance,
.table() .table()
.with_min(params.table_size) .with_min(params.table_size)
.build() .build()
.with_export(ExportEntry::new("table".into(), Internal::Table(INDEX_TABLE))) .with_export(ExportEntry::new("table".into(), Internal::Table(INDEX_TABLE)));
// globals let module = builder.build();
.with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, false), InitExpr::new(vec![Opcode::I32Const(DEFAULT_STACK_BASE as i32)])))
.with_export(ExportEntry::new("STACK_BASE".into(), Internal::Global(INDEX_GLOBAL_STACK_BASE)))
.with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, false), InitExpr::new(vec![Opcode::I32Const(params.static_size.unwrap_or(DEFAULT_STACK_TOP) as i32)]))) let mut function_executor = EmscriptenFunctionExecutor {
.with_export(ExportEntry::new("STACKTOP".into(), Internal::Global(INDEX_GLOBAL_STACK_TOP))) params: params.clone(),
};
.with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, false), InitExpr::new(vec![Opcode::I32Const((DEFAULT_STACK_BASE + params.total_stack) as i32)]))) const SIGNATURES: &'static [UserFunctionDescriptor] = &[
.with_export(ExportEntry::new("STACK_MAX".into(), Internal::Global(INDEX_GLOBAL_STACK_MAX))) UserFunctionDescriptor::Static(
"getTotalMemory",
&[],
Some(ValueType::I32),
),
UserFunctionDescriptor::Static(
"enlargeMemory",
&[],
Some(ValueType::I32),
),
UserFunctionDescriptor::Static(
"assert",
&[ValueType::I32],
None,
),
UserFunctionDescriptor::Static(
"abort",
&[],
None,
),
];
.with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, false), InitExpr::new(vec![Opcode::I32Const((DEFAULT_STACK_BASE + params.total_stack) as i32)]))) let stack_top = params.static_size.unwrap_or(DEFAULT_STACK_TOP);
.with_export(ExportEntry::new("DYNAMIC_BASE".into(), Internal::Global(INDEX_GLOBAL_DYNAMIC_BASE)))
.with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, false), InitExpr::new(vec![Opcode::I32Const((DEFAULT_STACK_BASE + params.total_stack) as i32)]))) let elements = UserDefinedElements {
.with_export(ExportEntry::new("DYNAMICTOP_PTR".into(), Internal::Global(INDEX_GLOBAL_DYNAMICTOP_PTR))) executor: Some(&mut function_executor),
globals: vec![
("STACK_BASE".into(), Arc::new(VariableInstance::new(false, VariableType::I32, RuntimeValue::I32(stack_top as i32)).unwrap())),
("STACKTOP".into(), Arc::new(VariableInstance::new(false, VariableType::I32, RuntimeValue::I32(stack_top as i32)).unwrap())),
("STACK_MAX".into(), Arc::new(VariableInstance::new(false, VariableType::I32, RuntimeValue::I32((stack_top + params.total_stack) as i32)).unwrap())),
("DYNAMIC_BASE".into(), Arc::new(VariableInstance::new(false, VariableType::I32, RuntimeValue::I32((stack_top + params.total_stack) as i32)).unwrap())),
("DYNAMICTOP_PTR".into(), Arc::new(VariableInstance::new(false, VariableType::I32, RuntimeValue::I32((stack_top + params.total_stack) as i32)).unwrap())),
("TOTAL_MEMORY".into(), Arc::new(VariableInstance::new(false, VariableType::I32, RuntimeValue::I32(params.total_memory as i32)).unwrap())),
("ABORT".into(), Arc::new(VariableInstance::new(false, VariableType::I32, RuntimeValue::I32(0)).unwrap())),
("EXITSTATUS".into(), Arc::new(VariableInstance::new(false, VariableType::I32, RuntimeValue::I32(0)).unwrap())),
("tableBase".into(), Arc::new(VariableInstance::new(false, VariableType::I32, RuntimeValue::I32(DEFAULT_TABLE_BASE as i32)).unwrap())),
("memoryBase".into(), Arc::new(VariableInstance::new(false, VariableType::I32, RuntimeValue::I32(DEFAULT_MEMORY_BASE as i32)).unwrap())),
].into_iter().collect(),
functions: ::std::borrow::Cow::from(SIGNATURES),
};
.with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, false), InitExpr::new(vec![Opcode::I32Const(params.total_memory as i32)]))) let mut instance = ModuleInstance::new(Weak::default(), "env".into(), module)?;
.with_export(ExportEntry::new("TOTAL_MEMORY".into(), Internal::Global(INDEX_GLOBAL_TOTAL_MEMORY))) instance.instantiate(None)?;
.with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, false), InitExpr::new(vec![Opcode::I32Const(0)]))) Ok(Arc::new(native_module(Arc::new(instance), elements)?))
.with_export(ExportEntry::new("ABORT".into(), Internal::Global(INDEX_GLOBAL_ABORT)))
.with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, false), InitExpr::new(vec![Opcode::I32Const(0)])))
.with_export(ExportEntry::new("EXITSTATUS".into(), Internal::Global(INDEX_GLOBAL_EXIT_STATUS)))
.with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, false), InitExpr::new(vec![Opcode::I32Const(DEFAULT_TABLE_BASE as i32)]))) // TODO: what is this?
.with_export(ExportEntry::new("tableBase".into(), Internal::Global(INDEX_GLOBAL_TABLE_BASE)))
.with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, false), InitExpr::new(vec![Opcode::I32Const(DEFAULT_MEMORY_BASE as i32)]))) // TODO: what is this?
.with_export(ExportEntry::new("memoryBase".into(), Internal::Global(INDEX_GLOBAL_MEMORY_BASE)))
// functions
.function()
.signature().build()
.body().with_opcodes(Opcodes::new(vec![Opcode::Unreachable, Opcode::End])).build()
.build()
.with_export(ExportEntry::new("abort".into(), Internal::Function(INDEX_FUNC_ABORT)))
.function()
.signature().param().i32().build()
.body().with_opcodes(Opcodes::new(vec![Opcode::Unreachable, Opcode::End])).build()
.build()
.with_export(ExportEntry::new("assert".into(), Internal::Function(INDEX_FUNC_ASSERT)))
.function()
.signature().return_type().i32().build()
.body().with_opcodes(Opcodes::new(vec![Opcode::Unreachable, Opcode::End])).build()
.build()
.with_export(ExportEntry::new("enlargeMemory".into(), Internal::Function(INDEX_FUNC_ENLARGE_MEMORY)))
.function()
.signature().return_type().i32().build()
.body().with_opcodes(Opcodes::new(vec![Opcode::Unreachable, Opcode::End])).build()
.build()
.with_export(ExportEntry::new("getTotalMemory".into(), Internal::Function(INDEX_FUNC_GET_TOTAL_MEMORY)));
EmscriptenModuleInstance::new(params, builder.build())
} }
impl Default for EmscriptenParams { impl Default for EnvParams {
fn default() -> Self { fn default() -> Self {
EmscriptenParams { EnvParams {
total_stack: DEFAULT_TOTAL_STACK, total_stack: DEFAULT_TOTAL_STACK,
total_memory: DEFAULT_TOTAL_MEMORY, total_memory: DEFAULT_TOTAL_MEMORY,
allow_memory_growth: DEFAULT_ALLOW_MEMORY_GROWTH, allow_memory_growth: DEFAULT_ALLOW_MEMORY_GROWTH,
@ -259,7 +275,7 @@ impl Default for EmscriptenParams {
} }
} }
impl EmscriptenParams { impl EnvParams {
fn max_memory(&self) -> Option<u32> { fn max_memory(&self) -> Option<u32> {
if self.allow_memory_growth { None } else { Some(self.total_memory) } if self.allow_memory_growth { None } else { Some(self.total_memory) }
} }

View File

@ -69,7 +69,7 @@ impl ProgramInstanceEssence {
pub fn with_env_params(env_params: EmscriptenParams) -> Result<Self, Error> { pub fn with_env_params(env_params: EmscriptenParams) -> Result<Self, Error> {
let env_mod = env_module(env_params)?; let env_mod = env_module(env_params)?;
Ok(ProgramInstanceEssence::with_env_module(Arc::new(env_mod))) Ok(ProgramInstanceEssence::with_env_module(env_mod))
} }
pub fn with_env_module(env_module: Arc<ModuleInstanceInterface>) -> Self { pub fn with_env_module(env_module: Arc<ModuleInstanceInterface>) -> Self {