Skip to content

Commit

Permalink
feat: upstream ops from WASI-virt
Browse files Browse the repository at this point in the history
WASI-virt contains functions that are helpful for manipulating modules
and dealing with exports/imports, which would be helpful to an even
wider group if upstreamed here to walrus.

This commit copies and upstreams some operations that were introduced
in WASI-virt for wider use via walrus.

See also: bytecodealliance/WASI-Virt#20

Signed-off-by: Victor Adossi <vadossi@cosmonic.com>
  • Loading branch information
vados-cosmonic committed Oct 10, 2023
1 parent 440dc03 commit 5e17929
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 7 deletions.
60 changes: 53 additions & 7 deletions src/module/functions/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
//! Functions within a wasm module.

use std::cmp;
use std::collections::BTreeMap;

use anyhow::{bail, Context};
use wasm_encoder::Encode;
use wasmparser::{FuncValidator, FunctionBody, Range, ValidatorResources};

#[cfg(feature = "parallel")]
use rayon::prelude::*;

mod local_function;

use crate::emit::{Emit, EmitContext};
Expand All @@ -11,13 +21,7 @@ use crate::parse::IndicesToIds;
use crate::tombstone_arena::{Id, Tombstone, TombstoneArena};
use crate::ty::TypeId;
use crate::ty::ValType;
use std::cmp;
use std::collections::BTreeMap;
use wasm_encoder::Encode;
use wasmparser::{FuncValidator, FunctionBody, Range, ValidatorResources};

#[cfg(feature = "parallel")]
use rayon::prelude::*;
use crate::{ExportItem, ImportKind, Memory, MemoryId};

pub use self::local_function::LocalFunction;

Expand Down Expand Up @@ -418,6 +422,48 @@ impl Module {

Ok(())
}

/// Retrieve an exported function by name
pub fn get_exported_func_by_name(&self, name: impl AsRef<str>) -> Result<FunctionId> {
self.exports
.iter()
// Find the export with the correct name and internal type
.filter_map(|expt| match expt.item {
ExportItem::Function(fid) if expt.name == name.as_ref() => Some(fid),
_ => None,
})
.nth(0)
.with_context(|| format!("unable to find function export '{}'", name.as_ref()))
}

/// Retrieve an imported function by name
pub fn get_imported_func_by_name(&self, name: impl AsRef<str>) -> Result<FunctionId> {
self.imports
.iter()
// Find the export with the correct name and internal type
.filter_map(|impt| match impt.kind {
ImportKind::Function(fid) if impt.name == name.as_ref() => Some(fid),
_ => None,
})
.nth(0)
.with_context(|| format!("unable to find function export '{}'", name.as_ref()))
}

/// Retrieve the ID for the first exported memory.
///
/// This method does not work in contexts with [multi-memory enabled](https://github.com/WebAssembly/multi-memory),
/// and will error if more than one memory is present.
pub fn get_primary_memory_id(&self) -> Result<MemoryId> {
if self.memories.len() > 1 {
bail!("multiple memories unsupported")
}

self.memories
.iter()
.next()
.map(Memory::id)
.context("module does not export a memory")
}
}

fn used_local_functions<'a>(cx: &mut EmitContext<'a>) -> Vec<(FunctionId, &'a LocalFunction, u64)> {
Expand Down
5 changes: 5 additions & 0 deletions src/module/memories.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ impl ModuleMemories {
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Memory> {
self.arena.iter_mut().map(|(_, f)| f)
}

/// Get the number of memories in this module
pub fn len(&self) -> usize {
self.arena.len()
}
}

impl Module {
Expand Down

0 comments on commit 5e17929

Please sign in to comment.