Files
parity-wasm/src/builder/module.rs

294 lines
8.9 KiB
Rust
Raw Normal View History

2017-04-06 11:34:31 +03:00
use super::invoke::{Invoke, Identity};
2017-04-11 13:35:19 +03:00
use super::code::{self, SignaturesBuilder, FunctionBuilder};
2017-04-10 13:11:34 +03:00
use super::import;
2017-04-06 11:34:31 +03:00
use elements;
/// Module builder
pub struct ModuleBuilder<F=Identity> {
callback: F,
2017-04-06 16:00:12 +03:00
module: ModuleScaffold,
}
2017-04-07 20:00:30 +03:00
/// Location of the internal module function
pub struct CodeLocation {
/// Location (index in 'functions' section) of the signature
pub signature: u32,
/// Location (index in the 'code' section) of the body
pub body: u32,
}
2017-04-06 16:00:12 +03:00
#[derive(Default)]
struct ModuleScaffold {
pub functions: elements::FunctionsSection,
pub types: elements::TypeSection,
2017-04-07 15:29:02 +03:00
pub import: elements::ImportSection,
2017-04-07 20:00:30 +03:00
pub code: elements::CodeSection,
2017-04-06 16:00:12 +03:00
pub other: Vec<elements::Section>,
}
impl From<elements::Module> for ModuleScaffold {
fn from(module: elements::Module) -> Self {
let mut funcs: Option<elements::FunctionsSection> = None;
let mut types: Option<elements::TypeSection> = None;
2017-04-07 15:29:02 +03:00
let mut import: Option<elements::ImportSection> = None;
2017-04-07 20:00:30 +03:00
let mut code: Option<elements::CodeSection> = None;
2017-04-06 16:00:12 +03:00
let mut sections = module.into_sections();
while let Some(section) = sections.pop() {
match section {
elements::Section::Type(sect) => { types = Some(sect); }
elements::Section::Function(sect) => { funcs = Some(sect); }
2017-04-07 15:29:02 +03:00
elements::Section::Import(sect) => { import = Some(sect); }
2017-04-07 20:00:30 +03:00
elements::Section::Code(sect) => { code = Some(sect); }
2017-04-06 16:00:12 +03:00
_ => {}
}
}
ModuleScaffold {
functions: funcs.unwrap_or_default(),
types: types.unwrap_or_default(),
2017-04-07 15:29:02 +03:00
import: import.unwrap_or_default(),
2017-04-07 20:00:30 +03:00
code: code.unwrap_or_default(),
2017-04-06 16:00:12 +03:00
other: sections,
}
}
}
impl From<ModuleScaffold> for elements::Module {
fn from(module: ModuleScaffold) -> Self {
let mut sections = Vec::new();
let types = module.types;
if types.types().len() > 0 {
sections.push(elements::Section::Type(types));
}
2017-04-07 15:29:02 +03:00
let import = module.import;
if import.entries().len() > 0 {
sections.push(elements::Section::Import(import));
}
2017-04-11 13:06:24 +03:00
let functions = module.functions;
if functions.entries().len() > 0 {
sections.push(elements::Section::Function(functions));
}
2017-04-11 13:35:19 +03:00
let code = module.code;
if code.bodies().len() > 0 {
sections.push(elements::Section::Code(code));
}
2017-04-06 16:00:12 +03:00
sections.extend(module.other);
elements::Module::new(sections)
}
2017-04-06 11:34:31 +03:00
}
impl ModuleBuilder {
/// New empty module builder
pub fn new() -> Self {
ModuleBuilder::with_callback(Identity)
}
}
impl<F> ModuleBuilder<F> where F: Invoke<elements::Module> {
/// New module builder with bound callback
pub fn with_callback(callback: F) -> Self {
ModuleBuilder {
callback: callback,
2017-04-06 16:00:12 +03:00
module: Default::default(),
2017-04-06 11:34:31 +03:00
}
}
2017-04-10 13:11:34 +03:00
/// Builder from raw module
pub fn with_module(mut self, module: elements::Module) -> Self {
self.module = module.into();
self
}
2017-04-06 11:34:31 +03:00
/// Fill module with sections from iterator
pub fn with_sections<I>(mut self, sections: I) -> Self
where I: IntoIterator<Item=elements::Section>
{
2017-04-06 16:00:12 +03:00
self.module.other.extend(sections);
2017-04-06 11:34:31 +03:00
self
}
2017-04-06 16:00:12 +03:00
/// Add additional section
2017-04-06 11:34:31 +03:00
pub fn with_section(mut self, section: elements::Section) -> Self {
2017-04-06 16:00:12 +03:00
self.module.other.push(section);
2017-04-06 11:34:31 +03:00
self
}
2017-04-06 16:00:12 +03:00
/// Binds to the type section, creates additional types when required
pub fn with_signatures(mut self, bindings: code::SignatureBindings) -> Self {
2017-04-07 14:04:27 +03:00
self.push_signatures(bindings);
self
}
2017-04-06 16:00:12 +03:00
2017-04-07 20:00:30 +03:00
/// Push stand-alone function definition, creating sections, signature and code blocks
/// in corresponding sections.
/// `FunctionDefinition` can be build using `builder::function` builder
pub fn push_function(&mut self, func: code::FunctionDefinition) -> CodeLocation {
let signature = func.signature;
let body = func.code;
2017-04-10 13:58:14 +03:00
let type_ref = self.resolve_type_ref(signature);
2017-04-07 20:00:30 +03:00
2017-04-10 13:58:14 +03:00
self.module.functions.entries_mut().push(elements::Func::new(type_ref));
let signature_index = self.module.functions.entries_mut().len() as u32 - 1;
self.module.code.bodies_mut().push(body);
let body_index = self.module.code.bodies_mut().len() as u32 - 1;
2017-04-07 20:00:30 +03:00
CodeLocation {
signature: signature_index,
body: body_index,
}
}
2017-04-10 13:58:14 +03:00
fn resolve_type_ref(&mut self, signature: code::Signature) -> u32 {
match signature {
code::Signature::Inline(func_type) => {
self.module.types.types_mut().push(elements::Type::Function(func_type));
self.module.types.types().len() as u32 - 1
}
code::Signature::TypeReference(type_ref) => {
type_ref
}
}
}
/// Push one function signature, returning it's calling index.
/// Can create corresponding type in type section.
pub fn push_signature(&mut self, signature: code::Signature) -> u32 {
let type_ref = self.resolve_type_ref(signature);
self.module.functions.entries_mut().push(elements::Func::new(type_ref));
self.module.functions.entries_mut().len() as u32 - 1
}
2017-04-07 14:04:27 +03:00
/// Push signatures in the module, returning corresponding indices of pushed signatures
pub fn push_signatures(&mut self, signatures: code::SignatureBindings) -> Vec<u32> {
let mut result = Vec::new();
// todo: maybe reuse existing types with the equal signatures
let raw_functions: Vec<u32> = signatures.into_iter().map(|binding|
match binding {
code::Signature::Inline(func_type) => {
2017-04-10 13:58:14 +03:00
self.module.types.types_mut().push(elements::Type::Function(func_type));
self.module.types.types().len() as u32 - 1
2017-04-07 14:04:27 +03:00
}
code::Signature::TypeReference(type_ref) => {
type_ref
}
2017-04-06 16:00:12 +03:00
}
2017-04-07 14:04:27 +03:00
).collect();
for function in raw_functions {
2017-04-10 13:58:14 +03:00
self.module.functions.entries_mut().push(elements::Func::new(function));
result.push(self.module.functions.entries_mut().len() as u32 - 1);
2017-04-06 16:00:12 +03:00
}
2017-04-07 14:04:27 +03:00
result
2017-04-06 16:00:12 +03:00
}
2017-04-11 13:35:19 +03:00
pub fn function(self) -> FunctionBuilder<Self> {
FunctionBuilder::with_callback(self)
}
2017-04-06 16:00:12 +03:00
/// Define functions section
2017-04-07 14:04:27 +03:00
pub fn functions(self) -> SignaturesBuilder<Self> {
SignaturesBuilder::with_callback(self)
2017-04-06 11:34:31 +03:00
}
2017-04-10 13:11:34 +03:00
/// With inserted import entry
pub fn with_import(mut self, entry: elements::ImportEntry) -> Self {
self.module.import.entries_mut().push(entry);
self
}
/// Import entry builder
pub fn import(self) -> import::ImportBuilder<Self> {
import::ImportBuilder::with_callback(self)
}
2017-04-06 11:34:31 +03:00
/// Build module (final step)
pub fn build(self) -> F::Result {
2017-04-06 16:00:12 +03:00
self.callback.invoke(self.module.into())
2017-04-06 11:34:31 +03:00
}
}
impl<F> Invoke<elements::FunctionsSection> for ModuleBuilder<F>
where F: Invoke<elements::Module>
{
type Result = Self;
fn invoke(self, section: elements::FunctionsSection) -> Self {
self.with_section(elements::Section::Function(section))
}
}
2017-04-06 16:00:12 +03:00
impl<F> Invoke<code::SignatureBindings> for ModuleBuilder<F>
where F: Invoke<elements::Module>
{
type Result = Self;
fn invoke(self, bindings: code::SignatureBindings) -> Self {
self.with_signatures(bindings)
}
}
2017-04-11 13:35:19 +03:00
impl<F> Invoke<code::FunctionDefinition> for ModuleBuilder<F>
where F: Invoke<elements::Module>
{
type Result = Self;
fn invoke(self, def: code::FunctionDefinition) -> Self {
let mut b = self;
b.push_function(def);
b
}
}
2017-04-10 13:11:34 +03:00
impl<F> Invoke<elements::ImportEntry> for ModuleBuilder<F>
where F: Invoke<elements::Module>
{
type Result = Self;
fn invoke(self, entry: elements::ImportEntry) -> Self::Result {
self.with_import(entry)
}
}
2017-04-06 11:34:31 +03:00
/// Start new module builder
pub fn module() -> ModuleBuilder {
ModuleBuilder::new()
}
2017-04-10 13:11:34 +03:00
/// Start builder to extend existing module
pub fn from_module(module: elements::Module) -> ModuleBuilder {
ModuleBuilder::new().with_module(module)
}
2017-04-06 11:34:31 +03:00
#[cfg(test)]
mod tests {
use super::module;
#[test]
fn smoky() {
let module = module().build();
assert_eq!(module.sections().len(), 0);
}
2017-04-06 16:00:12 +03:00
#[test]
fn functions() {
let module = module()
2017-04-11 13:35:19 +03:00
.function()
.signature().param().i32().build()
.body().build()
.build()
2017-04-06 16:00:12 +03:00
.build();
assert_eq!(module.type_section().expect("type section to exist").types().len(), 1);
assert_eq!(module.functions_section().expect("function section to exist").entries().len(), 1);
2017-04-11 13:35:19 +03:00
assert_eq!(module.code_section().expect("code section to exist").bodies().len(), 1);
2017-04-06 16:00:12 +03:00
}
2017-04-06 11:34:31 +03:00
}