Use types to represent wasm global/table/memory/signature indices (#560)
* Use a type to represent wasm table indices. * Use a type to represent wasm global variable indices. * Use a type to represent wasm memory indices. * Use a type to represent wasm signature indices. * Use PrimaryMap instead of Vec to protect against using wrong indices.
This commit is contained in:
@@ -380,9 +380,9 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||||||
let callee = state.pop1();
|
let callee = state.pop1();
|
||||||
let call = environ.translate_call_indirect(
|
let call = environ.translate_call_indirect(
|
||||||
builder.cursor(),
|
builder.cursor(),
|
||||||
table_index as TableIndex,
|
TableIndex::new(table_index as usize),
|
||||||
table,
|
table,
|
||||||
index as SignatureIndex,
|
SignatureIndex::new(index as usize),
|
||||||
sigref,
|
sigref,
|
||||||
callee,
|
callee,
|
||||||
state.peekn(num_args),
|
state.peekn(num_args),
|
||||||
@@ -403,13 +403,13 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||||||
Operator::MemoryGrow { reserved } => {
|
Operator::MemoryGrow { reserved } => {
|
||||||
// The WebAssembly MVP only supports one linear memory, but we expect the reserved
|
// The WebAssembly MVP only supports one linear memory, but we expect the reserved
|
||||||
// argument to be a memory index.
|
// argument to be a memory index.
|
||||||
let heap_index = reserved as MemoryIndex;
|
let heap_index = MemoryIndex::new(reserved as usize);
|
||||||
let heap = state.get_heap(builder.func, reserved, environ);
|
let heap = state.get_heap(builder.func, reserved, environ);
|
||||||
let val = state.pop1();
|
let val = state.pop1();
|
||||||
state.push1(environ.translate_memory_grow(builder.cursor(), heap_index, heap, val)?)
|
state.push1(environ.translate_memory_grow(builder.cursor(), heap_index, heap, val)?)
|
||||||
}
|
}
|
||||||
Operator::MemorySize { reserved } => {
|
Operator::MemorySize { reserved } => {
|
||||||
let heap_index = reserved as MemoryIndex;
|
let heap_index = MemoryIndex::new(reserved as usize);
|
||||||
let heap = state.get_heap(builder.func, reserved, environ);
|
let heap = state.get_heap(builder.func, reserved, environ);
|
||||||
state.push1(environ.translate_memory_size(builder.cursor(), heap_index, heap)?);
|
state.push1(environ.translate_memory_size(builder.cursor(), heap_index, heap)?);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ pub struct DummyModuleInfo {
|
|||||||
pub flags: settings::Flags,
|
pub flags: settings::Flags,
|
||||||
|
|
||||||
/// Signatures as provided by `declare_signature`.
|
/// Signatures as provided by `declare_signature`.
|
||||||
pub signatures: Vec<ir::Signature>,
|
pub signatures: PrimaryMap<SignatureIndex, ir::Signature>,
|
||||||
|
|
||||||
/// Module and field names of imported functions as provided by `declare_func_import`.
|
/// Module and field names of imported functions as provided by `declare_func_import`.
|
||||||
pub imported_funcs: Vec<(String, String)>,
|
pub imported_funcs: Vec<(String, String)>,
|
||||||
@@ -63,13 +63,13 @@ pub struct DummyModuleInfo {
|
|||||||
pub function_bodies: PrimaryMap<DefinedFuncIndex, ir::Function>,
|
pub function_bodies: PrimaryMap<DefinedFuncIndex, ir::Function>,
|
||||||
|
|
||||||
/// Tables as provided by `declare_table`.
|
/// Tables as provided by `declare_table`.
|
||||||
pub tables: Vec<Exportable<Table>>,
|
pub tables: PrimaryMap<TableIndex, Exportable<Table>>,
|
||||||
|
|
||||||
/// Memories as provided by `declare_memory`.
|
/// Memories as provided by `declare_memory`.
|
||||||
pub memories: Vec<Exportable<Memory>>,
|
pub memories: PrimaryMap<MemoryIndex, Exportable<Memory>>,
|
||||||
|
|
||||||
/// Globals as provided by `declare_global`.
|
/// Globals as provided by `declare_global`.
|
||||||
pub globals: Vec<Exportable<Global>>,
|
pub globals: PrimaryMap<GlobalIndex, Exportable<Global>>,
|
||||||
|
|
||||||
/// The start function.
|
/// The start function.
|
||||||
pub start_func: Option<FuncIndex>,
|
pub start_func: Option<FuncIndex>,
|
||||||
@@ -81,13 +81,13 @@ impl DummyModuleInfo {
|
|||||||
Self {
|
Self {
|
||||||
triple,
|
triple,
|
||||||
flags,
|
flags,
|
||||||
signatures: Vec::new(),
|
signatures: PrimaryMap::new(),
|
||||||
imported_funcs: Vec::new(),
|
imported_funcs: Vec::new(),
|
||||||
functions: PrimaryMap::new(),
|
functions: PrimaryMap::new(),
|
||||||
function_bodies: PrimaryMap::new(),
|
function_bodies: PrimaryMap::new(),
|
||||||
tables: Vec::new(),
|
tables: PrimaryMap::new(),
|
||||||
memories: Vec::new(),
|
memories: PrimaryMap::new(),
|
||||||
globals: Vec::new(),
|
globals: PrimaryMap::new(),
|
||||||
start_func: None,
|
start_func: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,7 +179,7 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ
|
|||||||
|
|
||||||
fn make_global(&mut self, func: &mut ir::Function, index: GlobalIndex) -> GlobalVariable {
|
fn make_global(&mut self, func: &mut ir::Function, index: GlobalIndex) -> GlobalVariable {
|
||||||
// Just create a dummy `vmctx` global.
|
// Just create a dummy `vmctx` global.
|
||||||
let offset = ((index * 8) as i64 + 8).into();
|
let offset = ((index.index() * 8) as i64 + 8).into();
|
||||||
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext {});
|
let vmctx = func.create_global_value(ir::GlobalValueData::VMContext {});
|
||||||
let iadd = func.create_global_value(ir::GlobalValueData::IAddImm {
|
let iadd = func.create_global_value(ir::GlobalValueData::IAddImm {
|
||||||
base: vmctx,
|
base: vmctx,
|
||||||
|
|||||||
@@ -72,7 +72,11 @@ pub fn parse_import_section<'data>(
|
|||||||
// becomes a concern here.
|
// becomes a concern here.
|
||||||
let module_name = from_utf8(module).unwrap();
|
let module_name = from_utf8(module).unwrap();
|
||||||
let field_name = from_utf8(field).unwrap();
|
let field_name = from_utf8(field).unwrap();
|
||||||
environ.declare_func_import(sig as SignatureIndex, module_name, field_name);
|
environ.declare_func_import(
|
||||||
|
SignatureIndex::new(sig as usize),
|
||||||
|
module_name,
|
||||||
|
field_name,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
ParserState::ImportSectionEntry {
|
ParserState::ImportSectionEntry {
|
||||||
ty:
|
ty:
|
||||||
@@ -125,7 +129,7 @@ pub fn parse_function_section(
|
|||||||
loop {
|
loop {
|
||||||
match *parser.read() {
|
match *parser.read() {
|
||||||
ParserState::FunctionSectionEntry(sigindex) => {
|
ParserState::FunctionSectionEntry(sigindex) => {
|
||||||
environ.declare_func_type(sigindex as SignatureIndex);
|
environ.declare_func_type(SignatureIndex::new(sigindex as usize));
|
||||||
}
|
}
|
||||||
ParserState::EndSection => break,
|
ParserState::EndSection => break,
|
||||||
ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)),
|
ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)),
|
||||||
@@ -151,12 +155,20 @@ pub fn parse_export_section<'data>(
|
|||||||
// assume valid UTF-8 and use `from_utf8_unchecked` if performance
|
// assume valid UTF-8 and use `from_utf8_unchecked` if performance
|
||||||
// becomes a concern here.
|
// becomes a concern here.
|
||||||
let name = from_utf8(field).unwrap();
|
let name = from_utf8(field).unwrap();
|
||||||
let func_index = FuncIndex::new(index as usize);
|
let index = index as usize;
|
||||||
match *kind {
|
match *kind {
|
||||||
ExternalKind::Function => environ.declare_func_export(func_index, name),
|
ExternalKind::Function => {
|
||||||
ExternalKind::Table => environ.declare_table_export(func_index.index(), name),
|
environ.declare_func_export(FuncIndex::new(index), name)
|
||||||
ExternalKind::Memory => environ.declare_memory_export(func_index.index(), name),
|
}
|
||||||
ExternalKind::Global => environ.declare_global_export(func_index.index(), name),
|
ExternalKind::Table => {
|
||||||
|
environ.declare_table_export(TableIndex::new(index), name)
|
||||||
|
}
|
||||||
|
ExternalKind::Memory => {
|
||||||
|
environ.declare_memory_export(MemoryIndex::new(index), name)
|
||||||
|
}
|
||||||
|
ExternalKind::Global => {
|
||||||
|
environ.declare_global_export(GlobalIndex::new(index), name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ParserState::EndSection => break,
|
ParserState::EndSection => break,
|
||||||
@@ -235,7 +247,7 @@ pub fn parse_global_section(
|
|||||||
GlobalInit::F64Const(value.bits())
|
GlobalInit::F64Const(value.bits())
|
||||||
}
|
}
|
||||||
ParserState::InitExpressionOperator(Operator::GetGlobal { global_index }) => {
|
ParserState::InitExpressionOperator(Operator::GetGlobal { global_index }) => {
|
||||||
GlobalInit::GlobalRef(global_index as GlobalIndex)
|
GlobalInit::GlobalRef(GlobalIndex::new(global_index as usize))
|
||||||
}
|
}
|
||||||
ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)),
|
ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)),
|
||||||
ref s => panic!("unexpected section content: {:?}", s),
|
ref s => panic!("unexpected section content: {:?}", s),
|
||||||
@@ -281,9 +293,12 @@ pub fn parse_data_section<'data>(
|
|||||||
(None, value as u32 as usize)
|
(None, value as u32 as usize)
|
||||||
}
|
}
|
||||||
ParserState::InitExpressionOperator(Operator::GetGlobal { global_index }) => {
|
ParserState::InitExpressionOperator(Operator::GetGlobal { global_index }) => {
|
||||||
match environ.get_global(global_index as GlobalIndex).initializer {
|
match environ
|
||||||
|
.get_global(GlobalIndex::new(global_index as usize))
|
||||||
|
.initializer
|
||||||
|
{
|
||||||
GlobalInit::I32Const(value) => (None, value as u32 as usize),
|
GlobalInit::I32Const(value) => (None, value as u32 as usize),
|
||||||
GlobalInit::Import() => (Some(global_index as GlobalIndex), 0),
|
GlobalInit::Import() => (Some(GlobalIndex::new(global_index as usize)), 0),
|
||||||
_ => panic!("should not happen"),
|
_ => panic!("should not happen"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -309,7 +324,7 @@ pub fn parse_data_section<'data>(
|
|||||||
ref s => panic!("unexpected section content: {:?}", s),
|
ref s => panic!("unexpected section content: {:?}", s),
|
||||||
};
|
};
|
||||||
environ.declare_data_initialization(
|
environ.declare_data_initialization(
|
||||||
memory_index as MemoryIndex,
|
MemoryIndex::new(memory_index as usize),
|
||||||
base,
|
base,
|
||||||
running_offset,
|
running_offset,
|
||||||
data,
|
data,
|
||||||
@@ -352,7 +367,9 @@ pub fn parse_elements_section(
|
|||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
loop {
|
loop {
|
||||||
let table_index = match *parser.read() {
|
let table_index = match *parser.read() {
|
||||||
ParserState::BeginElementSectionEntry(table_index) => table_index as TableIndex,
|
ParserState::BeginElementSectionEntry(table_index) => {
|
||||||
|
TableIndex::new(table_index as usize)
|
||||||
|
}
|
||||||
ParserState::EndSection => break,
|
ParserState::EndSection => break,
|
||||||
ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)),
|
ParserState::Error(e) => return Err(WasmError::from_binary_reader_error(e)),
|
||||||
ref s => panic!("unexpected section content: {:?}", s),
|
ref s => panic!("unexpected section content: {:?}", s),
|
||||||
@@ -367,9 +384,12 @@ pub fn parse_elements_section(
|
|||||||
(None, value as u32 as usize)
|
(None, value as u32 as usize)
|
||||||
}
|
}
|
||||||
ParserState::InitExpressionOperator(Operator::GetGlobal { global_index }) => {
|
ParserState::InitExpressionOperator(Operator::GetGlobal { global_index }) => {
|
||||||
match environ.get_global(global_index as GlobalIndex).initializer {
|
match environ
|
||||||
|
.get_global(GlobalIndex::new(global_index as usize))
|
||||||
|
.initializer
|
||||||
|
{
|
||||||
GlobalInit::I32Const(value) => (None, value as u32 as usize),
|
GlobalInit::I32Const(value) => (None, value as u32 as usize),
|
||||||
GlobalInit::Import() => (Some(global_index as GlobalIndex), 0),
|
GlobalInit::Import() => (Some(GlobalIndex::new(global_index as usize)), 0),
|
||||||
_ => panic!("should not happen"),
|
_ => panic!("should not happen"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ impl TranslationState {
|
|||||||
index: u32,
|
index: u32,
|
||||||
environ: &mut FE,
|
environ: &mut FE,
|
||||||
) -> GlobalVariable {
|
) -> GlobalVariable {
|
||||||
let index = index as GlobalIndex;
|
let index = GlobalIndex::new(index as usize);
|
||||||
*self
|
*self
|
||||||
.globals
|
.globals
|
||||||
.entry(index)
|
.entry(index)
|
||||||
@@ -302,7 +302,7 @@ impl TranslationState {
|
|||||||
index: u32,
|
index: u32,
|
||||||
environ: &mut FE,
|
environ: &mut FE,
|
||||||
) -> ir::Heap {
|
) -> ir::Heap {
|
||||||
let index = index as MemoryIndex;
|
let index = MemoryIndex::new(index as usize);
|
||||||
*self
|
*self
|
||||||
.heaps
|
.heaps
|
||||||
.entry(index)
|
.entry(index)
|
||||||
@@ -317,7 +317,7 @@ impl TranslationState {
|
|||||||
index: u32,
|
index: u32,
|
||||||
environ: &mut FE,
|
environ: &mut FE,
|
||||||
) -> ir::Table {
|
) -> ir::Table {
|
||||||
let index = index as TableIndex;
|
let index = TableIndex::new(index as usize);
|
||||||
*self
|
*self
|
||||||
.tables
|
.tables
|
||||||
.entry(index)
|
.entry(index)
|
||||||
@@ -334,7 +334,7 @@ impl TranslationState {
|
|||||||
index: u32,
|
index: u32,
|
||||||
environ: &mut FE,
|
environ: &mut FE,
|
||||||
) -> (ir::SigRef, usize) {
|
) -> (ir::SigRef, usize) {
|
||||||
let index = index as SignatureIndex;
|
let index = SignatureIndex::new(index as usize);
|
||||||
*self.signatures.entry(index).or_insert_with(|| {
|
*self.signatures.entry(index).or_insert_with(|| {
|
||||||
let sig = environ.make_indirect_sig(func, index);
|
let sig = environ.make_indirect_sig(func, index);
|
||||||
(sig, normal_args(&func.dfg.signatures[sig]))
|
(sig, normal_args(&func.dfg.signatures[sig]))
|
||||||
|
|||||||
@@ -13,14 +13,25 @@ entity_impl!(FuncIndex);
|
|||||||
pub struct DefinedFuncIndex(u32);
|
pub struct DefinedFuncIndex(u32);
|
||||||
entity_impl!(DefinedFuncIndex);
|
entity_impl!(DefinedFuncIndex);
|
||||||
|
|
||||||
/// Index of a table (imported or defined) inside the WebAssembly module.
|
/// Index type of a table (imported or defined) inside the WebAssembly module.
|
||||||
pub type TableIndex = usize;
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
||||||
/// Index of a global variable (imported or defined) inside the WebAssembly module.
|
pub struct TableIndex(u32);
|
||||||
pub type GlobalIndex = usize;
|
entity_impl!(TableIndex);
|
||||||
/// Index of a linear memory (imported or defined) inside the WebAssembly module.
|
|
||||||
pub type MemoryIndex = usize;
|
/// Index type of a global variable (imported or defined) inside the WebAssembly module.
|
||||||
/// Index of a signature (imported or defined) inside the WebAssembly module.
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
||||||
pub type SignatureIndex = usize;
|
pub struct GlobalIndex(u32);
|
||||||
|
entity_impl!(GlobalIndex);
|
||||||
|
|
||||||
|
/// Index type of a linear memory (imported or defined) inside the WebAssembly module.
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
||||||
|
pub struct MemoryIndex(u32);
|
||||||
|
entity_impl!(MemoryIndex);
|
||||||
|
|
||||||
|
/// Index type of a signature (imported or defined) inside the WebAssembly module.
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
|
||||||
|
pub struct SignatureIndex(u32);
|
||||||
|
entity_impl!(SignatureIndex);
|
||||||
|
|
||||||
/// WebAssembly global.
|
/// WebAssembly global.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
|||||||
Reference in New Issue
Block a user