Skip to content

Commit

Permalink
Merge pull request #26 from alexcrichton/wasmparser
Browse files Browse the repository at this point in the history
Switch to using `wasmparser` to parse wasm files
  • Loading branch information
alexcrichton authored Jan 25, 2019
2 parents e8f257f + 352fe3c commit 8db4a1c
Show file tree
Hide file tree
Showing 15 changed files with 674 additions and 583 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ id-arena = "2.0.1"
parity-wasm = "0.35.6"
petgraph = "0.4.13"
log = "0.4"
wasmparser = "0.24"

[dependencies.walrus-derive]
path = "./walrus-derive"
Expand Down
28 changes: 14 additions & 14 deletions src/const_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,23 @@ pub enum Const {
}

impl Const {
pub(crate) fn eval(init: &elements::InitExpr, ids: &IndicesToIds) -> Result<Const> {
let instrs = init.code();
if instrs.len() != 2 {
bail!("invalid constant expression");
}
match instrs[1] {
Instruction::End => {}
pub(crate) fn eval(init: &wasmparser::InitExpr, ids: &IndicesToIds) -> Result<Const> {
use wasmparser::Operator::*;
let mut reader = init.get_operators_reader();
let val = match reader.read()? {
I32Const { value } => Const::Value(Value::I32(value)),
I64Const { value } => Const::Value(Value::I64(value)),
F32Const { value } => Const::Value(Value::F32(f32::from_bits(value.bits()))),
F64Const { value } => Const::Value(Value::F64(f64::from_bits(value.bits()))),
GetGlobal { global_index } => Const::Global(ids.get_global(global_index)?),
_ => bail!("invalid constant expression"),
}
match instrs[0] {
Instruction::I32Const(n) => Ok(Const::Value(Value::I32(n))),
Instruction::I64Const(n) => Ok(Const::Value(Value::I64(n))),
Instruction::F32Const(n) => Ok(Const::Value(Value::F32(f32::from_bits(n)))),
Instruction::F64Const(n) => Ok(Const::Value(Value::F64(f64::from_bits(n)))),
Instruction::GetGlobal(n) => Ok(Const::Global(ids.get_global(n)?)),
};
match reader.read()? {
End => {}
_ => bail!("invalid constant expression"),
}
reader.ensure_end()?;
Ok(val)
}

pub(crate) fn emit_instructions(&self, indices: &IdsToIndices) -> elements::InitExpr {
Expand Down
33 changes: 18 additions & 15 deletions src/module/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,27 +46,30 @@ impl ModuleData {

impl Module {
/// Parses a raw wasm section into a fully-formed `ModuleData` instance.
pub fn parse_data(
pub(crate) fn parse_data(
&mut self,
section: &elements::DataSection,
section: wasmparser::DataSectionReader,
ids: &mut IndicesToIds,
) -> Result<()> {
for (i, segment) in section.entries().iter().enumerate() {
if segment.passive() {
let id = self.data.arena.next_id();
self.data.arena.alloc(Data {
value: segment.value().to_vec(),
});
ids.push_data(id);
continue;
}
for (i, segment) in section.into_iter().enumerate() {
let segment = segment?;

// TODO: upstream passive support
// if segment.passive() {
// let id = self.data.arena.next_id();
// self.data.arena.alloc(Data {
// value: segment.value().to_vec(),
// });
// ids.push_data(id);
// continue;
// }

let memory = ids.get_memory(segment.index())?;
let value = segment.value().to_vec();
let memory = ids.get_memory(segment.memory_index)?;
let value = segment.data.to_vec();
let memory = self.memories.get_mut(memory);

let offset = segment.offset().as_ref().unwrap();
let offset = Const::eval(offset, ids).with_context(|_e| format!("in segment {}", i))?;
let offset = Const::eval(&segment.init_expr, ids)
.with_context(|_e| format!("in segment {}", i))?;
match offset {
Const::Value(Value::I32(n)) => {
memory.data.add_absolute(n as u32, value);
Expand Down
39 changes: 22 additions & 17 deletions src/module/elements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,30 +50,35 @@ impl Module {
/// Parses a raw was section into a fully-formed `ModuleElements` instance.
pub fn parse_elements(
&mut self,
section: &elements::ElementSection,
section: wasmparser::ElementSectionReader,
ids: &mut IndicesToIds,
) -> Result<()> {
for (i, segment) in section.entries().iter().enumerate() {
if segment.passive() {
let mut list = Vec::with_capacity(segment.members().len());
for &func in segment.members() {
list.push(ids.get_func(func)?);
}
let id = self.elements.arena.next_id();
self.elements.arena.alloc(Element { members: list });
ids.push_element(id);
continue;
}

let table = ids.get_table(segment.index())?;
for (i, segment) in section.into_iter().enumerate() {
let segment = segment?;
// TODO: get support for passive segments in wasmparser
// if segment.passive() {
// let mut list = Vec::with_capacity(segment.members().len());
// for &func in segment.members() {
// list.push(ids.get_func(func)?);
// }
// let id = self.elements.arena.next_id();
// self.elements.arena.alloc(Element { members: list });
// ids.push_element(id);
// continue;
// }

let table = ids.get_table(segment.table_index)?;
let table = match &mut self.tables.get_mut(table).kind {
TableKind::Function(t) => t,
};

let functions = segment.members().iter().map(|func| ids.get_func(*func));
let offset = Const::eval(&segment.init_expr, ids)
.with_context(|_e| format!("in segment {}", i))?;
let functions = segment.items.get_items_reader()?.into_iter().map(|func| {
let func = func?;
ids.get_func(func)
});

let offset = segment.offset().as_ref().unwrap();
let offset = Const::eval(offset, ids).with_context(|_e| format!("in segment {}", i))?;
match offset {
Const::Value(Value::I32(n)) => {
let offset = n as usize;
Expand Down
19 changes: 11 additions & 8 deletions src/module/exports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,20 +100,23 @@ impl Module {
/// Construct the export set for a wasm module.
pub(crate) fn parse_exports(
&mut self,
section: &elements::ExportSection,
section: wasmparser::ExportSectionReader,
ids: &IndicesToIds,
) -> Result<()> {
for exp in section.entries() {
let item = match *exp.internal() {
elements::Internal::Function(f) => ExportItem::Function(ids.get_func(f)?),
elements::Internal::Table(t) => ExportItem::Table(ids.get_table(t)?),
elements::Internal::Memory(t) => ExportItem::Memory(ids.get_memory(t)?),
elements::Internal::Global(t) => ExportItem::Global(ids.get_global(t)?),
use wasmparser::ExternalKind::*;

for entry in section {
let entry = entry?;
let item = match entry.kind {
Function => ExportItem::Function(ids.get_func(entry.index)?),
Table => ExportItem::Table(ids.get_table(entry.index)?),
Memory => ExportItem::Memory(ids.get_memory(entry.index)?),
Global => ExportItem::Global(ids.get_global(entry.index)?),
};
let id = self.exports.arena.next_id();
self.exports.arena.alloc(Export {
id,
name: exp.field().to_string(),
name: entry.field.to_string(),
item,
});
}
Expand Down
Loading

0 comments on commit 8db4a1c

Please sign in to comment.