diff --git a/src/frontend.rs b/src/frontend.rs index 2a1fdc5..a84317c 100644 --- a/src/frontend.rs +++ b/src/frontend.rs @@ -27,11 +27,14 @@ pub fn wasm_to_ir(bytes: &[u8]) -> Result> { Ok(module) } -fn parse_init_expr<'a>(init_expr: &wasmparser::InitExpr<'a>) -> Result { +fn parse_init_expr<'a>(init_expr: &wasmparser::InitExpr<'a>) -> Result> { let operators = init_expr .get_operators_reader() .into_iter() .collect::, _>>()?; + if operators.len() == 1 && matches!(&operators[0], &wasmparser::Operator::End) { + return Ok(None); + } if operators.len() != 2 || !matches!(&operators[1], &wasmparser::Operator::End) { anyhow::bail!( "Unsupported operator seq in base-address expr: {:?}", @@ -39,8 +42,10 @@ fn parse_init_expr<'a>(init_expr: &wasmparser::InitExpr<'a>) -> Result { ); } Ok(match &operators[0] { - &wasmparser::Operator::I32Const { value } => value as usize, - &wasmparser::Operator::I64Const { value } => value as usize, + &wasmparser::Operator::I32Const { value } => Some(value as u64), + &wasmparser::Operator::I64Const { value } => Some(value as u64), + &wasmparser::Operator::F32Const { value } => Some(value.bits() as u64), + &wasmparser::Operator::F64Const { value } => Some(value.bits()), op => anyhow::bail!("Unsupported data segment base-address operator: {:?}", op), }) } @@ -73,7 +78,8 @@ fn handle_payload<'a>( Some(ImportKind::Func(func)) } ImportSectionEntryType::Global(ty) => { - let global = module.frontend_add_global(ty.content_type.into()); + let ty = ty.content_type.into(); + let global = module.frontend_add_global(GlobalData { ty, value: None }); Some(ImportKind::Global(global)) } ImportSectionEntryType::Table(ty) => { @@ -94,7 +100,12 @@ fn handle_payload<'a>( Payload::GlobalSection(reader) => { for global in reader { let global = global?; - module.frontend_add_global(global.ty.content_type.into()); + let ty = global.ty.content_type.into(); + let init_expr = parse_init_expr(&global.init_expr)?; + module.frontend_add_global(GlobalData { + ty, + value: init_expr, + }); } } Payload::TableSection(reader) => { @@ -156,9 +167,9 @@ fn handle_payload<'a>( } => { let data = segment.data.to_vec(); let memory = Memory::from(*memory_index); - let offset = parse_init_expr(init_expr)?; + let offset = parse_init_expr(init_expr)?.unwrap_or(0) as usize; module - .frontend_memory_mut(memory) + .memory_mut(memory) .segments .push(MemorySegment { offset, data }); } @@ -182,7 +193,7 @@ fn handle_payload<'a>( init_expr, } => { let table = Table::from(*table_index); - let offset = parse_init_expr(&init_expr)?; + let offset = parse_init_expr(&init_expr)?.unwrap_or(0) as usize; let items = element .items .get_items_reader()? @@ -197,11 +208,7 @@ fn handle_payload<'a>( funcs.push(func); } - let table_items = module - .frontend_table_mut(table) - .func_elements - .as_mut() - .unwrap(); + let table_items = module.table_mut(table).func_elements.as_mut().unwrap(); if (offset + funcs.len()) > table_items.len() { table_items.resize(offset + funcs.len(), Func::invalid()); } diff --git a/src/ir/display.rs b/src/ir/display.rs index 95fae3a..c7da2f9 100644 --- a/src/ir/display.rs +++ b/src/ir/display.rs @@ -155,8 +155,12 @@ impl<'a> Display for ModuleDisplay<'a> { sig_strs.insert(sig, sig_str.clone()); writeln!(f, " {}: {}", sig, sig_str)?; } - for (global, global_ty) in self.0.globals() { - writeln!(f, " {}: {}", global, global_ty)?; + for (global, global_data) in self.0.globals() { + writeln!( + f, + " {}: {:?} # {}", + global, global_data.value, global_data.ty + )?; } for (table, table_data) in self.0.tables() { writeln!(f, " {}: {}", table, table_data.ty)?; diff --git a/src/ir/module.rs b/src/ir/module.rs index 9730827..8d3c1f1 100644 --- a/src/ir/module.rs +++ b/src/ir/module.rs @@ -9,7 +9,7 @@ pub struct Module<'a> { orig_bytes: &'a [u8], funcs: EntityVec, signatures: EntityVec, - globals: EntityVec, + globals: EntityVec, tables: EntityVec, imports: Vec, exports: Vec, @@ -43,6 +43,12 @@ pub struct TableData { pub func_elements: Option>, } +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct GlobalData { + pub ty: Type, + pub value: Option, +} + impl From<&wasmparser::FuncType> for SignatureData { fn from(fty: &wasmparser::FuncType) -> Self { Self { @@ -149,11 +155,11 @@ impl<'a> Module<'a> { pub fn signatures<'b>(&'b self) -> impl Iterator { self.signatures.entries() } - pub fn global_ty(&self, id: Global) -> Type { - self.globals[id] + pub fn global<'b>(&'b self, id: Global) -> &'b GlobalData { + &self.globals[id] } - pub fn globals<'b>(&'b self) -> impl Iterator + 'b { - self.globals.entries().map(|(id, ty)| (id, *ty)) + pub fn globals<'b>(&'b self) -> impl Iterator + 'b { + self.globals.entries() } pub fn table<'b>(&'b self, id: Table) -> &'b TableData { &self.tables[id] @@ -170,6 +176,12 @@ impl<'a> Module<'a> { pub fn exports<'b>(&'b self) -> impl Iterator + 'b { self.exports.iter() } + pub(crate) fn table_mut<'b>(&'b mut self, table: Table) -> &'b mut TableData { + &mut self.tables[table] + } + pub(crate) fn memory_mut<'b>(&'b mut self, memory: Memory) -> &'b mut MemoryData { + &mut self.memories[memory] + } pub(crate) fn frontend_add_signature(&mut self, ty: SignatureData) { self.signatures.push(ty); @@ -185,11 +197,8 @@ impl<'a> Module<'a> { }; self.tables.push(TableData { ty, func_elements }) } - pub(crate) fn frontend_table_mut<'b>(&'b mut self, table: Table) -> &'b mut TableData { - &mut self.tables[table] - } - pub(crate) fn frontend_add_global(&mut self, ty: Type) -> Global { - self.globals.push(ty) + pub(crate) fn frontend_add_global(&mut self, global: GlobalData) -> Global { + self.globals.push(global) } pub(crate) fn frontend_add_import(&mut self, import: Import) { self.imports.push(import); @@ -200,9 +209,6 @@ impl<'a> Module<'a> { pub(crate) fn frontend_add_memory(&mut self, memory: MemoryData) -> Memory { self.memories.push(memory) } - pub(crate) fn frontend_memory_mut<'b>(&'b mut self, memory: Memory) -> &'b mut MemoryData { - &mut self.memories[memory] - } pub fn from_wasm_bytes(bytes: &'a [u8]) -> Result { let mut module = frontend::wasm_to_ir(bytes)?; diff --git a/src/op_traits.rs b/src/op_traits.rs index 0d50ae5..0045a8c 100644 --- a/src/op_traits.rs +++ b/src/op_traits.rs @@ -39,7 +39,7 @@ pub fn op_inputs( &Operator::TypedSelect { ty } => Ok(vec![ty, ty, Type::I32].into()), &Operator::GlobalGet { .. } => Ok(Cow::Borrowed(&[])), - &Operator::GlobalSet { global_index } => Ok(vec![module.global_ty(global_index)].into()), + &Operator::GlobalSet { global_index } => Ok(vec![module.global(global_index).ty].into()), Operator::I32Load { .. } | Operator::I64Load { .. } @@ -258,7 +258,7 @@ pub fn op_outputs( Ok(vec![val_ty].into()) } &Operator::TypedSelect { ty } => Ok(vec![ty].into()), - &Operator::GlobalGet { global_index } => Ok(vec![module.global_ty(global_index)].into()), + &Operator::GlobalGet { global_index } => Ok(vec![module.global(global_index).ty].into()), &Operator::GlobalSet { .. } => Ok(Cow::Borrowed(&[])), Operator::I32Load { .. }