diff --git a/src/interpreter/env.rs b/src/interpreter/env.rs index 651fc6c..e7f54d5 100644 --- a/src/interpreter/env.rs +++ b/src/interpreter/env.rs @@ -81,7 +81,8 @@ pub struct EnvModuleInstance { impl EnvModuleInstance { pub fn new(params: EnvParams, module: Module) -> Result { - let instance = ModuleInstance::new(Weak::default(), "env".into(), module)?; + let mut instance = ModuleInstance::new(Weak::default(), "env".into(), module)?; + instance.instantiate(false, None)?; Ok(EnvModuleInstance { _params: params, @@ -186,7 +187,7 @@ pub fn env_module(params: EnvParams) -> Result { .with_export(ExportEntry::new("DYNAMIC_BASE".into(), Internal::Global(INDEX_GLOBAL_DYNAMIC_BASE))) .with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, true), InitExpr::new(vec![Opcode::I32Const((DEFAULT_STACK_BASE + params.total_stack) as i32)]))) .with_export(ExportEntry::new("DYNAMICTOP_PTR".into(), Internal::Global(INDEX_GLOBAL_DYNAMICTOP_PTR))) - .with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, params.allow_memory_growth), InitExpr::new(vec![Opcode::I32Const(params.total_memory as i32)]))) + .with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, params.allow_memory_growth), InitExpr::new(vec![Opcode::I32Const(params.total_memory as i32)]))) .with_export(ExportEntry::new("TOTAL_MEMORY".into(), Internal::Global(INDEX_GLOBAL_TOTAL_MEMORY))) .with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, true), InitExpr::new(vec![Opcode::I32Const(0)]))) .with_export(ExportEntry::new("ABORT".into(), Internal::Global(INDEX_GLOBAL_ABORT))) diff --git a/src/interpreter/module.rs b/src/interpreter/module.rs index 12e34fa..f490710 100644 --- a/src/interpreter/module.rs +++ b/src/interpreter/module.rs @@ -235,32 +235,30 @@ impl ModuleInstance { } // validate export section - if is_user_module { // TODO: env module exports STACKTOP global, which is mutable => check is failed - if let Some(export_section) = self.module.export_section() { - for export in export_section.entries() { - match export.internal() { - &Internal::Function(function_index) => { - self.require_function(ItemIndex::IndexSpace(function_index)).map(|_| ())?; - self.exports.entry(export.field().into()).or_insert_with(Default::default).push(Internal::Function(function_index)); - }, - &Internal::Global(global_index) => { - self.global(ItemIndex::IndexSpace(global_index), None) - .and_then(|g| if g.is_mutable() { - Err(Error::Validation(format!("trying to export mutable global {}", export.field()))) - } else { - Ok(()) - })?; - self.exports.entry(export.field().into()).or_insert_with(Default::default).push(Internal::Global(global_index)); - }, - &Internal::Memory(memory_index) => { - self.memory(ItemIndex::IndexSpace(memory_index)).map(|_| ())?; - self.exports.entry(export.field().into()).or_insert_with(Default::default).push(Internal::Memory(memory_index)); - }, - &Internal::Table(table_index) => { - self.table(ItemIndex::IndexSpace(table_index)).map(|_| ())?; - self.exports.entry(export.field().into()).or_insert_with(Default::default).push(Internal::Table(table_index)); - }, - } + if let Some(export_section) = self.module.export_section() { + for export in export_section.entries() { + match export.internal() { + &Internal::Function(function_index) => { + self.require_function(ItemIndex::IndexSpace(function_index)).map(|_| ())?; + self.exports.entry(export.field().into()).or_insert_with(Default::default).push(Internal::Function(function_index)); + }, + &Internal::Global(global_index) => { + self.global(ItemIndex::IndexSpace(global_index), None) + .and_then(|g| if g.is_mutable() && is_user_module { + Err(Error::Validation(format!("trying to export mutable global {}", export.field()))) + } else { + Ok(()) + })?; + self.exports.entry(export.field().into()).or_insert_with(Default::default).push(Internal::Global(global_index)); + }, + &Internal::Memory(memory_index) => { + self.memory(ItemIndex::IndexSpace(memory_index)).map(|_| ())?; + self.exports.entry(export.field().into()).or_insert_with(Default::default).push(Internal::Memory(memory_index)); + }, + &Internal::Table(table_index) => { + self.table(ItemIndex::IndexSpace(table_index)).map(|_| ())?; + self.exports.entry(export.field().into()).or_insert_with(Default::default).push(Internal::Table(table_index)); + }, } } } diff --git a/src/interpreter/tests/basics.rs b/src/interpreter/tests/basics.rs index f9bc24e..87b0fb2 100644 --- a/src/interpreter/tests/basics.rs +++ b/src/interpreter/tests/basics.rs @@ -210,6 +210,17 @@ fn single_program_different_modules() { assert_eq!(executor.values, vec![7, 57, 42]); } +#[test] +fn import_env_mutable_global() { + let program = ProgramInstance::new().unwrap(); + + let module = module() + .with_import(ImportEntry::new("env".into(), "STACKTOP".into(), External::Global(GlobalType::new(ValueType::I32, false)))) + .build(); + + program.add_module("main", module, None).unwrap(); +} + #[test] fn env_native_export_entry_type_check() { let program = ProgramInstance::new().unwrap();