Complete support for global init expressions.

This commit is contained in:
Dan Gohman
2017-10-10 09:35:10 -07:00
parent 653e8bb563
commit 8e1ba080c0
3 changed files with 25 additions and 57 deletions

View File

@@ -197,6 +197,7 @@ impl WasmRuntime for DummyRuntime {
fn declare_table_elements( fn declare_table_elements(
&mut self, &mut self,
_table_index: TableIndex, _table_index: TableIndex,
_base: Option<GlobalIndex>,
_offset: usize, _offset: usize,
_elements: &[FunctionIndex], _elements: &[FunctionIndex],
) { ) {
@@ -208,11 +209,11 @@ impl WasmRuntime for DummyRuntime {
fn declare_data_initialization( fn declare_data_initialization(
&mut self, &mut self,
_memory_index: MemoryIndex, _memory_index: MemoryIndex,
_base: Option<GlobalIndex>,
_offset: usize, _offset: usize,
_data: &[u8], _data: &[u8],
) -> Result<(), String> { ) {
// We do nothing // We do nothing
Ok(())
} }
fn declare_func_export(&mut self, func_index: FunctionIndex, name: &str) { fn declare_func_export(&mut self, func_index: FunctionIndex, name: &str) {

View File

@@ -183,6 +183,7 @@ pub trait WasmRuntime: FuncEnvironment {
fn declare_table_elements( fn declare_table_elements(
&mut self, &mut self,
table_index: TableIndex, table_index: TableIndex,
base: Option<GlobalIndex>,
offset: usize, offset: usize,
elements: &[FunctionIndex], elements: &[FunctionIndex],
); );
@@ -192,9 +193,10 @@ pub trait WasmRuntime: FuncEnvironment {
fn declare_data_initialization( fn declare_data_initialization(
&mut self, &mut self,
memory_index: MemoryIndex, memory_index: MemoryIndex,
base: Option<GlobalIndex>,
offset: usize, offset: usize,
data: &[u8], data: &[u8],
) -> Result<(), String>; );
/// Declares a function export to the runtime. /// Declares a function export to the runtime.
fn declare_func_export(&mut self, func_index: FunctionIndex, name: &str); fn declare_func_export(&mut self, func_index: FunctionIndex, name: &str);

View File

@@ -101,7 +101,7 @@ pub fn parse_import_section(
}, },
size: tab.limits.initial as usize, size: tab.limits.initial as usize,
maximum: tab.limits.maximum.map(|x| x as usize), maximum: tab.limits.maximum.map(|x| x as usize),
}); })
} }
ParserState::EndSection => break, ParserState::EndSection => break,
ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))),
@@ -227,7 +227,6 @@ pub fn parse_global_section(
GlobalInit::GlobalRef(global_index as GlobalIndex) GlobalInit::GlobalRef(global_index as GlobalIndex)
} }
ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))),
}; };
match *parser.read() { match *parser.read() {
ParserState::EndInitExpressionBody => (), ParserState::EndInitExpressionBody => (),
@@ -261,35 +260,14 @@ pub fn parse_data_section(
ParserState::BeginInitExpressionBody => (), ParserState::BeginInitExpressionBody => (),
ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))),
}; };
let mut offset = match *parser.read() { let (base, offset) = match *parser.read() {
ParserState::InitExpressionOperator(Operator::I32Const { value }) => { ParserState::InitExpressionOperator(Operator::I32Const { value }) => {
if value < 0 { (None, value as u32 as usize)
return Err(SectionParsingError::WrongSectionContent(String::from(
"negative \
offset value",
)));
} else {
value as usize
}
} }
ParserState::InitExpressionOperator(Operator::GetGlobal { global_index }) => { ParserState::InitExpressionOperator(Operator::GetGlobal { global_index }) => {
match runtime.get_global(global_index as GlobalIndex).initializer { match runtime.get_global(global_index as GlobalIndex).initializer {
GlobalInit::I32Const(value) => { GlobalInit::I32Const(value) => (None, value as u32 as usize),
if value < 0 { GlobalInit::Import() => (Some(global_index as GlobalIndex), 0),
return Err(SectionParsingError::WrongSectionContent(String::from(
"\
negative offset value",
)));
} else {
value as usize
}
}
GlobalInit::Import() => {
return Err(SectionParsingError::WrongSectionContent(String::from(
"\
imported globals not supported",
)))
} // TODO: add runtime support
_ => panic!("should not happen"), _ => panic!("should not happen"),
} }
} }
@@ -303,17 +281,20 @@ pub fn parse_data_section(
ParserState::BeginDataSectionEntryBody(_) => (), ParserState::BeginDataSectionEntryBody(_) => (),
ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))),
}; };
let mut running_offset = offset;
loop { loop {
let data = match *parser.read() { let data = match *parser.read() {
ParserState::DataSectionEntryBodyChunk(data) => data, ParserState::DataSectionEntryBodyChunk(data) => data,
ParserState::EndDataSectionEntryBody => break, ParserState::EndDataSectionEntryBody => break,
ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))),
}; };
match runtime.declare_data_initialization(memory_index as MemoryIndex, offset, data) { runtime.declare_data_initialization(
Ok(()) => (), memory_index as MemoryIndex,
Err(s) => return Err(SectionParsingError::WrongSectionContent(s)), base,
}; running_offset,
offset += data.len(); data,
);
running_offset += data.len();
} }
match *parser.read() { match *parser.read() {
ParserState::EndDataSectionEntry => (), ParserState::EndDataSectionEntry => (),
@@ -354,7 +335,7 @@ pub fn parse_elements_section(
) -> Result<(), SectionParsingError> { ) -> Result<(), SectionParsingError> {
loop { loop {
let table_index = match *parser.read() { let table_index = match *parser.read() {
ParserState::BeginElementSectionEntry(ref table_index) => *table_index as TableIndex, ParserState::BeginElementSectionEntry(table_index) => table_index as TableIndex,
ParserState::EndSection => break, ParserState::EndSection => break,
ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))),
}; };
@@ -362,30 +343,14 @@ pub fn parse_elements_section(
ParserState::BeginInitExpressionBody => (), ParserState::BeginInitExpressionBody => (),
ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))),
}; };
let offset = match *parser.read() { let (base, offset) = match *parser.read() {
ParserState::InitExpressionOperator(Operator::I32Const { value }) => { ParserState::InitExpressionOperator(Operator::I32Const { value }) => {
if value < 0 { (None, value as u32 as usize)
return Err(SectionParsingError::WrongSectionContent(String::from(
"negative \
offset value",
)));
} else {
value as usize
}
} }
ParserState::InitExpressionOperator(Operator::GetGlobal { global_index }) => { ParserState::InitExpressionOperator(Operator::GetGlobal { global_index }) => {
match runtime.get_global(global_index as GlobalIndex).initializer { match runtime.get_global(global_index as GlobalIndex).initializer {
GlobalInit::I32Const(value) => { GlobalInit::I32Const(value) => (None, value as u32 as usize),
if value < 0 { GlobalInit::Import() => (Some(global_index as GlobalIndex), 0),
return Err(SectionParsingError::WrongSectionContent(String::from(
"\
negative offset value",
)));
} else {
value as usize
}
}
GlobalInit::Import() => 0, // TODO: add runtime support
_ => panic!("should not happen"), _ => panic!("should not happen"),
} }
} }
@@ -399,7 +364,7 @@ pub fn parse_elements_section(
ParserState::ElementSectionEntryBody(ref elements) => { ParserState::ElementSectionEntryBody(ref elements) => {
let elems: Vec<FunctionIndex> = let elems: Vec<FunctionIndex> =
elements.iter().map(|&x| x as FunctionIndex).collect(); elements.iter().map(|&x| x as FunctionIndex).collect();
runtime.declare_table_elements(table_index, offset, &elems) runtime.declare_table_elements(table_index, base, offset, &elems)
} }
ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))),
}; };