mirror of
https://github.com/fluencelabs/wasm-utils
synced 2025-04-15 00:46:16 +00:00
add some docs
This commit is contained in:
parent
c3833efca7
commit
62ea903c3a
85
src/graph.rs
85
src/graph.rs
@ -7,8 +7,15 @@ use std::borrow::ToOwned;
|
|||||||
use std::string::String;
|
use std::string::String;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
/// Imported or declared variant of the same thing.
|
||||||
|
///
|
||||||
|
/// In WebAssembly, function/global/memory/table instances can either be
|
||||||
|
/// imported or declared internally, forming united index space.
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum ImportedOrDeclared<T=()> {
|
pub enum ImportedOrDeclared<T=()> {
|
||||||
|
/// Variant for imported instances.
|
||||||
Imported(String, String),
|
Imported(String, String),
|
||||||
|
/// Variant for instances declared internally in the module.
|
||||||
Declared(T),
|
Declared(T),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,74 +25,148 @@ impl<T> From<&elements::ImportEntry> for ImportedOrDeclared<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Function origin (imported or internal).
|
||||||
pub type FuncOrigin = ImportedOrDeclared<FuncBody>;
|
pub type FuncOrigin = ImportedOrDeclared<FuncBody>;
|
||||||
|
/// Global origin (imported or internal).
|
||||||
pub type GlobalOrigin = ImportedOrDeclared<Vec<Instruction>>;
|
pub type GlobalOrigin = ImportedOrDeclared<Vec<Instruction>>;
|
||||||
|
/// Memory origin (imported or internal).
|
||||||
pub type MemoryOrigin = ImportedOrDeclared;
|
pub type MemoryOrigin = ImportedOrDeclared;
|
||||||
|
/// Table origin (imported or internal).
|
||||||
pub type TableOrigin = ImportedOrDeclared;
|
pub type TableOrigin = ImportedOrDeclared;
|
||||||
|
|
||||||
|
/// Function body.
|
||||||
|
///
|
||||||
|
/// Function consist of declaration (signature, i.e. type reference)
|
||||||
|
/// and the actual code. This part is the actual code.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct FuncBody {
|
pub struct FuncBody {
|
||||||
pub locals: Vec<elements::Local>,
|
pub locals: Vec<elements::Local>,
|
||||||
pub code: Vec<Instruction>,
|
pub code: Vec<Instruction>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Function declaration.
|
||||||
|
///
|
||||||
|
/// As with other instances, functions can be either imported or declared
|
||||||
|
/// within the module - `origin` field is handling this.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Func {
|
pub struct Func {
|
||||||
|
/// Function signature/type reference.
|
||||||
pub type_ref: EntryRef<elements::Type>,
|
pub type_ref: EntryRef<elements::Type>,
|
||||||
|
/// Where this function comes from (imported or declared).
|
||||||
pub origin: FuncOrigin,
|
pub origin: FuncOrigin,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Global declaration.
|
||||||
|
///
|
||||||
|
/// As with other instances, globals can be either imported or declared
|
||||||
|
/// within the module - `origin` field is handling this.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Global {
|
pub struct Global {
|
||||||
pub content: elements::ValueType,
|
pub content: elements::ValueType,
|
||||||
pub is_mut: bool,
|
pub is_mut: bool,
|
||||||
pub origin: GlobalOrigin,
|
pub origin: GlobalOrigin,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Instruction.
|
||||||
|
///
|
||||||
|
/// Some instructions don't reference any entities within the WebAssembly module,
|
||||||
|
/// while others do. This enum is for tracking references when required.
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum Instruction {
|
pub enum Instruction {
|
||||||
|
/// WebAssembly instruction that does not reference any module entities.
|
||||||
Plain(elements::Instruction),
|
Plain(elements::Instruction),
|
||||||
|
/// Call instruction which references the function.
|
||||||
Call(EntryRef<Func>),
|
Call(EntryRef<Func>),
|
||||||
|
/// Indirect call instruction which references function type (function signature).
|
||||||
CallIndirect(EntryRef<elements::Type>, u8),
|
CallIndirect(EntryRef<elements::Type>, u8),
|
||||||
|
/// get_global instruction which references the global.
|
||||||
GetGlobal(EntryRef<Global>),
|
GetGlobal(EntryRef<Global>),
|
||||||
|
/// set_global instruction which references the global.
|
||||||
SetGlobal(EntryRef<Global>),
|
SetGlobal(EntryRef<Global>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Memory instance decriptor.
|
||||||
|
///
|
||||||
|
/// As with other similar instances, memory instances can be either imported
|
||||||
|
/// or declared within the module - `origin` field is handling this.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Memory {
|
pub struct Memory {
|
||||||
|
/// Declared limits of the table instance.
|
||||||
pub limits: elements::ResizableLimits,
|
pub limits: elements::ResizableLimits,
|
||||||
|
/// Origin of the memory instance (internal or imported).
|
||||||
pub origin: MemoryOrigin,
|
pub origin: MemoryOrigin,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Memory instance decriptor.
|
||||||
|
///
|
||||||
|
/// As with other similar instances, memory instances can be either imported
|
||||||
|
/// or declared within the module - `origin` field is handling this.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Table {
|
pub struct Table {
|
||||||
pub origin: TableOrigin,
|
/// Declared limits of the table instance.
|
||||||
pub limits: elements::ResizableLimits,
|
pub limits: elements::ResizableLimits,
|
||||||
|
/// Origin of the table instance (internal or imported).
|
||||||
|
pub origin: TableOrigin,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Segment location.
|
||||||
|
///
|
||||||
|
/// Reserved for future use. Currenty only `Default` variant is supported.
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum SegmentLocation {
|
pub enum SegmentLocation {
|
||||||
|
/// Not used currently.
|
||||||
Passive,
|
Passive,
|
||||||
|
/// Default segment location with index `0`.
|
||||||
Default(Vec<Instruction>),
|
Default(Vec<Instruction>),
|
||||||
|
/// Not used currently.
|
||||||
WithIndex(u32, Vec<Instruction>),
|
WithIndex(u32, Vec<Instruction>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Data segment of data section.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct DataSegment {
|
pub struct DataSegment {
|
||||||
|
/// Location of the segment in the linear memory.
|
||||||
pub location: SegmentLocation,
|
pub location: SegmentLocation,
|
||||||
|
/// Raw value of the data segment.
|
||||||
pub value: Vec<u8>,
|
pub value: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Element segment of element section.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct ElementSegment {
|
pub struct ElementSegment {
|
||||||
|
/// Location of the segment in the table space.
|
||||||
pub location: SegmentLocation,
|
pub location: SegmentLocation,
|
||||||
|
/// Raw value (function indices) of the element segment.
|
||||||
pub value: Vec<u32>,
|
pub value: Vec<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Export entry reference.
|
||||||
|
///
|
||||||
|
/// Module can export function, global, table or memory instance
|
||||||
|
/// under specific name (field).
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum ExportLocal {
|
pub enum ExportLocal {
|
||||||
|
/// Function reference.
|
||||||
Func(EntryRef<Func>),
|
Func(EntryRef<Func>),
|
||||||
|
/// Global reference.
|
||||||
Global(EntryRef<Global>),
|
Global(EntryRef<Global>),
|
||||||
|
/// Table reference.
|
||||||
Table(EntryRef<Table>),
|
Table(EntryRef<Table>),
|
||||||
|
/// Memory reference.
|
||||||
Memory(EntryRef<Memory>),
|
Memory(EntryRef<Memory>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Export entry description.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Export {
|
pub struct Export {
|
||||||
|
/// Name (field) of the export entry.
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
/// What entity is exported.
|
||||||
pub local: ExportLocal,
|
pub local: ExportLocal,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
/// Module
|
||||||
|
#[derive(Debug, Default)]
|
||||||
pub struct Module {
|
pub struct Module {
|
||||||
pub types: RefList<elements::Type>,
|
pub types: RefList<elements::Type>,
|
||||||
pub funcs: RefList<Func>,
|
pub funcs: RefList<Func>,
|
||||||
|
@ -84,6 +84,8 @@ impl<T> EntryRef<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// List that tracks references and indices.
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct RefList<T> {
|
pub struct RefList<T> {
|
||||||
items: Vec<EntryRef<T>>,
|
items: Vec<EntryRef<T>>,
|
||||||
}
|
}
|
||||||
@ -96,8 +98,12 @@ impl<T> Default for RefList<T> {
|
|||||||
|
|
||||||
impl<T> RefList<T> {
|
impl<T> RefList<T> {
|
||||||
|
|
||||||
|
/// New empty list.
|
||||||
pub fn new() -> Self { Self::default() }
|
pub fn new() -> Self { Self::default() }
|
||||||
|
|
||||||
|
/// Push new element in the list.
|
||||||
|
///
|
||||||
|
/// Returns refernce tracking entry.
|
||||||
pub fn push(&mut self, t: T) -> EntryRef<T> {
|
pub fn push(&mut self, t: T) -> EntryRef<T> {
|
||||||
let idx = self.items.len();
|
let idx = self.items.len();
|
||||||
let val: EntryRef<_> = Entry::new(t, idx).into();
|
let val: EntryRef<_> = Entry::new(t, idx).into();
|
||||||
@ -105,6 +111,12 @@ impl<T> RefList<T> {
|
|||||||
val
|
val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Start deleting.
|
||||||
|
///
|
||||||
|
/// Start deleting some entries in the list. Returns transaction
|
||||||
|
/// that can be populated with number of removed entries.
|
||||||
|
/// When transaction is finailized, all entries are deleted and
|
||||||
|
/// internal indices of other entries are updated.
|
||||||
pub fn begin_delete(&mut self) -> DeleteTransaction<T> {
|
pub fn begin_delete(&mut self) -> DeleteTransaction<T> {
|
||||||
DeleteTransaction {
|
DeleteTransaction {
|
||||||
list: self,
|
list: self,
|
||||||
@ -112,6 +124,9 @@ impl<T> RefList<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get entry with index (checked).
|
||||||
|
///
|
||||||
|
/// Can return None when index out of bounts.
|
||||||
pub fn get(&self, idx: usize) -> Option<EntryRef<T>> {
|
pub fn get(&self, idx: usize) -> Option<EntryRef<T>> {
|
||||||
self.items.get(idx).cloned()
|
self.items.get(idx).cloned()
|
||||||
}
|
}
|
||||||
@ -134,14 +149,19 @@ impl<T> RefList<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Delete several items.
|
||||||
pub fn delete(&mut self, indices: &[usize]) {
|
pub fn delete(&mut self, indices: &[usize]) {
|
||||||
self.done_delete(indices)
|
self.done_delete(indices)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Delete one item.
|
||||||
pub fn delete_one(&mut self, index: usize) {
|
pub fn delete_one(&mut self, index: usize) {
|
||||||
self.done_delete(&[index])
|
self.done_delete(&[index])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Initialize from slice.
|
||||||
|
///
|
||||||
|
/// Slice members are cloned.
|
||||||
pub fn from_slice(list: &[T]) -> Self
|
pub fn from_slice(list: &[T]) -> Self
|
||||||
where T: Clone
|
where T: Clone
|
||||||
{
|
{
|
||||||
@ -154,23 +174,32 @@ impl<T> RefList<T> {
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Length of the list.
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.items.len()
|
self.items.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clone entry (reference counting object to item) by index.
|
||||||
|
///
|
||||||
|
/// Will panic if index out of bounds.
|
||||||
pub fn clone_ref(&self, idx: usize) -> EntryRef<T> {
|
pub fn clone_ref(&self, idx: usize) -> EntryRef<T> {
|
||||||
self.items[idx].clone()
|
self.items[idx].clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get reference to entry by index.
|
||||||
|
///
|
||||||
|
/// Will panic if index out of bounds.
|
||||||
pub fn get_ref(&self, idx: usize) -> &EntryRef<T> {
|
pub fn get_ref(&self, idx: usize) -> &EntryRef<T> {
|
||||||
&self.items[idx]
|
&self.items[idx]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Iterate through entries.
|
||||||
pub fn iter(&self) -> slice::Iter<EntryRef<T>> {
|
pub fn iter(&self) -> slice::Iter<EntryRef<T>> {
|
||||||
self.items.iter()
|
self.items.iter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Delete transaction.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub struct DeleteTransaction<'a, T> {
|
pub struct DeleteTransaction<'a, T> {
|
||||||
list: &'a mut RefList<T>,
|
list: &'a mut RefList<T>,
|
||||||
@ -178,12 +207,14 @@ pub struct DeleteTransaction<'a, T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> DeleteTransaction<'a, T> {
|
impl<'a, T> DeleteTransaction<'a, T> {
|
||||||
|
/// Add new element to the delete list.
|
||||||
pub fn push(self, idx: usize) -> Self {
|
pub fn push(self, idx: usize) -> Self {
|
||||||
let mut tx = self;
|
let mut tx = self;
|
||||||
tx.deleted.push(idx);
|
tx.deleted.push(idx);
|
||||||
tx
|
tx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Commit transaction.
|
||||||
pub fn done(self) {
|
pub fn done(self) {
|
||||||
let indices = self.deleted;
|
let indices = self.deleted;
|
||||||
let list = self.list;
|
let list = self.list;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user