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:
oooooba
2018-10-20 02:49:41 +09:00
committed by Dan Gohman
parent e10a3434b8
commit 709eed21c1
5 changed files with 70 additions and 39 deletions

View File

@@ -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)?);
} }

View File

@@ -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,

View File

@@ -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"),
} }
} }

View File

@@ -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]))

View File

@@ -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)]