From 1fbbbc963729570c8a6899d22873ff17d218f889 Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Tue, 22 Nov 2022 23:30:11 -0800 Subject: [PATCH] WIP. --- Cargo.toml | 2 +- src/frontend.rs | 70 ++++++++++++++++++----------------------- src/ir.rs | 16 +++++----- src/ir/module.rs | 4 +-- src/op_traits.rs | 6 ++-- src/ops.rs | 35 +++++++++++++-------- src/passes/basic_opt.rs | 4 +-- 7 files changed, 69 insertions(+), 68 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ad65155..75bc908 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ license = "Apache-2.0 WITH LLVM-exception" edition = "2018" [dependencies] -wasmparser = { git = 'https://github.com/cfallin/wasm-tools', rev = '03a81b6a6ed4d5d9730fa71bf65636a3b1538ce7' } +wasmparser = "0.95" anyhow = "1.0" structopt = "0.3" log = "0.4" diff --git a/src/frontend.rs b/src/frontend.rs index d569b14..b12d2d3 100644 --- a/src/frontend.rs +++ b/src/frontend.rs @@ -10,10 +10,7 @@ use anyhow::{bail, Result}; use fxhash::{FxHashMap, FxHashSet}; use log::trace; use std::convert::TryFrom; -use wasmparser::{ - DataKind, ExternalKind, Ieee32, Ieee64, ImportSectionEntryType, Parser, Payload, TypeDef, - TypeOrFuncType, -}; +use wasmparser::{BlockType, DataKind, ExternalKind, Parser, Payload, TypeRef}; pub fn wasm_to_ir(bytes: &[u8]) -> Result> { let mut module = Module::with_orig_bytes(bytes); @@ -27,7 +24,7 @@ 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::ConstExpr<'a>) -> Result> { let operators = init_expr .get_operators_reader() .into_iter() @@ -60,24 +57,23 @@ fn handle_payload<'a>( Payload::TypeSection(reader) => { for ty in reader { let ty = ty?; - if let TypeDef::Func(fty) = ty { - module.frontend_add_signature(fty.into()); - } + let wasmparser::Type::Func(fty) = ty; + module.frontend_add_signature(fty.into()); } } Payload::ImportSection(reader) => { for import in reader { let import = import?; let module_name = import.module.to_owned(); - let name = import.field.unwrap_or("").to_owned(); + let name = import.name.to_owned(); let kind = match import.ty { - ImportSectionEntryType::Function(sig_idx) => { + TypeRef::Func(sig_idx) => { let func = module.frontend_add_func(FuncDecl::Import(Signature::from(sig_idx))); *next_func += 1; Some(ImportKind::Func(func)) } - ImportSectionEntryType::Global(ty) => { + TypeRef::Global(ty) => { let mutable = ty.mutable; let ty = ty.content_type.into(); let global = module.frontend_add_global(GlobalData { @@ -87,7 +83,7 @@ fn handle_payload<'a>( }); Some(ImportKind::Global(global)) } - ImportSectionEntryType::Table(ty) => { + TypeRef::Table(ty) => { let table = module.frontend_add_table(ty.element_type.into(), None); Some(ImportKind::Table(table)) } @@ -140,9 +136,9 @@ fn handle_payload<'a>( Payload::ExportSection(reader) => { for export in reader { let export = export?; - let name = export.field.to_owned(); + let name = export.name.to_owned(); let kind = match export.kind { - ExternalKind::Function => Some(ExportKind::Func(Func::from(export.index))), + ExternalKind::Func => Some(ExportKind::Func(Func::from(export.index))), ExternalKind::Table => Some(ExportKind::Table(Table::from(export.index))), ExternalKind::Global => Some(ExportKind::Global(Global::from(export.index))), ExternalKind::Memory => Some(ExportKind::Memory(Memory::from(export.index))), @@ -170,11 +166,11 @@ fn handle_payload<'a>( DataKind::Passive => {} DataKind::Active { memory_index, - init_expr, + offset_expr, } => { let data = segment.data.to_vec(); let memory = Memory::from(*memory_index); - let offset = parse_init_expr(init_expr)?.unwrap_or(0) as usize; + let offset = parse_init_expr(offset_expr)?.unwrap_or(0) as usize; module .memory_mut(memory) .segments @@ -189,7 +185,7 @@ fn handle_payload<'a>( Payload::ElementSection(reader) => { for element in reader { let element = element?; - if element.ty != wasmparser::Type::FuncRef { + if element.ty != wasmparser::ValType::FuncRef { anyhow::bail!("Unsupported table type: {:?}", element.ty); } match &element.kind { @@ -197,10 +193,10 @@ fn handle_payload<'a>( wasmparser::ElementKind::Declared => {} wasmparser::ElementKind::Active { table_index, - init_expr, + offset_expr, } => { let table = Table::from(*table_index); - let offset = parse_init_expr(&init_expr)?.unwrap_or(0) as usize; + let offset = parse_init_expr(&offset_expr)?.unwrap_or(0) as usize; let items = element .items .get_items_reader()? @@ -224,7 +220,7 @@ fn handle_payload<'a>( } } } - Payload::End => {} + Payload::End(_) => {} payload => { log::warn!("Skipping section: {:?}", payload); } @@ -453,16 +449,12 @@ impl LocalTracker { vec![ty], )), Type::F32 => body.add_value(ValueDef::Operator( - Operator::F32Const { - value: Ieee32::from_bits(0), - }, + Operator::F32Const { value: 0 }, vec![], vec![ty], )), Type::F64 => body.add_value(ValueDef::Operator( - Operator::F64Const { - value: Ieee64::from_bits(0), - }, + Operator::F64Const { value: 0 }, vec![], vec![ty], )), @@ -1021,8 +1013,8 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> { } } - wasmparser::Operator::Block { ty } => { - let (params, results) = self.block_params_and_results(*ty); + wasmparser::Operator::Block { blockty } => { + let (params, results) = self.block_params_and_results(*blockty); let out = self.body.add_block(); self.add_block_params(out, &results[..]); let start_depth = self.op_stack.len() - params.len(); @@ -1034,8 +1026,8 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> { }); } - wasmparser::Operator::Loop { ty } => { - let (params, results) = self.block_params_and_results(*ty); + wasmparser::Operator::Loop { blockty } => { + let (params, results) = self.block_params_and_results(*blockty); let header = self.body.add_block(); self.add_block_params(header, ¶ms[..]); let initial_args = self.pop_n(params.len()); @@ -1055,8 +1047,8 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> { }); } - wasmparser::Operator::If { ty } => { - let (params, results) = self.block_params_and_results(*ty); + wasmparser::Operator::If { blockty } => { + let (params, results) = self.block_params_and_results(*blockty); let if_true = self.body.add_block(); let if_false = self.body.add_block(); let join = self.body.add_block(); @@ -1140,20 +1132,20 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> { } } - wasmparser::Operator::BrTable { table } => { + wasmparser::Operator::BrTable { targets } => { // Get the selector index. let index = self.pop_1(); // Get the signature of the default frame; this tells // us the signature of all frames (since wasmparser // validates the input for us). Pop that many args. - let default_frame = self.relative_frame(table.default()); + let default_frame = self.relative_frame(targets.default()); let default_term_target = default_frame.br_target(); let arg_len = default_frame.br_args().len(); let args = self.pop_n(arg_len); // Generate a branch terminator with the same args for // every branch target. let mut term_targets = vec![]; - for target in table.targets() { + for target in targets.targets() { let target = target?; let frame = self.relative_frame(target); assert_eq!(frame.br_args().len(), args.len()); @@ -1181,11 +1173,11 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> { } } - fn block_params_and_results(&self, ty: TypeOrFuncType) -> (Vec, Vec) { + fn block_params_and_results(&self, ty: BlockType) -> (Vec, Vec) { match ty { - TypeOrFuncType::Type(wasmparser::Type::EmptyBlockType) => (vec![], vec![]), - TypeOrFuncType::Type(ret_ty) => (vec![], vec![ret_ty.into()]), - TypeOrFuncType::FuncType(sig_idx) => { + BlockType::Empty => (vec![], vec![]), + BlockType::Type(ret_ty) => (vec![], vec![ret_ty.into()]), + BlockType::FuncType(sig_idx) => { let sig = &self.module.signature(Signature::from(sig_idx)); ( Vec::from(sig.params.clone()), diff --git a/src/ir.rs b/src/ir.rs index ce29eb2..1bc1d4c 100644 --- a/src/ir.rs +++ b/src/ir.rs @@ -11,15 +11,15 @@ pub enum Type { V128, FuncRef, } -impl From for Type { - fn from(ty: wasmparser::Type) -> Self { +impl From for Type { + fn from(ty: wasmparser::ValType) -> Self { match ty { - wasmparser::Type::I32 => Type::I32, - wasmparser::Type::I64 => Type::I64, - wasmparser::Type::F32 => Type::F32, - wasmparser::Type::F64 => Type::F64, - wasmparser::Type::V128 => Type::V128, - wasmparser::Type::FuncRef => Type::FuncRef, + wasmparser::ValType::I32 => Type::I32, + wasmparser::ValType::I64 => Type::I64, + wasmparser::ValType::F32 => Type::F32, + wasmparser::ValType::F64 => Type::F64, + wasmparser::ValType::V128 => Type::V128, + wasmparser::ValType::FuncRef => Type::FuncRef, _ => panic!("Unsupported type: {:?}", ty), } } diff --git a/src/ir/module.rs b/src/ir/module.rs index 886faf7..f83fe08 100644 --- a/src/ir/module.rs +++ b/src/ir/module.rs @@ -53,12 +53,12 @@ impl From<&wasmparser::FuncType> for SignatureData { fn from(fty: &wasmparser::FuncType) -> Self { Self { params: fty - .params + .params() .iter() .map(|&ty| ty.into()) .collect::>(), returns: fty - .returns + .results() .iter() .map(|&ty| ty.into()) .collect::>(), diff --git a/src/op_traits.rs b/src/op_traits.rs index adfca67..4e51e91 100644 --- a/src/op_traits.rs +++ b/src/op_traits.rs @@ -1,7 +1,7 @@ //! Metadata on operators. use crate::entity::EntityVec; -use crate::ir::{Global, Local, Module, Signature, Table, Type, Value}; +use crate::ir::{Local, Module, Signature, Type, Value}; use crate::Operator; use anyhow::Result; use std::borrow::Cow; @@ -711,8 +711,8 @@ impl std::fmt::Display for Operator { Operator::I32Const { value } => write!(f, "i32const<{}>", value)?, Operator::I64Const { value } => write!(f, "i64const<{}>", value)?, - Operator::F32Const { value } => write!(f, "f32const<{}>", value.bits())?, - Operator::F64Const { value } => write!(f, "f64const<{}>", value.bits())?, + Operator::F32Const { value } => write!(f, "f32const<{}>", value)?, + Operator::F64Const { value } => write!(f, "f64const<{}>", value)?, Operator::I32Eqz => write!(f, "i32eqz")?, Operator::I32Eq => write!(f, "i32eq")?, diff --git a/src/ops.rs b/src/ops.rs index 1da5250..9dc3eef 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -2,7 +2,6 @@ use crate::{Func, Global, Local, Memory, Signature, Table, Type}; use std::convert::TryFrom; -use wasmparser::MemoryImmediate; pub use wasmparser::{Ieee32, Ieee64}; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] @@ -127,16 +126,16 @@ pub enum Operator { }, I32Const { - value: i32, + value: u32, }, I64Const { - value: i64, + value: u64, }, F32Const { - value: Ieee32, + value: u32, }, F64Const { - value: Ieee64, + value: u64, }, I32Eqz, @@ -319,9 +318,11 @@ impl<'a, 'b> std::convert::TryFrom<&'b wasmparser::Operator<'a>> for Operator { function_index: Func::from(function_index), }), &wasmparser::Operator::CallIndirect { - index, table_index, .. + type_index, + table_index, + .. } => Ok(Operator::CallIndirect { - sig_index: Signature::from(index), + sig_index: Signature::from(type_index), table_index: Table::from(table_index), }), &wasmparser::Operator::Return => Ok(Operator::Return), @@ -413,10 +414,18 @@ impl<'a, 'b> std::convert::TryFrom<&'b wasmparser::Operator<'a>> for Operator { &wasmparser::Operator::I64Store32 { memarg } => Ok(Operator::I64Store32 { memory: memarg.into(), }), - &wasmparser::Operator::I32Const { value } => Ok(Operator::I32Const { value }), - &wasmparser::Operator::I64Const { value } => Ok(Operator::I64Const { value }), - &wasmparser::Operator::F32Const { value } => Ok(Operator::F32Const { value }), - &wasmparser::Operator::F64Const { value } => Ok(Operator::F64Const { value }), + &wasmparser::Operator::I32Const { value } => Ok(Operator::I32Const { + value: value as u32, + }), + &wasmparser::Operator::I64Const { value } => Ok(Operator::I64Const { + value: value as u64, + }), + &wasmparser::Operator::F32Const { value } => Ok(Operator::F32Const { + value: value.bits(), + }), + &wasmparser::Operator::F64Const { value } => Ok(Operator::F64Const { + value: value.bits(), + }), &wasmparser::Operator::I32Eqz => Ok(Operator::I32Eqz), &wasmparser::Operator::I32Eq => Ok(Operator::I32Eq), &wasmparser::Operator::I32Ne => Ok(Operator::I32Ne), @@ -576,8 +585,8 @@ impl<'a, 'b> std::convert::TryFrom<&'b wasmparser::Operator<'a>> for Operator { } } -impl std::convert::From for MemoryArg { - fn from(value: MemoryImmediate) -> MemoryArg { +impl std::convert::From for MemoryArg { + fn from(value: wasmparser::MemArg) -> MemoryArg { MemoryArg { align: value.align as u32, offset: u32::try_from(value.offset).expect("offset too large"), diff --git a/src/passes/basic_opt.rs b/src/passes/basic_opt.rs index fe9ada3..e0074df 100644 --- a/src/passes/basic_opt.rs +++ b/src/passes/basic_opt.rs @@ -204,7 +204,7 @@ impl GVNPass { match const_val { Some(ConstVal::I32(val)) => { value = ValueDef::Operator( - Operator::I32Const { value: val as i32 }, + Operator::I32Const { value: val }, vec![], vec![Type::I32], ); @@ -212,7 +212,7 @@ impl GVNPass { } Some(ConstVal::I64(val)) => { value = ValueDef::Operator( - Operator::I64Const { value: val as i64 }, + Operator::I64Const { value: val }, vec![], vec![Type::I64], );