callindirect_1

This commit is contained in:
Svyatoslav Nikolsky
2017-05-02 08:01:57 +03:00
parent 36662f24a6
commit a2ef2378ea
5 changed files with 152 additions and 0 deletions

View File

@ -6,6 +6,7 @@ mod code;
mod misc; mod misc;
mod import; mod import;
mod memory; mod memory;
mod table;
pub use self::module::{module, from_module, ModuleBuilder}; pub use self::module::{module, from_module, ModuleBuilder};
pub use self::code::{signatures, signature, function}; pub use self::code::{signatures, signature, function};

View File

@ -1,6 +1,7 @@
use super::invoke::{Invoke, Identity}; use super::invoke::{Invoke, Identity};
use super::code::{self, SignaturesBuilder, FunctionBuilder}; use super::code::{self, SignaturesBuilder, FunctionBuilder};
use super::memory::{self, MemoryBuilder}; use super::memory::{self, MemoryBuilder};
use super::table::{self, TableBuilder};
use super::import; use super::import;
use elements; use elements;
@ -208,6 +209,18 @@ impl<F> ModuleBuilder<F> where F: Invoke<elements::Module> {
(entries.len() - 1) as u32 (entries.len() - 1) as u32
} }
/// Push table
pub fn push_table(&mut self, mut table: table::TableDefinition) -> u32 {
let entries = self.module.table.entries_mut();
entries.push(elements::TableType::new(table.min, Some(table.min)));
let table_index = (entries.len() - 1) as u32;
for entry in table.elements.drain(..) {
self.module.element.entries_mut()
.push(elements::ElementSegment::new(table_index, entry.offset, entry.values))
}
table_index
}
fn resolve_type_ref(&mut self, signature: code::Signature) -> u32 { fn resolve_type_ref(&mut self, signature: code::Signature) -> u32 {
match signature { match signature {
code::Signature::Inline(func_type) => { code::Signature::Inline(func_type) => {
@ -254,6 +267,11 @@ impl<F> ModuleBuilder<F> where F: Invoke<elements::Module> {
MemoryBuilder::with_callback(self) MemoryBuilder::with_callback(self)
} }
/// Add new table using dedicated builder
pub fn table(self) -> TableBuilder<Self> {
TableBuilder::with_callback(self)
}
/// Define functions section /// Define functions section
pub fn functions(self) -> SignaturesBuilder<Self> { pub fn functions(self) -> SignaturesBuilder<Self> {
SignaturesBuilder::with_callback(self) SignaturesBuilder::with_callback(self)
@ -321,6 +339,18 @@ impl<F> Invoke<memory::MemoryDefinition> for ModuleBuilder<F>
} }
} }
impl<F> Invoke<table::TableDefinition> for ModuleBuilder<F>
where F: Invoke<elements::Module>
{
type Result = Self;
fn invoke(self, def: table::TableDefinition) -> Self {
let mut b = self;
b.push_table(def);
b
}
}
impl<F> Invoke<elements::ImportEntry> for ModuleBuilder<F> impl<F> Invoke<elements::ImportEntry> for ModuleBuilder<F>
where F: Invoke<elements::Module> where F: Invoke<elements::Module>
{ {

58
src/builder/table.rs Normal file
View File

@ -0,0 +1,58 @@
use elements;
use super::invoke::{Invoke, Identity};
pub struct TableDefinition {
pub min: u32,
pub elements: Vec<TableEntryDefinition>,
}
pub struct TableEntryDefinition {
pub offset: elements::InitExpr,
pub values: Vec<u32>,
}
pub struct TableBuilder<F=Identity> {
callback: F,
table: TableDefinition,
}
impl TableBuilder {
pub fn new() -> Self {
TableBuilder::with_callback(Identity)
}
}
impl<F> TableBuilder<F> where F: Invoke<TableDefinition> {
pub fn with_callback(callback: F) -> Self {
TableBuilder {
callback: callback,
table: Default::default(),
}
}
pub fn with_min(mut self, min: u32) -> Self {
self.table.min = min;
self
}
pub fn with_element(mut self, index: u32, values: Vec<u32>) -> Self {
self.table.elements.push(TableEntryDefinition {
offset: elements::InitExpr::new(vec![elements::Opcode::I32Const(index as i32)]),
values: values,
});
self
}
pub fn build(self) -> F::Result {
self.callback.invoke(self.table)
}
}
impl Default for TableDefinition {
fn default() -> Self {
TableDefinition {
min: 0,
elements: Vec::new(),
}
}
}

View File

@ -323,6 +323,11 @@ impl TableSection {
pub fn entries(&self) -> &[TableType] { pub fn entries(&self) -> &[TableType] {
&self.0 &self.0
} }
/// Mutable table entries.
pub fn entries_mut(&mut self) -> &mut Vec<TableType> {
&mut self.0
}
} }
impl Deserialize for TableSection { impl Deserialize for TableSection {
@ -538,6 +543,11 @@ impl ElementSection {
pub fn entries(&self) -> &[ElementSegment] { pub fn entries(&self) -> &[ElementSegment] {
&self.0 &self.0
} }
/// Mutable elements entries in the section
pub fn entries_mut(&mut self) -> &mut Vec<ElementSegment> {
&mut self.0
}
} }
impl Deserialize for ElementSection { impl Deserialize for ElementSection {

View File

@ -649,3 +649,56 @@ fn call_zero_args() {
let module = program.add_module("main", module).unwrap(); let module = program.add_module("main", module).unwrap();
assert_eq!(module.execute_main(vec![]).unwrap().unwrap(), RuntimeValue::I32(43)); assert_eq!(module.execute_main(vec![]).unwrap().unwrap(), RuntimeValue::I32(43));
} }
/// https://github.com/WebAssembly/wabt/blob/8e1f6031e9889ba770c7be4a9b084da5f14456a0/test/interp/callimport-zero-args.txt
#[test]
fn callimport_zero_zrgs() {
// TODO: import needed
}
/// https://github.com/WebAssembly/wabt/blob/8e1f6031e9889ba770c7be4a9b084da5f14456a0/test/interp/callindirect.txt#L31
#[test]
fn callindirect_1() {
let body1 = Opcodes::new(vec![
Opcode::I32Const(0),
Opcode::End,
]);
let body2 = Opcodes::new(vec![
Opcode::I32Const(1),
Opcode::End,
]);
let body3 = Opcodes::new(vec![
Opcode::GetLocal(0),
Opcode::CallIndirect(0, false),
Opcode::End,
]);
let module = module()
.table()
.with_min(2)
.with_element(0, vec![0, 1])
.build()
.function()
.signature().return_type().i32().build()
.body().with_opcodes(body1).build()
.build()
.function()
.signature().return_type().i32().build()
.body().with_opcodes(body2).build()
.build()
.function().main()
.signature()
.param().i32()
.return_type().i32()
.build()
.body().with_opcodes(body3).build()
.build()
.build();
let program = ProgramInstance::new();
let module = program.add_module("main", module).unwrap();
assert_eq!(module.execute_main(vec![RuntimeValue::I32(0)]).unwrap().unwrap(), RuntimeValue::I32(0));
assert_eq!(module.execute_main(vec![RuntimeValue::I32(1)]).unwrap().unwrap(), RuntimeValue::I32(1));
}