Propagate optional import names to the wasmtime/C API
With the module linking proposal the field name on imports is now optional, and only the module is required to be specified. This commit propagates this API change to the boundary of wasmtime's API, ensuring consumers are aware of what's optional with module linking and what isn't. Note that it's expected that all existing users will either update accordingly or unwrap the result since module linking is presumably disabled.
This commit is contained in:
@@ -581,7 +581,7 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
|
|||||||
&mut self,
|
&mut self,
|
||||||
index: TypeIndex,
|
index: TypeIndex,
|
||||||
module: &'data str,
|
module: &'data str,
|
||||||
field: &'data str,
|
field: Option<&'data str>,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
self.info.functions.len(),
|
self.info.functions.len(),
|
||||||
@@ -591,7 +591,7 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
|
|||||||
self.info.functions.push(Exportable::new(index));
|
self.info.functions.push(Exportable::new(index));
|
||||||
self.info
|
self.info
|
||||||
.imported_funcs
|
.imported_funcs
|
||||||
.push((String::from(module), String::from(field)));
|
.push((String::from(module), String::from(field.unwrap())));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -609,12 +609,12 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
|
|||||||
&mut self,
|
&mut self,
|
||||||
global: Global,
|
global: Global,
|
||||||
module: &'data str,
|
module: &'data str,
|
||||||
field: &'data str,
|
field: Option<&'data str>,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
self.info.globals.push(Exportable::new(global));
|
self.info.globals.push(Exportable::new(global));
|
||||||
self.info
|
self.info
|
||||||
.imported_globals
|
.imported_globals
|
||||||
.push((String::from(module), String::from(field)));
|
.push((String::from(module), String::from(field.unwrap())));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -627,12 +627,12 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
|
|||||||
&mut self,
|
&mut self,
|
||||||
table: Table,
|
table: Table,
|
||||||
module: &'data str,
|
module: &'data str,
|
||||||
field: &'data str,
|
field: Option<&'data str>,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
self.info.tables.push(Exportable::new(table));
|
self.info.tables.push(Exportable::new(table));
|
||||||
self.info
|
self.info
|
||||||
.imported_tables
|
.imported_tables
|
||||||
.push((String::from(module), String::from(field)));
|
.push((String::from(module), String::from(field.unwrap())));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -672,12 +672,12 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment {
|
|||||||
&mut self,
|
&mut self,
|
||||||
memory: Memory,
|
memory: Memory,
|
||||||
module: &'data str,
|
module: &'data str,
|
||||||
field: &'data str,
|
field: Option<&'data str>,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
self.info.memories.push(Exportable::new(memory));
|
self.info.memories.push(Exportable::new(memory));
|
||||||
self.info
|
self.info
|
||||||
.imported_memories
|
.imported_memories
|
||||||
.push((String::from(module), String::from(field)));
|
.push((String::from(module), String::from(field.unwrap())));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -674,7 +674,7 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
|
|||||||
&mut self,
|
&mut self,
|
||||||
index: TypeIndex,
|
index: TypeIndex,
|
||||||
module: &'data str,
|
module: &'data str,
|
||||||
field: &'data str,
|
field: Option<&'data str>,
|
||||||
) -> WasmResult<()>;
|
) -> WasmResult<()>;
|
||||||
|
|
||||||
/// Declares a table import to the environment.
|
/// Declares a table import to the environment.
|
||||||
@@ -682,7 +682,7 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
|
|||||||
&mut self,
|
&mut self,
|
||||||
table: Table,
|
table: Table,
|
||||||
module: &'data str,
|
module: &'data str,
|
||||||
field: &'data str,
|
field: Option<&'data str>,
|
||||||
) -> WasmResult<()>;
|
) -> WasmResult<()>;
|
||||||
|
|
||||||
/// Declares a memory import to the environment.
|
/// Declares a memory import to the environment.
|
||||||
@@ -690,7 +690,7 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
|
|||||||
&mut self,
|
&mut self,
|
||||||
memory: Memory,
|
memory: Memory,
|
||||||
module: &'data str,
|
module: &'data str,
|
||||||
field: &'data str,
|
field: Option<&'data str>,
|
||||||
) -> WasmResult<()>;
|
) -> WasmResult<()>;
|
||||||
|
|
||||||
/// Declares an event import to the environment.
|
/// Declares an event import to the environment.
|
||||||
@@ -698,7 +698,7 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
|
|||||||
&mut self,
|
&mut self,
|
||||||
event: Event,
|
event: Event,
|
||||||
module: &'data str,
|
module: &'data str,
|
||||||
field: &'data str,
|
field: Option<&'data str>,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
drop((event, module, field));
|
drop((event, module, field));
|
||||||
Err(WasmError::Unsupported("wasm events".to_string()))
|
Err(WasmError::Unsupported("wasm events".to_string()))
|
||||||
@@ -709,7 +709,7 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
|
|||||||
&mut self,
|
&mut self,
|
||||||
global: Global,
|
global: Global,
|
||||||
module: &'data str,
|
module: &'data str,
|
||||||
field: &'data str,
|
field: Option<&'data str>,
|
||||||
) -> WasmResult<()>;
|
) -> WasmResult<()>;
|
||||||
|
|
||||||
/// Declares a module import to the environment.
|
/// Declares a module import to the environment.
|
||||||
@@ -717,7 +717,7 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
|
|||||||
&mut self,
|
&mut self,
|
||||||
ty_index: TypeIndex,
|
ty_index: TypeIndex,
|
||||||
module: &'data str,
|
module: &'data str,
|
||||||
field: &'data str,
|
field: Option<&'data str>,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
drop((ty_index, module, field));
|
drop((ty_index, module, field));
|
||||||
Err(WasmError::Unsupported("module linking".to_string()))
|
Err(WasmError::Unsupported("module linking".to_string()))
|
||||||
@@ -728,7 +728,7 @@ pub trait ModuleEnvironment<'data>: TargetEnvironment {
|
|||||||
&mut self,
|
&mut self,
|
||||||
ty_index: TypeIndex,
|
ty_index: TypeIndex,
|
||||||
module: &'data str,
|
module: &'data str,
|
||||||
field: &'data str,
|
field: Option<&'data str>,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
drop((ty_index, module, field));
|
drop((ty_index, module, field));
|
||||||
Err(WasmError::Unsupported("module linking".to_string()))
|
Err(WasmError::Unsupported("module linking".to_string()))
|
||||||
|
|||||||
@@ -156,27 +156,25 @@ pub fn parse_import_section<'data>(
|
|||||||
|
|
||||||
for entry in imports {
|
for entry in imports {
|
||||||
let import = entry?;
|
let import = entry?;
|
||||||
let module_name = import.module;
|
|
||||||
let field_name = import.field.unwrap(); // TODO Handle error when module linking is implemented.
|
|
||||||
match entity_type(import.ty, environ)? {
|
match entity_type(import.ty, environ)? {
|
||||||
EntityType::Function(idx) => {
|
EntityType::Function(idx) => {
|
||||||
environ.declare_func_import(idx, module_name, field_name)?;
|
environ.declare_func_import(idx, import.module, import.field)?;
|
||||||
}
|
}
|
||||||
EntityType::Module(idx) => {
|
EntityType::Module(idx) => {
|
||||||
environ.declare_module_import(idx, module_name, field_name)?;
|
environ.declare_module_import(idx, import.module, import.field)?;
|
||||||
}
|
}
|
||||||
EntityType::Instance(idx) => {
|
EntityType::Instance(idx) => {
|
||||||
environ.declare_instance_import(idx, module_name, field_name)?;
|
environ.declare_instance_import(idx, import.module, import.field)?;
|
||||||
}
|
}
|
||||||
EntityType::Memory(ty) => {
|
EntityType::Memory(ty) => {
|
||||||
environ.declare_memory_import(ty, module_name, field_name)?;
|
environ.declare_memory_import(ty, import.module, import.field)?;
|
||||||
}
|
}
|
||||||
EntityType::Event(e) => environ.declare_event_import(e, module_name, field_name)?,
|
EntityType::Event(e) => environ.declare_event_import(e, import.module, import.field)?,
|
||||||
EntityType::Global(ty) => {
|
EntityType::Global(ty) => {
|
||||||
environ.declare_global_import(ty, module_name, field_name)?;
|
environ.declare_global_import(ty, import.module, import.field)?;
|
||||||
}
|
}
|
||||||
EntityType::Table(ty) => {
|
EntityType::Table(ty) => {
|
||||||
environ.declare_table_import(ty, module_name, field_name)?;
|
environ.declare_table_import(ty, import.module, import.field)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -960,7 +960,8 @@
|
|||||||
*
|
*
|
||||||
* This function takes ownership of the `module`, `name`, and
|
* This function takes ownership of the `module`, `name`, and
|
||||||
* #wasm_externtype_t arguments. The caller is responsible for deleting the
|
* #wasm_externtype_t arguments. The caller is responsible for deleting the
|
||||||
* returned value.
|
* returned value. Note that `name` can be `NULL` where in the module linking
|
||||||
|
* proposal the import name can be omitted.
|
||||||
*
|
*
|
||||||
* \fn const wasm_name_t* wasm_importtype_module(const wasm_importtype_t *);
|
* \fn const wasm_name_t* wasm_importtype_module(const wasm_importtype_t *);
|
||||||
* \brief Returns the module this import is importing from.
|
* \brief Returns the module this import is importing from.
|
||||||
@@ -972,7 +973,9 @@
|
|||||||
* \brief Returns the name this import is importing from.
|
* \brief Returns the name this import is importing from.
|
||||||
*
|
*
|
||||||
* The returned memory is owned by the #wasm_importtype_t argument, the caller
|
* The returned memory is owned by the #wasm_importtype_t argument, the caller
|
||||||
* should not deallocate it.
|
* should not deallocate it. Note that `NULL` can be returned which means
|
||||||
|
* that the import name is not provided. This is for imports with the module
|
||||||
|
* linking proposal that only have the module specified.
|
||||||
*
|
*
|
||||||
* \fn const wasm_externtype_t* wasm_importtype_type(const wasm_importtype_t *);
|
* \fn const wasm_externtype_t* wasm_importtype_type(const wasm_importtype_t *);
|
||||||
* \brief Returns the type of item this import is importing.
|
* \brief Returns the type of item this import is importing.
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ pub extern "C" fn wasmtime_linker_get_default(
|
|||||||
pub extern "C" fn wasmtime_linker_get_one_by_name(
|
pub extern "C" fn wasmtime_linker_get_one_by_name(
|
||||||
linker: &wasmtime_linker_t,
|
linker: &wasmtime_linker_t,
|
||||||
module: &wasm_name_t,
|
module: &wasm_name_t,
|
||||||
name: &wasm_name_t,
|
name: Option<&wasm_name_t>,
|
||||||
item_ptr: &mut *mut wasm_extern_t,
|
item_ptr: &mut *mut wasm_extern_t,
|
||||||
) -> Option<Box<wasmtime_error_t>> {
|
) -> Option<Box<wasmtime_error_t>> {
|
||||||
let linker = &linker.linker;
|
let linker = &linker.linker;
|
||||||
@@ -124,9 +124,12 @@ pub extern "C" fn wasmtime_linker_get_one_by_name(
|
|||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(_) => return bad_utf8(),
|
Err(_) => return bad_utf8(),
|
||||||
};
|
};
|
||||||
let name = match str::from_utf8(name.as_slice()) {
|
let name = match name {
|
||||||
Ok(s) => s,
|
Some(name) => match str::from_utf8(name.as_slice()) {
|
||||||
|
Ok(s) => Some(s),
|
||||||
Err(_) => return bad_utf8(),
|
Err(_) => return bad_utf8(),
|
||||||
|
},
|
||||||
|
None => None,
|
||||||
};
|
};
|
||||||
handle_result(linker.get_one_by_name(module, name), |which| {
|
handle_result(linker.get_one_by_name(module, name), |which| {
|
||||||
*item_ptr = Box::into_raw(Box::new(wasm_extern_t { which }))
|
*item_ptr = Box::into_raw(Box::new(wasm_extern_t { which }))
|
||||||
|
|||||||
@@ -51,7 +51,13 @@ pub extern "C" fn wasmtime_module_new(
|
|||||||
handle_result(Module::from_binary(&engine.engine, binary), |module| {
|
handle_result(Module::from_binary(&engine.engine, binary), |module| {
|
||||||
let imports = module
|
let imports = module
|
||||||
.imports()
|
.imports()
|
||||||
.map(|i| wasm_importtype_t::new(i.module().to_owned(), i.name().to_owned(), i.ty()))
|
.map(|i| {
|
||||||
|
wasm_importtype_t::new(
|
||||||
|
i.module().to_owned(),
|
||||||
|
i.name().map(|s| s.to_owned()),
|
||||||
|
i.ty(),
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let exports = module
|
let exports = module
|
||||||
.exports()
|
.exports()
|
||||||
@@ -118,7 +124,13 @@ pub extern "C" fn wasm_module_obtain(
|
|||||||
}
|
}
|
||||||
let imports = module
|
let imports = module
|
||||||
.imports()
|
.imports()
|
||||||
.map(|i| wasm_importtype_t::new(i.module().to_owned(), i.name().to_owned(), i.ty()))
|
.map(|i| {
|
||||||
|
wasm_importtype_t::new(
|
||||||
|
i.module().to_owned(),
|
||||||
|
i.name().map(|s| s.to_owned()),
|
||||||
|
i.ty(),
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let exports = module
|
let exports = module
|
||||||
.exports()
|
.exports()
|
||||||
@@ -175,7 +187,13 @@ pub extern "C" fn wasmtime_module_deserialize(
|
|||||||
|module| {
|
|module| {
|
||||||
let imports = module
|
let imports = module
|
||||||
.imports()
|
.imports()
|
||||||
.map(|i| wasm_importtype_t::new(i.module().to_owned(), i.name().to_owned(), i.ty()))
|
.map(|i| {
|
||||||
|
wasm_importtype_t::new(
|
||||||
|
i.module().to_owned(),
|
||||||
|
i.name().map(|s| s.to_owned()),
|
||||||
|
i.ty(),
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let exports = module
|
let exports = module
|
||||||
.exports()
|
.exports()
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use wasmtime::ExternType;
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct wasm_importtype_t {
|
pub struct wasm_importtype_t {
|
||||||
pub(crate) module: String,
|
pub(crate) module: String,
|
||||||
pub(crate) name: String,
|
pub(crate) name: Option<String>,
|
||||||
pub(crate) ty: ExternType,
|
pub(crate) ty: ExternType,
|
||||||
module_cache: OnceCell<wasm_name_t>,
|
module_cache: OnceCell<wasm_name_t>,
|
||||||
name_cache: OnceCell<wasm_name_t>,
|
name_cache: OnceCell<wasm_name_t>,
|
||||||
@@ -16,7 +16,7 @@ pub struct wasm_importtype_t {
|
|||||||
wasmtime_c_api_macros::declare_ty!(wasm_importtype_t);
|
wasmtime_c_api_macros::declare_ty!(wasm_importtype_t);
|
||||||
|
|
||||||
impl wasm_importtype_t {
|
impl wasm_importtype_t {
|
||||||
pub(crate) fn new(module: String, name: String, ty: ExternType) -> wasm_importtype_t {
|
pub(crate) fn new(module: String, name: Option<String>, ty: ExternType) -> wasm_importtype_t {
|
||||||
wasm_importtype_t {
|
wasm_importtype_t {
|
||||||
module,
|
module,
|
||||||
name,
|
name,
|
||||||
@@ -31,13 +31,16 @@ impl wasm_importtype_t {
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wasm_importtype_new(
|
pub extern "C" fn wasm_importtype_new(
|
||||||
module: &mut wasm_name_t,
|
module: &mut wasm_name_t,
|
||||||
name: &mut wasm_name_t,
|
name: Option<&mut wasm_name_t>,
|
||||||
ty: Box<wasm_externtype_t>,
|
ty: Box<wasm_externtype_t>,
|
||||||
) -> Option<Box<wasm_importtype_t>> {
|
) -> Option<Box<wasm_importtype_t>> {
|
||||||
let module = module.take();
|
let module = module.take();
|
||||||
let name = name.take();
|
let name = name.map(|n| n.take());
|
||||||
let module = String::from_utf8(module).ok()?;
|
let module = String::from_utf8(module).ok()?;
|
||||||
let name = String::from_utf8(name).ok()?;
|
let name = match name {
|
||||||
|
Some(name) => Some(String::from_utf8(name).ok()?),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
Some(Box::new(wasm_importtype_t::new(module, name, ty.ty())))
|
Some(Box::new(wasm_importtype_t::new(module, name, ty.ty())))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,9 +51,12 @@ pub extern "C" fn wasm_importtype_module(it: &wasm_importtype_t) -> &wasm_name_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wasm_importtype_name(it: &wasm_importtype_t) -> &wasm_name_t {
|
pub extern "C" fn wasm_importtype_name(it: &wasm_importtype_t) -> Option<&wasm_name_t> {
|
||||||
|
let name = it.name.as_ref()?;
|
||||||
|
Some(
|
||||||
it.name_cache
|
it.name_cache
|
||||||
.get_or_init(|| wasm_name_t::from_name(it.name.clone()))
|
.get_or_init(|| wasm_name_t::from_name(name.to_string())),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|||||||
@@ -328,7 +328,7 @@ pub extern "C" fn wasi_instance_bind_import<'a>(
|
|||||||
import: &wasm_importtype_t,
|
import: &wasm_importtype_t,
|
||||||
) -> Option<&'a wasm_extern_t> {
|
) -> Option<&'a wasm_extern_t> {
|
||||||
let module = &import.module;
|
let module = &import.module;
|
||||||
let name = str::from_utf8(import.name.as_bytes()).ok()?;
|
let name = str::from_utf8(import.name.as_ref()?.as_bytes()).ok()?;
|
||||||
|
|
||||||
let export = match &instance.wasi {
|
let export = match &instance.wasi {
|
||||||
WasiInstance::Preview1(wasi) => {
|
WasiInstance::Preview1(wasi) => {
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ pub struct Module {
|
|||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
|
|
||||||
/// All import records, in the order they are declared in the module.
|
/// All import records, in the order they are declared in the module.
|
||||||
pub imports: Vec<(String, String, EntityIndex)>,
|
pub imports: Vec<(String, Option<String>, EntityIndex)>,
|
||||||
|
|
||||||
/// Exported entities.
|
/// Exported entities.
|
||||||
pub exports: IndexMap<String, EntityIndex>,
|
pub exports: IndexMap<String, EntityIndex>,
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
|
|||||||
&mut self,
|
&mut self,
|
||||||
index: TypeIndex,
|
index: TypeIndex,
|
||||||
module: &str,
|
module: &str,
|
||||||
field: &str,
|
field: Option<&str>,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(
|
||||||
self.result.module.functions.len(),
|
self.result.module.functions.len(),
|
||||||
@@ -275,7 +275,7 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
|
|||||||
let func_index = self.result.module.functions.push(sig_index);
|
let func_index = self.result.module.functions.push(sig_index);
|
||||||
self.result.module.imports.push((
|
self.result.module.imports.push((
|
||||||
module.to_owned(),
|
module.to_owned(),
|
||||||
field.to_owned(),
|
field.map(|s| s.to_owned()),
|
||||||
EntityIndex::Function(func_index),
|
EntityIndex::Function(func_index),
|
||||||
));
|
));
|
||||||
self.result.module.num_imported_funcs += 1;
|
self.result.module.num_imported_funcs += 1;
|
||||||
@@ -283,7 +283,12 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_table_import(&mut self, table: Table, module: &str, field: &str) -> WasmResult<()> {
|
fn declare_table_import(
|
||||||
|
&mut self,
|
||||||
|
table: Table,
|
||||||
|
module: &str,
|
||||||
|
field: Option<&str>,
|
||||||
|
) -> WasmResult<()> {
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(
|
||||||
self.result.module.table_plans.len(),
|
self.result.module.table_plans.len(),
|
||||||
self.result.module.num_imported_tables,
|
self.result.module.num_imported_tables,
|
||||||
@@ -293,7 +298,7 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
|
|||||||
let table_index = self.result.module.table_plans.push(plan);
|
let table_index = self.result.module.table_plans.push(plan);
|
||||||
self.result.module.imports.push((
|
self.result.module.imports.push((
|
||||||
module.to_owned(),
|
module.to_owned(),
|
||||||
field.to_owned(),
|
field.map(|s| s.to_owned()),
|
||||||
EntityIndex::Table(table_index),
|
EntityIndex::Table(table_index),
|
||||||
));
|
));
|
||||||
self.result.module.num_imported_tables += 1;
|
self.result.module.num_imported_tables += 1;
|
||||||
@@ -304,7 +309,7 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
|
|||||||
&mut self,
|
&mut self,
|
||||||
memory: Memory,
|
memory: Memory,
|
||||||
module: &str,
|
module: &str,
|
||||||
field: &str,
|
field: Option<&str>,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(
|
||||||
self.result.module.memory_plans.len(),
|
self.result.module.memory_plans.len(),
|
||||||
@@ -318,7 +323,7 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
|
|||||||
let memory_index = self.result.module.memory_plans.push(plan);
|
let memory_index = self.result.module.memory_plans.push(plan);
|
||||||
self.result.module.imports.push((
|
self.result.module.imports.push((
|
||||||
module.to_owned(),
|
module.to_owned(),
|
||||||
field.to_owned(),
|
field.map(|s| s.to_owned()),
|
||||||
EntityIndex::Memory(memory_index),
|
EntityIndex::Memory(memory_index),
|
||||||
));
|
));
|
||||||
self.result.module.num_imported_memories += 1;
|
self.result.module.num_imported_memories += 1;
|
||||||
@@ -329,7 +334,7 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
|
|||||||
&mut self,
|
&mut self,
|
||||||
global: Global,
|
global: Global,
|
||||||
module: &str,
|
module: &str,
|
||||||
field: &str,
|
field: Option<&str>,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(
|
||||||
self.result.module.globals.len(),
|
self.result.module.globals.len(),
|
||||||
@@ -339,7 +344,7 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
|
|||||||
let global_index = self.result.module.globals.push(global);
|
let global_index = self.result.module.globals.push(global);
|
||||||
self.result.module.imports.push((
|
self.result.module.imports.push((
|
||||||
module.to_owned(),
|
module.to_owned(),
|
||||||
field.to_owned(),
|
field.map(|s| s.to_owned()),
|
||||||
EntityIndex::Global(global_index),
|
EntityIndex::Global(global_index),
|
||||||
));
|
));
|
||||||
self.result.module.num_imported_globals += 1;
|
self.result.module.num_imported_globals += 1;
|
||||||
|
|||||||
@@ -309,8 +309,9 @@ fn with_imports<R>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
for (expected, actual) in m.imports.iter().zip(externs) {
|
for (expected, actual) in m.imports.iter().zip(externs) {
|
||||||
process(&expected.2, actual).with_context(|| {
|
process(&expected.2, actual).with_context(|| match &expected.1 {
|
||||||
format!("incompatible import type for {}/{}", expected.0, expected.1)
|
Some(name) => format!("incompatible import type for {}/{}", expected.0, name),
|
||||||
|
None => format!("incompatible import type for {}", expected.0),
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -592,28 +592,27 @@ impl Linker {
|
|||||||
let mut options = Vec::new();
|
let mut options = Vec::new();
|
||||||
for i in self.map.keys() {
|
for i in self.map.keys() {
|
||||||
if &*self.strings[i.module] != import.module()
|
if &*self.strings[i.module] != import.module()
|
||||||
|| &*self.strings[i.name] != import.name()
|
|| self.strings.get(i.name).map(|s| &**s) != import.name()
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
options.push(format!(" * {:?}\n", i.kind));
|
options.push(format!(" * {:?}\n", i.kind));
|
||||||
}
|
}
|
||||||
|
let desc = match import.name() {
|
||||||
|
Some(name) => format!("{}::{}", import.module(), name),
|
||||||
|
None => import.module().to_string(),
|
||||||
|
};
|
||||||
if options.is_empty() {
|
if options.is_empty() {
|
||||||
return anyhow!(
|
return anyhow!("unknown import: `{}` has not been defined", desc);
|
||||||
"unknown import: `{}::{}` has not been defined",
|
|
||||||
import.module(),
|
|
||||||
import.name()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
options.sort();
|
options.sort();
|
||||||
|
|
||||||
anyhow!(
|
anyhow!(
|
||||||
"incompatible import type for `{}::{}` specified\n\
|
"incompatible import type for `{}` specified\n\
|
||||||
desired signature was: {:?}\n\
|
desired signature was: {:?}\n\
|
||||||
signatures available:\n\n{}",
|
signatures available:\n\n{}",
|
||||||
import.module(),
|
desc,
|
||||||
import.name(),
|
|
||||||
import.ty(),
|
import.ty(),
|
||||||
options.concat(),
|
options.concat(),
|
||||||
)
|
)
|
||||||
@@ -649,7 +648,10 @@ impl Linker {
|
|||||||
pub fn get(&self, import: &ImportType) -> Option<Extern> {
|
pub fn get(&self, import: &ImportType) -> Option<Extern> {
|
||||||
let key = ImportKey {
|
let key = ImportKey {
|
||||||
module: *self.string2idx.get(import.module())?,
|
module: *self.string2idx.get(import.module())?,
|
||||||
name: *self.string2idx.get(import.name())?,
|
name: match import.name() {
|
||||||
|
Some(name) => *self.string2idx.get(name)?,
|
||||||
|
None => usize::max_value(),
|
||||||
|
},
|
||||||
kind: self.import_kind(import.ty()),
|
kind: self.import_kind(import.ty()),
|
||||||
};
|
};
|
||||||
self.map.get(&key).cloned()
|
self.map.get(&key).cloned()
|
||||||
@@ -662,12 +664,13 @@ impl Linker {
|
|||||||
pub fn get_by_name<'a: 'p, 'p>(
|
pub fn get_by_name<'a: 'p, 'p>(
|
||||||
&'a self,
|
&'a self,
|
||||||
module: &'p str,
|
module: &'p str,
|
||||||
name: &'p str,
|
name: Option<&'p str>,
|
||||||
) -> impl Iterator<Item = &'a Extern> + 'p {
|
) -> impl Iterator<Item = &'a Extern> + 'p {
|
||||||
self.map
|
self.map
|
||||||
.iter()
|
.iter()
|
||||||
.filter(move |(key, _item)| {
|
.filter(move |(key, _item)| {
|
||||||
&*self.strings[key.module] == module && &*self.strings[key.name] == name
|
&*self.strings[key.module] == module
|
||||||
|
&& self.strings.get(key.name).map(|s| &**s) == name
|
||||||
})
|
})
|
||||||
.map(|(_, item)| item)
|
.map(|(_, item)| item)
|
||||||
}
|
}
|
||||||
@@ -678,13 +681,17 @@ impl Linker {
|
|||||||
/// a single `Extern` item. If the `module` and `name` pair isn't defined
|
/// a single `Extern` item. If the `module` and `name` pair isn't defined
|
||||||
/// in this linker then an error is returned. If more than one value exists
|
/// in this linker then an error is returned. If more than one value exists
|
||||||
/// for the `module` and `name` pairs, then an error is returned as well.
|
/// for the `module` and `name` pairs, then an error is returned as well.
|
||||||
pub fn get_one_by_name(&self, module: &str, name: &str) -> Result<Extern> {
|
pub fn get_one_by_name(&self, module: &str, name: Option<&str>) -> Result<Extern> {
|
||||||
|
let err_msg = || match name {
|
||||||
|
Some(name) => format!("named `{}` in `{}`", name, module),
|
||||||
|
None => format!("named `{}`", module),
|
||||||
|
};
|
||||||
let mut items = self.get_by_name(module, name);
|
let mut items = self.get_by_name(module, name);
|
||||||
let ret = items
|
let ret = items
|
||||||
.next()
|
.next()
|
||||||
.ok_or_else(|| anyhow!("no item named `{}` in `{}`", name, module))?;
|
.ok_or_else(|| anyhow!("no item {}", err_msg()))?;
|
||||||
if items.next().is_some() {
|
if items.next().is_some() {
|
||||||
bail!("too many items named `{}` in `{}`", name, module);
|
bail!("too many items {}", err_msg());
|
||||||
}
|
}
|
||||||
Ok(ret.clone())
|
Ok(ret.clone())
|
||||||
}
|
}
|
||||||
@@ -694,7 +701,7 @@ impl Linker {
|
|||||||
/// An export with an empty string is considered to be a "default export".
|
/// An export with an empty string is considered to be a "default export".
|
||||||
/// "_start" is also recognized for compatibility.
|
/// "_start" is also recognized for compatibility.
|
||||||
pub fn get_default(&self, module: &str) -> Result<Func> {
|
pub fn get_default(&self, module: &str) -> Result<Func> {
|
||||||
let mut items = self.get_by_name(module, "");
|
let mut items = self.get_by_name(module, Some(""));
|
||||||
if let Some(external) = items.next() {
|
if let Some(external) = items.next() {
|
||||||
if items.next().is_some() {
|
if items.next().is_some() {
|
||||||
bail!("too many items named `` in `{}`", module);
|
bail!("too many items named `` in `{}`", module);
|
||||||
@@ -706,7 +713,7 @@ impl Linker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// For compatibility, also recognize "_start".
|
// For compatibility, also recognize "_start".
|
||||||
let mut items = self.get_by_name(module, "_start");
|
let mut items = self.get_by_name(module, Some("_start"));
|
||||||
if let Some(external) = items.next() {
|
if let Some(external) = items.next() {
|
||||||
if items.next().is_some() {
|
if items.next().is_some() {
|
||||||
bail!("too many items named `_start` in `{}`", module);
|
bail!("too many items named `_start` in `{}`", module);
|
||||||
|
|||||||
@@ -423,7 +423,7 @@ impl Module {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(move |(module_name, name, entity_index)| {
|
.map(move |(module_name, name, entity_index)| {
|
||||||
let r#type = EntityType::new(entity_index, module);
|
let r#type = EntityType::new(entity_index, module);
|
||||||
ImportType::new(module_name, name, r#type)
|
ImportType::new(module_name, name.as_deref(), r#type)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,11 +43,9 @@ pub fn create_global(store: &Store, gt: &GlobalType, val: Val) -> Result<StoreIn
|
|||||||
let local_sig_index = module.signatures.push(wasm.clone());
|
let local_sig_index = module.signatures.push(wasm.clone());
|
||||||
let func_index = module.functions.push(local_sig_index);
|
let func_index = module.functions.push(local_sig_index);
|
||||||
module.num_imported_funcs = 1;
|
module.num_imported_funcs = 1;
|
||||||
module.imports.push((
|
module
|
||||||
"".into(),
|
.imports
|
||||||
"".into(),
|
.push(("".into(), None, wasm::EntityIndex::Function(func_index)));
|
||||||
wasm::EntityIndex::Function(func_index),
|
|
||||||
));
|
|
||||||
|
|
||||||
let f = f.caller_checked_anyfunc();
|
let f = f.caller_checked_anyfunc();
|
||||||
let f = unsafe { f.as_ref() };
|
let f = unsafe { f.as_ref() };
|
||||||
|
|||||||
@@ -483,13 +483,10 @@ impl ModuleType {
|
|||||||
|
|
||||||
/// Returns the list of imports associated with this module type.
|
/// Returns the list of imports associated with this module type.
|
||||||
pub fn imports(&self) -> impl ExactSizeIterator<Item = ImportType<'_>> {
|
pub fn imports(&self) -> impl ExactSizeIterator<Item = ImportType<'_>> {
|
||||||
self.imports.iter().map(|(module, name, ty)| {
|
self.imports.iter().map(|(module, name, ty)| ImportType {
|
||||||
ImportType {
|
|
||||||
module,
|
module,
|
||||||
// FIXME(#2094) should thread through the `Option`
|
name: name.as_deref(),
|
||||||
name: name.as_ref().unwrap(),
|
|
||||||
ty: EntityOrExtern::Extern(ty),
|
ty: EntityOrExtern::Extern(ty),
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -676,7 +673,7 @@ pub struct ImportType<'module> {
|
|||||||
module: &'module str,
|
module: &'module str,
|
||||||
|
|
||||||
/// The field of the import.
|
/// The field of the import.
|
||||||
name: &'module str,
|
name: Option<&'module str>,
|
||||||
|
|
||||||
/// The type of the import.
|
/// The type of the import.
|
||||||
ty: EntityOrExtern<'module>,
|
ty: EntityOrExtern<'module>,
|
||||||
@@ -693,7 +690,7 @@ impl<'module> ImportType<'module> {
|
|||||||
/// is of type `ty`.
|
/// is of type `ty`.
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
module: &'module str,
|
module: &'module str,
|
||||||
name: &'module str,
|
name: Option<&'module str>,
|
||||||
ty: EntityType<'module>,
|
ty: EntityType<'module>,
|
||||||
) -> ImportType<'module> {
|
) -> ImportType<'module> {
|
||||||
ImportType {
|
ImportType {
|
||||||
@@ -710,7 +707,10 @@ impl<'module> ImportType<'module> {
|
|||||||
|
|
||||||
/// Returns the field name of the module that this import is expected to
|
/// Returns the field name of the module that this import is expected to
|
||||||
/// come from.
|
/// come from.
|
||||||
pub fn name(&self) -> &'module str {
|
///
|
||||||
|
/// Note that the name can be `None` for the module linking proposal. If the
|
||||||
|
/// module linking proposal is not enabled it's safe to unwrap this.
|
||||||
|
pub fn name(&self) -> Option<&'module str> {
|
||||||
self.name
|
self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -726,8 +726,8 @@ impl<'module> ImportType<'module> {
|
|||||||
impl<'module> fmt::Debug for ImportType<'module> {
|
impl<'module> fmt::Debug for ImportType<'module> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.debug_struct("ImportType")
|
f.debug_struct("ImportType")
|
||||||
.field("module", &self.module().to_owned())
|
.field("module", &self.module())
|
||||||
.field("name", &self.name().to_owned())
|
.field("name", &self.name())
|
||||||
.field("ty", &self.ty())
|
.field("ty", &self.ty())
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ impl WastContext {
|
|||||||
|
|
||||||
fn get_export(&self, module: Option<&str>, name: &str) -> Result<Extern> {
|
fn get_export(&self, module: Option<&str>, name: &str) -> Result<Extern> {
|
||||||
match module {
|
match module {
|
||||||
Some(module) => self.linker.get_one_by_name(module, name),
|
Some(module) => self.linker.get_one_by_name(module, Some(name)),
|
||||||
None => self
|
None => self
|
||||||
.current
|
.current
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
|||||||
@@ -265,7 +265,7 @@ impl RunCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn invoke_export(&self, linker: &Linker, name: &str) -> Result<()> {
|
fn invoke_export(&self, linker: &Linker, name: &str) -> Result<()> {
|
||||||
let func = match linker.get_one_by_name("", name)?.into_func() {
|
let func = match linker.get_one_by_name("", Some(name))?.into_func() {
|
||||||
Some(func) => func,
|
Some(func) => func,
|
||||||
None => bail!("export of `{}` wasn't a function", name),
|
None => bail!("export of `{}` wasn't a function", name),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ mod tests {
|
|||||||
module
|
module
|
||||||
.imports()
|
.imports()
|
||||||
.map(|import| {
|
.map(|import| {
|
||||||
assert_eq!("hostcall_read", import.name());
|
assert_eq!(Some("hostcall_read"), import.name());
|
||||||
let func = Func::wrap(&store, {
|
let func = Func::wrap(&store, {
|
||||||
move |caller: Caller<'_>| {
|
move |caller: Caller<'_>| {
|
||||||
let mem = caller.get_export("memory").unwrap().into_memory().unwrap();
|
let mem = caller.get_export("memory").unwrap().into_memory().unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user