WIP.
This commit is contained in:
parent
abc46f1d14
commit
1fbbbc9637
|
@ -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"
|
||||
|
|
|
@ -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<Module<'_>> {
|
||||
let mut module = Module::with_orig_bytes(bytes);
|
||||
|
@ -27,7 +24,7 @@ pub fn wasm_to_ir(bytes: &[u8]) -> Result<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
|
||||
.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<Type>, Vec<Type>) {
|
||||
fn block_params_and_results(&self, ty: BlockType) -> (Vec<Type>, Vec<Type>) {
|
||||
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()),
|
||||
|
|
16
src/ir.rs
16
src/ir.rs
|
@ -11,15 +11,15 @@ pub enum Type {
|
|||
V128,
|
||||
FuncRef,
|
||||
}
|
||||
impl From<wasmparser::Type> for Type {
|
||||
fn from(ty: wasmparser::Type) -> Self {
|
||||
impl From<wasmparser::ValType> 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),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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::<Vec<Type>>(),
|
||||
returns: fty
|
||||
.returns
|
||||
.results()
|
||||
.iter()
|
||||
.map(|&ty| ty.into())
|
||||
.collect::<Vec<Type>>(),
|
||||
|
|
|
@ -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")?,
|
||||
|
|
35
src/ops.rs
35
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<MemoryImmediate> for MemoryArg {
|
||||
fn from(value: MemoryImmediate) -> MemoryArg {
|
||||
impl std::convert::From<wasmparser::MemArg> for MemoryArg {
|
||||
fn from(value: wasmparser::MemArg) -> MemoryArg {
|
||||
MemoryArg {
|
||||
align: value.align as u32,
|
||||
offset: u32::try_from(value.offset).expect("offset too large"),
|
||||
|
|
|
@ -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],
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue