Define a "table" concept.
"Table" is to WebAssembly tables as "Heap" is to WebAssembly linear memories.
This commit is contained in:
@@ -377,10 +377,12 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
||||
// `index` is the index of the function's signature and `table_index` is the index of
|
||||
// the table to search the function in.
|
||||
let (sigref, num_args) = state.get_indirect_sig(builder.func, index, environ);
|
||||
let table = state.get_table(builder.func, table_index, environ);
|
||||
let callee = state.pop1();
|
||||
let call = environ.translate_call_indirect(
|
||||
builder.cursor(),
|
||||
table_index as TableIndex,
|
||||
table,
|
||||
index as SignatureIndex,
|
||||
sigref,
|
||||
callee,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
//! "Dummy" environment for testing wasm translation.
|
||||
|
||||
use cranelift_codegen::cursor::FuncCursor;
|
||||
use cranelift_codegen::ir::immediates::Imm64;
|
||||
use cranelift_codegen::ir::types::*;
|
||||
use cranelift_codegen::ir::{self, InstBuilder};
|
||||
use cranelift_codegen::settings;
|
||||
@@ -169,7 +170,11 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ
|
||||
|
||||
fn make_heap(&mut self, func: &mut ir::Function, _index: MemoryIndex) -> ir::Heap {
|
||||
// Create a static heap whose base address is stored at `vmctx+0`.
|
||||
let gv = func.create_global_value(ir::GlobalValueData::VMContext { offset: 0.into() });
|
||||
let addr = func.create_global_value(ir::GlobalValueData::VMContext { offset: 0.into() });
|
||||
let gv = func.create_global_value(ir::GlobalValueData::Deref {
|
||||
base: addr,
|
||||
offset: 0.into(),
|
||||
});
|
||||
|
||||
func.create_heap(ir::HeapData {
|
||||
base: gv,
|
||||
@@ -181,6 +186,29 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ
|
||||
})
|
||||
}
|
||||
|
||||
fn make_table(&mut self, func: &mut ir::Function, _index: TableIndex) -> ir::Table {
|
||||
// Create a table whose base address is stored at `vmctx+0`.
|
||||
let base_gv_addr =
|
||||
func.create_global_value(ir::GlobalValueData::VMContext { offset: 0.into() });
|
||||
let base_gv = func.create_global_value(ir::GlobalValueData::Deref {
|
||||
base: base_gv_addr,
|
||||
offset: 0.into(),
|
||||
});
|
||||
let bound_gv_addr =
|
||||
func.create_global_value(ir::GlobalValueData::VMContext { offset: 0.into() });
|
||||
let bound_gv = func.create_global_value(ir::GlobalValueData::Deref {
|
||||
base: bound_gv_addr,
|
||||
offset: 0.into(),
|
||||
});
|
||||
|
||||
func.create_table(ir::TableData {
|
||||
base_gv,
|
||||
min_size: Imm64::new(0),
|
||||
bound_gv,
|
||||
element_size: Imm64::new(i64::from(self.pointer_bytes()) * 2),
|
||||
})
|
||||
}
|
||||
|
||||
fn make_indirect_sig(&mut self, func: &mut ir::Function, index: SignatureIndex) -> ir::SigRef {
|
||||
// A real implementation would probably change the calling convention and add `vmctx` and
|
||||
// signature index arguments.
|
||||
@@ -204,6 +232,7 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ
|
||||
&mut self,
|
||||
mut pos: FuncCursor,
|
||||
_table_index: TableIndex,
|
||||
_table: ir::Table,
|
||||
_sig_index: SignatureIndex,
|
||||
sig_ref: ir::SigRef,
|
||||
callee: ir::Value,
|
||||
|
||||
@@ -89,6 +89,11 @@ pub trait FuncEnvironment {
|
||||
ir::Type::int(u16::from(self.triple().pointer_width().unwrap().bits())).unwrap()
|
||||
}
|
||||
|
||||
/// Get the size of a native pointer, in bytes.
|
||||
fn pointer_bytes(&self) -> u8 {
|
||||
self.triple().pointer_width().unwrap().bytes()
|
||||
}
|
||||
|
||||
/// Set up the necessary preamble definitions in `func` to access the global variable
|
||||
/// identified by `index`.
|
||||
///
|
||||
@@ -104,6 +109,12 @@ pub trait FuncEnvironment {
|
||||
/// The index space covers both imported and locally declared memories.
|
||||
fn make_heap(&mut self, func: &mut ir::Function, index: MemoryIndex) -> ir::Heap;
|
||||
|
||||
/// Set up the necessary preamble definitions in `func` to access the table identified
|
||||
/// by `index`.
|
||||
///
|
||||
/// The index space covers both imported and locally declared tables.
|
||||
fn make_table(&mut self, func: &mut ir::Function, index: TableIndex) -> ir::Table;
|
||||
|
||||
/// Set up a signature definition in the preamble of `func` that can be used for an indirect
|
||||
/// call with signature `index`.
|
||||
///
|
||||
@@ -141,6 +152,7 @@ pub trait FuncEnvironment {
|
||||
&mut self,
|
||||
pos: FuncCursor,
|
||||
table_index: TableIndex,
|
||||
table: ir::Table,
|
||||
sig_index: SignatureIndex,
|
||||
sig_ref: ir::SigRef,
|
||||
callee: ir::Value,
|
||||
|
||||
@@ -7,7 +7,7 @@ use cranelift_codegen::ir::{self, Ebb, Inst, Value};
|
||||
use environ::{FuncEnvironment, GlobalVariable};
|
||||
use std::collections::HashMap;
|
||||
use std::vec::Vec;
|
||||
use translation_utils::{FunctionIndex, GlobalIndex, MemoryIndex, SignatureIndex};
|
||||
use translation_utils::{FunctionIndex, GlobalIndex, MemoryIndex, SignatureIndex, TableIndex};
|
||||
|
||||
/// A control stack frame can be an `if`, a `block` or a `loop`, each one having the following
|
||||
/// fields:
|
||||
@@ -140,6 +140,9 @@ pub struct TranslationState {
|
||||
// Map of heaps that have been created by `FuncEnvironment::make_heap`.
|
||||
heaps: HashMap<MemoryIndex, ir::Heap>,
|
||||
|
||||
// Map of tables that have been created by `FuncEnvironment::make_table`.
|
||||
tables: HashMap<TableIndex, ir::Table>,
|
||||
|
||||
// Map of indirect call signatures that have been created by
|
||||
// `FuncEnvironment::make_indirect_sig()`.
|
||||
// Stores both the signature reference and the number of WebAssembly arguments
|
||||
@@ -159,6 +162,7 @@ impl TranslationState {
|
||||
reachable: true,
|
||||
globals: HashMap::new(),
|
||||
heaps: HashMap::new(),
|
||||
tables: HashMap::new(),
|
||||
signatures: HashMap::new(),
|
||||
functions: HashMap::new(),
|
||||
}
|
||||
@@ -303,6 +307,21 @@ impl TranslationState {
|
||||
.or_insert_with(|| environ.make_heap(func, index))
|
||||
}
|
||||
|
||||
/// Get the `Table` reference that should be used to access table `index`.
|
||||
/// Create the reference if necessary.
|
||||
pub fn get_table<FE: FuncEnvironment + ?Sized>(
|
||||
&mut self,
|
||||
func: &mut ir::Function,
|
||||
index: u32,
|
||||
environ: &mut FE,
|
||||
) -> ir::Table {
|
||||
let index = index as TableIndex;
|
||||
*self
|
||||
.tables
|
||||
.entry(index)
|
||||
.or_insert_with(|| environ.make_table(func, index))
|
||||
}
|
||||
|
||||
/// Get the `SigRef` reference that should be used to make an indirect call with signature
|
||||
/// `index`. Also return the number of WebAssembly arguments in the signature.
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user