This commit is contained in:
Chris Fallin 2022-11-22 23:30:11 -08:00
parent abc46f1d14
commit 1fbbbc9637
7 changed files with 69 additions and 68 deletions

View file

@ -7,7 +7,7 @@ license = "Apache-2.0 WITH LLVM-exception"
edition = "2018" edition = "2018"
[dependencies] [dependencies]
wasmparser = { git = 'https://github.com/cfallin/wasm-tools', rev = '03a81b6a6ed4d5d9730fa71bf65636a3b1538ce7' } wasmparser = "0.95"
anyhow = "1.0" anyhow = "1.0"
structopt = "0.3" structopt = "0.3"
log = "0.4" log = "0.4"

View file

@ -10,10 +10,7 @@ use anyhow::{bail, Result};
use fxhash::{FxHashMap, FxHashSet}; use fxhash::{FxHashMap, FxHashSet};
use log::trace; use log::trace;
use std::convert::TryFrom; use std::convert::TryFrom;
use wasmparser::{ use wasmparser::{BlockType, DataKind, ExternalKind, Parser, Payload, TypeRef};
DataKind, ExternalKind, Ieee32, Ieee64, ImportSectionEntryType, Parser, Payload, TypeDef,
TypeOrFuncType,
};
pub fn wasm_to_ir(bytes: &[u8]) -> Result<Module<'_>> { pub fn wasm_to_ir(bytes: &[u8]) -> Result<Module<'_>> {
let mut module = Module::with_orig_bytes(bytes); let mut module = Module::with_orig_bytes(bytes);
@ -27,7 +24,7 @@ pub fn wasm_to_ir(bytes: &[u8]) -> Result<Module<'_>> {
Ok(module) Ok(module)
} }
fn parse_init_expr<'a>(init_expr: &wasmparser::InitExpr<'a>) -> Result<Option<u64>> { fn parse_init_expr<'a>(init_expr: &wasmparser::ConstExpr<'a>) -> Result<Option<u64>> {
let operators = init_expr let operators = init_expr
.get_operators_reader() .get_operators_reader()
.into_iter() .into_iter()
@ -60,24 +57,23 @@ fn handle_payload<'a>(
Payload::TypeSection(reader) => { Payload::TypeSection(reader) => {
for ty in reader { for ty in reader {
let ty = ty?; let ty = ty?;
if let TypeDef::Func(fty) = ty { let wasmparser::Type::Func(fty) = ty;
module.frontend_add_signature(fty.into()); module.frontend_add_signature(fty.into());
}
} }
} }
Payload::ImportSection(reader) => { Payload::ImportSection(reader) => {
for import in reader { for import in reader {
let import = import?; let import = import?;
let module_name = import.module.to_owned(); 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 { let kind = match import.ty {
ImportSectionEntryType::Function(sig_idx) => { TypeRef::Func(sig_idx) => {
let func = let func =
module.frontend_add_func(FuncDecl::Import(Signature::from(sig_idx))); module.frontend_add_func(FuncDecl::Import(Signature::from(sig_idx)));
*next_func += 1; *next_func += 1;
Some(ImportKind::Func(func)) Some(ImportKind::Func(func))
} }
ImportSectionEntryType::Global(ty) => { TypeRef::Global(ty) => {
let mutable = ty.mutable; let mutable = ty.mutable;
let ty = ty.content_type.into(); let ty = ty.content_type.into();
let global = module.frontend_add_global(GlobalData { let global = module.frontend_add_global(GlobalData {
@ -87,7 +83,7 @@ fn handle_payload<'a>(
}); });
Some(ImportKind::Global(global)) Some(ImportKind::Global(global))
} }
ImportSectionEntryType::Table(ty) => { TypeRef::Table(ty) => {
let table = module.frontend_add_table(ty.element_type.into(), None); let table = module.frontend_add_table(ty.element_type.into(), None);
Some(ImportKind::Table(table)) Some(ImportKind::Table(table))
} }
@ -140,9 +136,9 @@ fn handle_payload<'a>(
Payload::ExportSection(reader) => { Payload::ExportSection(reader) => {
for export in reader { for export in reader {
let export = export?; let export = export?;
let name = export.field.to_owned(); let name = export.name.to_owned();
let kind = match export.kind { 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::Table => Some(ExportKind::Table(Table::from(export.index))),
ExternalKind::Global => Some(ExportKind::Global(Global::from(export.index))), ExternalKind::Global => Some(ExportKind::Global(Global::from(export.index))),
ExternalKind::Memory => Some(ExportKind::Memory(Memory::from(export.index))), ExternalKind::Memory => Some(ExportKind::Memory(Memory::from(export.index))),
@ -170,11 +166,11 @@ fn handle_payload<'a>(
DataKind::Passive => {} DataKind::Passive => {}
DataKind::Active { DataKind::Active {
memory_index, memory_index,
init_expr, offset_expr,
} => { } => {
let data = segment.data.to_vec(); let data = segment.data.to_vec();
let memory = Memory::from(*memory_index); 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 module
.memory_mut(memory) .memory_mut(memory)
.segments .segments
@ -189,7 +185,7 @@ fn handle_payload<'a>(
Payload::ElementSection(reader) => { Payload::ElementSection(reader) => {
for element in reader { for element in reader {
let element = element?; let element = element?;
if element.ty != wasmparser::Type::FuncRef { if element.ty != wasmparser::ValType::FuncRef {
anyhow::bail!("Unsupported table type: {:?}", element.ty); anyhow::bail!("Unsupported table type: {:?}", element.ty);
} }
match &element.kind { match &element.kind {
@ -197,10 +193,10 @@ fn handle_payload<'a>(
wasmparser::ElementKind::Declared => {} wasmparser::ElementKind::Declared => {}
wasmparser::ElementKind::Active { wasmparser::ElementKind::Active {
table_index, table_index,
init_expr, offset_expr,
} => { } => {
let table = Table::from(*table_index); 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 let items = element
.items .items
.get_items_reader()? .get_items_reader()?
@ -224,7 +220,7 @@ fn handle_payload<'a>(
} }
} }
} }
Payload::End => {} Payload::End(_) => {}
payload => { payload => {
log::warn!("Skipping section: {:?}", payload); log::warn!("Skipping section: {:?}", payload);
} }
@ -453,16 +449,12 @@ impl LocalTracker {
vec![ty], vec![ty],
)), )),
Type::F32 => body.add_value(ValueDef::Operator( Type::F32 => body.add_value(ValueDef::Operator(
Operator::F32Const { Operator::F32Const { value: 0 },
value: Ieee32::from_bits(0),
},
vec![], vec![],
vec![ty], vec![ty],
)), )),
Type::F64 => body.add_value(ValueDef::Operator( Type::F64 => body.add_value(ValueDef::Operator(
Operator::F64Const { Operator::F64Const { value: 0 },
value: Ieee64::from_bits(0),
},
vec![], vec![],
vec![ty], vec![ty],
)), )),
@ -1021,8 +1013,8 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
} }
} }
wasmparser::Operator::Block { ty } => { wasmparser::Operator::Block { blockty } => {
let (params, results) = self.block_params_and_results(*ty); let (params, results) = self.block_params_and_results(*blockty);
let out = self.body.add_block(); let out = self.body.add_block();
self.add_block_params(out, &results[..]); self.add_block_params(out, &results[..]);
let start_depth = self.op_stack.len() - params.len(); let start_depth = self.op_stack.len() - params.len();
@ -1034,8 +1026,8 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
}); });
} }
wasmparser::Operator::Loop { ty } => { wasmparser::Operator::Loop { blockty } => {
let (params, results) = self.block_params_and_results(*ty); let (params, results) = self.block_params_and_results(*blockty);
let header = self.body.add_block(); let header = self.body.add_block();
self.add_block_params(header, &params[..]); self.add_block_params(header, &params[..]);
let initial_args = self.pop_n(params.len()); let initial_args = self.pop_n(params.len());
@ -1055,8 +1047,8 @@ impl<'a, 'b> FunctionBodyBuilder<'a, 'b> {
}); });
} }
wasmparser::Operator::If { ty } => { wasmparser::Operator::If { blockty } => {
let (params, results) = self.block_params_and_results(*ty); let (params, results) = self.block_params_and_results(*blockty);
let if_true = self.body.add_block(); let if_true = self.body.add_block();
let if_false = self.body.add_block(); let if_false = self.body.add_block();
let join = 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. // Get the selector index.
let index = self.pop_1(); let index = self.pop_1();
// Get the signature of the default frame; this tells // Get the signature of the default frame; this tells
// us the signature of all frames (since wasmparser // us the signature of all frames (since wasmparser
// validates the input for us). Pop that many args. // 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 default_term_target = default_frame.br_target();
let arg_len = default_frame.br_args().len(); let arg_len = default_frame.br_args().len();
let args = self.pop_n(arg_len); let args = self.pop_n(arg_len);
// Generate a branch terminator with the same args for // Generate a branch terminator with the same args for
// every branch target. // every branch target.
let mut term_targets = vec![]; let mut term_targets = vec![];
for target in table.targets() { for target in targets.targets() {
let target = target?; let target = target?;
let frame = self.relative_frame(target); let frame = self.relative_frame(target);
assert_eq!(frame.br_args().len(), args.len()); 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<Type>, Vec<Type>) { fn block_params_and_results(&self, ty: BlockType) -> (Vec<Type>, Vec<Type>) {
match ty { match ty {
TypeOrFuncType::Type(wasmparser::Type::EmptyBlockType) => (vec![], vec![]), BlockType::Empty => (vec![], vec![]),
TypeOrFuncType::Type(ret_ty) => (vec![], vec![ret_ty.into()]), BlockType::Type(ret_ty) => (vec![], vec![ret_ty.into()]),
TypeOrFuncType::FuncType(sig_idx) => { BlockType::FuncType(sig_idx) => {
let sig = &self.module.signature(Signature::from(sig_idx)); let sig = &self.module.signature(Signature::from(sig_idx));
( (
Vec::from(sig.params.clone()), Vec::from(sig.params.clone()),

View file

@ -11,15 +11,15 @@ pub enum Type {
V128, V128,
FuncRef, FuncRef,
} }
impl From<wasmparser::Type> for Type { impl From<wasmparser::ValType> for Type {
fn from(ty: wasmparser::Type) -> Self { fn from(ty: wasmparser::ValType) -> Self {
match ty { match ty {
wasmparser::Type::I32 => Type::I32, wasmparser::ValType::I32 => Type::I32,
wasmparser::Type::I64 => Type::I64, wasmparser::ValType::I64 => Type::I64,
wasmparser::Type::F32 => Type::F32, wasmparser::ValType::F32 => Type::F32,
wasmparser::Type::F64 => Type::F64, wasmparser::ValType::F64 => Type::F64,
wasmparser::Type::V128 => Type::V128, wasmparser::ValType::V128 => Type::V128,
wasmparser::Type::FuncRef => Type::FuncRef, wasmparser::ValType::FuncRef => Type::FuncRef,
_ => panic!("Unsupported type: {:?}", ty), _ => panic!("Unsupported type: {:?}", ty),
} }
} }

View file

@ -53,12 +53,12 @@ impl From<&wasmparser::FuncType> for SignatureData {
fn from(fty: &wasmparser::FuncType) -> Self { fn from(fty: &wasmparser::FuncType) -> Self {
Self { Self {
params: fty params: fty
.params .params()
.iter() .iter()
.map(|&ty| ty.into()) .map(|&ty| ty.into())
.collect::<Vec<Type>>(), .collect::<Vec<Type>>(),
returns: fty returns: fty
.returns .results()
.iter() .iter()
.map(|&ty| ty.into()) .map(|&ty| ty.into())
.collect::<Vec<Type>>(), .collect::<Vec<Type>>(),

View file

@ -1,7 +1,7 @@
//! Metadata on operators. //! Metadata on operators.
use crate::entity::EntityVec; 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 crate::Operator;
use anyhow::Result; use anyhow::Result;
use std::borrow::Cow; use std::borrow::Cow;
@ -711,8 +711,8 @@ impl std::fmt::Display for Operator {
Operator::I32Const { value } => write!(f, "i32const<{}>", value)?, Operator::I32Const { value } => write!(f, "i32const<{}>", value)?,
Operator::I64Const { value } => write!(f, "i64const<{}>", value)?, Operator::I64Const { value } => write!(f, "i64const<{}>", value)?,
Operator::F32Const { value } => write!(f, "f32const<{}>", value.bits())?, Operator::F32Const { value } => write!(f, "f32const<{}>", value)?,
Operator::F64Const { value } => write!(f, "f64const<{}>", value.bits())?, Operator::F64Const { value } => write!(f, "f64const<{}>", value)?,
Operator::I32Eqz => write!(f, "i32eqz")?, Operator::I32Eqz => write!(f, "i32eqz")?,
Operator::I32Eq => write!(f, "i32eq")?, Operator::I32Eq => write!(f, "i32eq")?,

View file

@ -2,7 +2,6 @@
use crate::{Func, Global, Local, Memory, Signature, Table, Type}; use crate::{Func, Global, Local, Memory, Signature, Table, Type};
use std::convert::TryFrom; use std::convert::TryFrom;
use wasmparser::MemoryImmediate;
pub use wasmparser::{Ieee32, Ieee64}; pub use wasmparser::{Ieee32, Ieee64};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
@ -127,16 +126,16 @@ pub enum Operator {
}, },
I32Const { I32Const {
value: i32, value: u32,
}, },
I64Const { I64Const {
value: i64, value: u64,
}, },
F32Const { F32Const {
value: Ieee32, value: u32,
}, },
F64Const { F64Const {
value: Ieee64, value: u64,
}, },
I32Eqz, I32Eqz,
@ -319,9 +318,11 @@ impl<'a, 'b> std::convert::TryFrom<&'b wasmparser::Operator<'a>> for Operator {
function_index: Func::from(function_index), function_index: Func::from(function_index),
}), }),
&wasmparser::Operator::CallIndirect { &wasmparser::Operator::CallIndirect {
index, table_index, .. type_index,
table_index,
..
} => Ok(Operator::CallIndirect { } => Ok(Operator::CallIndirect {
sig_index: Signature::from(index), sig_index: Signature::from(type_index),
table_index: Table::from(table_index), table_index: Table::from(table_index),
}), }),
&wasmparser::Operator::Return => Ok(Operator::Return), &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 { &wasmparser::Operator::I64Store32 { memarg } => Ok(Operator::I64Store32 {
memory: memarg.into(), memory: memarg.into(),
}), }),
&wasmparser::Operator::I32Const { value } => Ok(Operator::I32Const { value }), &wasmparser::Operator::I32Const { value } => Ok(Operator::I32Const {
&wasmparser::Operator::I64Const { value } => Ok(Operator::I64Const { value }), value: value as u32,
&wasmparser::Operator::F32Const { value } => Ok(Operator::F32Const { value }), }),
&wasmparser::Operator::F64Const { value } => Ok(Operator::F64Const { value }), &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::I32Eqz => Ok(Operator::I32Eqz),
&wasmparser::Operator::I32Eq => Ok(Operator::I32Eq), &wasmparser::Operator::I32Eq => Ok(Operator::I32Eq),
&wasmparser::Operator::I32Ne => Ok(Operator::I32Ne), &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<MemoryImmediate> for MemoryArg { impl std::convert::From<wasmparser::MemArg> for MemoryArg {
fn from(value: MemoryImmediate) -> MemoryArg { fn from(value: wasmparser::MemArg) -> MemoryArg {
MemoryArg { MemoryArg {
align: value.align as u32, align: value.align as u32,
offset: u32::try_from(value.offset).expect("offset too large"), offset: u32::try_from(value.offset).expect("offset too large"),

View file

@ -204,7 +204,7 @@ impl GVNPass {
match const_val { match const_val {
Some(ConstVal::I32(val)) => { Some(ConstVal::I32(val)) => {
value = ValueDef::Operator( value = ValueDef::Operator(
Operator::I32Const { value: val as i32 }, Operator::I32Const { value: val },
vec![], vec![],
vec![Type::I32], vec![Type::I32],
); );
@ -212,7 +212,7 @@ impl GVNPass {
} }
Some(ConstVal::I64(val)) => { Some(ConstVal::I64(val)) => {
value = ValueDef::Operator( value = ValueDef::Operator(
Operator::I64Const { value: val as i64 }, Operator::I64Const { value: val },
vec![], vec![],
vec![Type::I64], vec![Type::I64],
); );