WIP.
This commit is contained in:
parent
a73dacd5df
commit
86454940af
120
src/frontend.rs
120
src/frontend.rs
|
@ -11,7 +11,8 @@ use fxhash::{FxHashMap, FxHashSet};
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use wasmparser::{
|
use wasmparser::{
|
||||||
Ieee32, Ieee64, ImportSectionEntryType, Parser, Payload, TypeDef, TypeOrFuncType,
|
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<'_>> {
|
||||||
|
@ -33,46 +34,60 @@ fn handle_payload<'a>(
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
trace!("Wasm parser item: {:?}", payload);
|
trace!("Wasm parser item: {:?}", payload);
|
||||||
match payload {
|
match payload {
|
||||||
Payload::TypeSection(mut reader) => {
|
Payload::TypeSection(reader) => {
|
||||||
for _ in 0..reader.get_count() {
|
for ty in reader {
|
||||||
let ty = reader.read()?;
|
let ty = ty?;
|
||||||
if let TypeDef::Func(fty) = ty {
|
if let TypeDef::Func(fty) = ty {
|
||||||
module.frontend_add_signature(fty.into());
|
module.frontend_add_signature(fty.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Payload::ImportSection(mut reader) => {
|
Payload::ImportSection(reader) => {
|
||||||
for _ in 0..reader.get_count() {
|
for import in reader {
|
||||||
match reader.read()?.ty {
|
let import = import?;
|
||||||
|
let module_name = import.module.to_owned();
|
||||||
|
let name = import.field.unwrap_or("").to_owned();
|
||||||
|
let kind = match import.ty {
|
||||||
ImportSectionEntryType::Function(sig_idx) => {
|
ImportSectionEntryType::Function(sig_idx) => {
|
||||||
module.frontend_add_func(FuncDecl::Import(Signature::from(sig_idx)));
|
let func =
|
||||||
|
module.frontend_add_func(FuncDecl::Import(Signature::from(sig_idx)));
|
||||||
*next_func += 1;
|
*next_func += 1;
|
||||||
|
Some(ImportKind::Func(func))
|
||||||
}
|
}
|
||||||
ImportSectionEntryType::Global(ty) => {
|
ImportSectionEntryType::Global(ty) => {
|
||||||
module.frontend_add_global(ty.content_type.into());
|
let global = module.frontend_add_global(ty.content_type.into());
|
||||||
|
Some(ImportKind::Global(global))
|
||||||
}
|
}
|
||||||
ImportSectionEntryType::Table(ty) => {
|
ImportSectionEntryType::Table(ty) => {
|
||||||
module.frontend_add_table(ty.element_type.into());
|
let table = module.frontend_add_table(ty.element_type.into());
|
||||||
|
Some(ImportKind::Table(table))
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => None,
|
||||||
|
};
|
||||||
|
if let Some(kind) = kind {
|
||||||
|
module.frontend_add_import(Import {
|
||||||
|
module: module_name,
|
||||||
|
name,
|
||||||
|
kind,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Payload::GlobalSection(mut reader) => {
|
Payload::GlobalSection(reader) => {
|
||||||
for _ in 0..reader.get_count() {
|
for global in reader {
|
||||||
let global = reader.read()?;
|
let global = global?;
|
||||||
module.frontend_add_global(global.ty.content_type.into());
|
module.frontend_add_global(global.ty.content_type.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Payload::TableSection(mut reader) => {
|
Payload::TableSection(reader) => {
|
||||||
for _ in 0..reader.get_count() {
|
for table in reader {
|
||||||
let table = reader.read()?;
|
let table = table?;
|
||||||
module.frontend_add_table(table.element_type.into());
|
module.frontend_add_table(table.element_type.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Payload::FunctionSection(mut reader) => {
|
Payload::FunctionSection(reader) => {
|
||||||
for _ in 0..reader.get_count() {
|
for sig_idx in reader {
|
||||||
let sig_idx = Signature::from(reader.read()?);
|
let sig_idx = Signature::from(sig_idx?);
|
||||||
module.frontend_add_func(FuncDecl::Body(sig_idx, FunctionBody::default()));
|
module.frontend_add_func(FuncDecl::Body(sig_idx, FunctionBody::default()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,6 +101,71 @@ fn handle_payload<'a>(
|
||||||
let existing_body = module.func_mut(func_idx).body_mut().unwrap();
|
let existing_body = module.func_mut(func_idx).body_mut().unwrap();
|
||||||
*existing_body = body;
|
*existing_body = body;
|
||||||
}
|
}
|
||||||
|
Payload::ExportSection(reader) => {
|
||||||
|
for export in reader {
|
||||||
|
let export = export?;
|
||||||
|
let name = export.field.to_owned();
|
||||||
|
let kind = match export.kind {
|
||||||
|
ExternalKind::Function => 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))),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
if let Some(kind) = kind {
|
||||||
|
module.frontend_add_export(Export { name, kind });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Payload::MemorySection(reader) => {
|
||||||
|
for memory in reader {
|
||||||
|
let memory = memory?;
|
||||||
|
module.frontend_add_memory(MemoryData {
|
||||||
|
initial_pages: memory.initial as usize,
|
||||||
|
maximum_pages: memory.maximum.map(|max| max as usize),
|
||||||
|
segments: vec![],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Payload::DataSection(reader) => {
|
||||||
|
for segment in reader {
|
||||||
|
let segment = segment?;
|
||||||
|
match &segment.kind {
|
||||||
|
DataKind::Passive => {}
|
||||||
|
DataKind::Active {
|
||||||
|
memory_index,
|
||||||
|
init_expr,
|
||||||
|
} => {
|
||||||
|
let data = segment.data.to_vec();
|
||||||
|
let memory = Memory::from(*memory_index);
|
||||||
|
let operators = init_expr
|
||||||
|
.get_operators_reader()
|
||||||
|
.into_iter()
|
||||||
|
.collect::<Result<Vec<wasmparser::Operator>, _>>()?;
|
||||||
|
if operators.len() != 2
|
||||||
|
|| !matches!(&operators[1], &wasmparser::Operator::End)
|
||||||
|
{
|
||||||
|
anyhow::bail!(
|
||||||
|
"Unsupported operator seq in base-address expr: {:?}",
|
||||||
|
operators
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let offset = match &operators[0] {
|
||||||
|
&wasmparser::Operator::I32Const { value } => value as usize,
|
||||||
|
&wasmparser::Operator::I64Const { value } => value as usize,
|
||||||
|
op => anyhow::bail!(
|
||||||
|
"Unsupported data segment base-address operator: {:?}",
|
||||||
|
op
|
||||||
|
),
|
||||||
|
};
|
||||||
|
module
|
||||||
|
.frontend_memory_mut(memory)
|
||||||
|
.segments
|
||||||
|
.push(MemorySegment { offset, data });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -158,6 +158,36 @@ impl<'a> Display for ModuleDisplay<'a> {
|
||||||
for (table, table_ty) in self.0.tables() {
|
for (table, table_ty) in self.0.tables() {
|
||||||
writeln!(f, " {}: {}", table, table_ty)?;
|
writeln!(f, " {}: {}", table, table_ty)?;
|
||||||
}
|
}
|
||||||
|
for (memory, memory_data) in self.0.memories() {
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
" {}: initial {} max {:?}",
|
||||||
|
memory, memory_data.initial_pages, memory_data.maximum_pages
|
||||||
|
)?;
|
||||||
|
for seg in &memory_data.segments {
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
" {} offset {}: [{}]",
|
||||||
|
memory,
|
||||||
|
seg.offset,
|
||||||
|
seg.data
|
||||||
|
.iter()
|
||||||
|
.map(|&byte| format!("0x{:02x}", byte))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for import in self.0.imports() {
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
" import \"{}\".\"{}\": {}",
|
||||||
|
import.module, import.name, import.kind
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
for export in self.0.exports() {
|
||||||
|
writeln!(f, " export \"{}\": {}", export.name, export.kind)?;
|
||||||
|
}
|
||||||
for (func, func_decl) in self.0.funcs() {
|
for (func, func_decl) in self.0.funcs() {
|
||||||
match func_decl {
|
match func_decl {
|
||||||
FuncDecl::Body(sig, body) => {
|
FuncDecl::Body(sig, body) => {
|
||||||
|
|
118
src/ir/module.rs
118
src/ir/module.rs
|
@ -1,16 +1,19 @@
|
||||||
use super::{Func, FuncDecl, Global, ModuleDisplay, Signature, Table, Type};
|
use super::{Func, FuncDecl, Global, Memory, ModuleDisplay, Signature, Table, Type};
|
||||||
use crate::entity::EntityVec;
|
use crate::entity::EntityVec;
|
||||||
use crate::frontend;
|
use crate::frontend;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use fxhash::FxHashSet;
|
use fxhash::FxHashSet;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Module<'a> {
|
pub struct Module<'a> {
|
||||||
orig_bytes: &'a [u8],
|
orig_bytes: &'a [u8],
|
||||||
funcs: EntityVec<Func, FuncDecl>,
|
funcs: EntityVec<Func, FuncDecl>,
|
||||||
signatures: EntityVec<Signature, SignatureData>,
|
signatures: EntityVec<Signature, SignatureData>,
|
||||||
globals: EntityVec<Global, Type>,
|
globals: EntityVec<Global, Type>,
|
||||||
tables: EntityVec<Table, Type>,
|
tables: EntityVec<Table, Type>,
|
||||||
|
imports: Vec<Import>,
|
||||||
|
exports: Vec<Export>,
|
||||||
|
memories: EntityVec<Memory, MemoryData>,
|
||||||
|
|
||||||
dirty_funcs: FxHashSet<Func>,
|
dirty_funcs: FxHashSet<Func>,
|
||||||
}
|
}
|
||||||
|
@ -21,6 +24,19 @@ pub struct SignatureData {
|
||||||
pub returns: Vec<Type>,
|
pub returns: Vec<Type>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct MemoryData {
|
||||||
|
pub initial_pages: usize,
|
||||||
|
pub maximum_pages: Option<usize>,
|
||||||
|
pub segments: Vec<MemorySegment>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct MemorySegment {
|
||||||
|
pub offset: usize,
|
||||||
|
pub data: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
impl From<&wasmparser::FuncType> for SignatureData {
|
impl From<&wasmparser::FuncType> for SignatureData {
|
||||||
fn from(fty: &wasmparser::FuncType) -> Self {
|
fn from(fty: &wasmparser::FuncType) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -43,11 +59,70 @@ impl From<wasmparser::FuncType> for SignatureData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Import {
|
||||||
|
pub module: String,
|
||||||
|
pub name: String,
|
||||||
|
pub kind: ImportKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum ImportKind {
|
||||||
|
Table(Table),
|
||||||
|
Func(Func),
|
||||||
|
Global(Global),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for ImportKind {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
ImportKind::Table(table) => write!(f, "{}", table)?,
|
||||||
|
ImportKind::Func(func) => write!(f, "{}", func)?,
|
||||||
|
ImportKind::Global(global) => write!(f, "{}", global)?,
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Export {
|
||||||
|
pub name: String,
|
||||||
|
pub kind: ExportKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum ExportKind {
|
||||||
|
Table(Table),
|
||||||
|
Func(Func),
|
||||||
|
Global(Global),
|
||||||
|
Memory(Memory),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for ExportKind {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
ExportKind::Table(table) => write!(f, "{}", table)?,
|
||||||
|
ExportKind::Func(func) => write!(f, "{}", func)?,
|
||||||
|
ExportKind::Global(global) => write!(f, "{}", global)?,
|
||||||
|
ExportKind::Memory(memory) => write!(f, "{}", memory)?,
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Module<'a> {
|
impl<'a> Module<'a> {
|
||||||
pub(crate) fn with_orig_bytes(orig_bytes: &'a [u8]) -> Module<'a> {
|
pub(crate) fn with_orig_bytes(orig_bytes: &'a [u8]) -> Module<'a> {
|
||||||
let mut m = Module::default();
|
Module {
|
||||||
m.orig_bytes = orig_bytes;
|
orig_bytes,
|
||||||
m
|
funcs: EntityVec::default(),
|
||||||
|
signatures: EntityVec::default(),
|
||||||
|
globals: EntityVec::default(),
|
||||||
|
tables: EntityVec::default(),
|
||||||
|
imports: vec![],
|
||||||
|
exports: vec![],
|
||||||
|
memories: EntityVec::default(),
|
||||||
|
dirty_funcs: FxHashSet::default(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,18 +155,39 @@ impl<'a> Module<'a> {
|
||||||
pub fn tables<'b>(&'b self) -> impl Iterator<Item = (Table, Type)> + 'b {
|
pub fn tables<'b>(&'b self) -> impl Iterator<Item = (Table, Type)> + 'b {
|
||||||
self.tables.entries().map(|(id, ty)| (id, *ty))
|
self.tables.entries().map(|(id, ty)| (id, *ty))
|
||||||
}
|
}
|
||||||
|
pub fn memories<'b>(&'b self) -> impl Iterator<Item = (Memory, &'b MemoryData)> + 'b {
|
||||||
|
self.memories.entries()
|
||||||
|
}
|
||||||
|
pub fn imports<'b>(&'b self) -> impl Iterator<Item = &'b Import> + 'b {
|
||||||
|
self.imports.iter()
|
||||||
|
}
|
||||||
|
pub fn exports<'b>(&'b self) -> impl Iterator<Item = &'b Export> + 'b {
|
||||||
|
self.exports.iter()
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn frontend_add_signature(&mut self, ty: SignatureData) {
|
pub(crate) fn frontend_add_signature(&mut self, ty: SignatureData) {
|
||||||
self.signatures.push(ty);
|
self.signatures.push(ty);
|
||||||
}
|
}
|
||||||
pub(crate) fn frontend_add_func(&mut self, body: FuncDecl) {
|
pub(crate) fn frontend_add_func(&mut self, body: FuncDecl) -> Func {
|
||||||
self.funcs.push(body);
|
self.funcs.push(body)
|
||||||
}
|
}
|
||||||
pub(crate) fn frontend_add_table(&mut self, ty: Type) {
|
pub(crate) fn frontend_add_table(&mut self, ty: Type) -> Table {
|
||||||
self.tables.push(ty);
|
self.tables.push(ty)
|
||||||
}
|
}
|
||||||
pub(crate) fn frontend_add_global(&mut self, ty: Type) {
|
pub(crate) fn frontend_add_global(&mut self, ty: Type) -> Global {
|
||||||
self.globals.push(ty);
|
self.globals.push(ty)
|
||||||
|
}
|
||||||
|
pub(crate) fn frontend_add_import(&mut self, import: Import) {
|
||||||
|
self.imports.push(import);
|
||||||
|
}
|
||||||
|
pub(crate) fn frontend_add_export(&mut self, export: Export) {
|
||||||
|
self.exports.push(export);
|
||||||
|
}
|
||||||
|
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<Self> {
|
pub fn from_wasm_bytes(bytes: &'a [u8]) -> Result<Self> {
|
||||||
|
|
Loading…
Reference in a new issue