mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-06-14 15:31:44 +00:00
callindirect_1
This commit is contained in:
@ -6,6 +6,7 @@ mod code;
|
||||
mod misc;
|
||||
mod import;
|
||||
mod memory;
|
||||
mod table;
|
||||
|
||||
pub use self::module::{module, from_module, ModuleBuilder};
|
||||
pub use self::code::{signatures, signature, function};
|
||||
|
@ -1,6 +1,7 @@
|
||||
use super::invoke::{Invoke, Identity};
|
||||
use super::code::{self, SignaturesBuilder, FunctionBuilder};
|
||||
use super::memory::{self, MemoryBuilder};
|
||||
use super::table::{self, TableBuilder};
|
||||
use super::import;
|
||||
use elements;
|
||||
|
||||
@ -208,6 +209,18 @@ impl<F> ModuleBuilder<F> where F: Invoke<elements::Module> {
|
||||
(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 {
|
||||
match signature {
|
||||
code::Signature::Inline(func_type) => {
|
||||
@ -254,6 +267,11 @@ impl<F> ModuleBuilder<F> where F: Invoke<elements::Module> {
|
||||
MemoryBuilder::with_callback(self)
|
||||
}
|
||||
|
||||
/// Add new table using dedicated builder
|
||||
pub fn table(self) -> TableBuilder<Self> {
|
||||
TableBuilder::with_callback(self)
|
||||
}
|
||||
|
||||
/// Define functions section
|
||||
pub fn functions(self) -> SignaturesBuilder<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>
|
||||
where F: Invoke<elements::Module>
|
||||
{
|
||||
|
58
src/builder/table.rs
Normal file
58
src/builder/table.rs
Normal 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(),
|
||||
}
|
||||
}
|
||||
}
|
@ -323,6 +323,11 @@ impl TableSection {
|
||||
pub fn entries(&self) -> &[TableType] {
|
||||
&self.0
|
||||
}
|
||||
|
||||
/// Mutable table entries.
|
||||
pub fn entries_mut(&mut self) -> &mut Vec<TableType> {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for TableSection {
|
||||
@ -538,6 +543,11 @@ impl ElementSection {
|
||||
pub fn entries(&self) -> &[ElementSegment] {
|
||||
&self.0
|
||||
}
|
||||
|
||||
/// Mutable elements entries in the section
|
||||
pub fn entries_mut(&mut self) -> &mut Vec<ElementSegment> {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for ElementSection {
|
||||
|
@ -649,3 +649,56 @@ fn call_zero_args() {
|
||||
let module = program.add_module("main", module).unwrap();
|
||||
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));
|
||||
}
|
||||
|
Reference in New Issue
Block a user