From 10e1abf6d04e3d9dd03f62f10eb83c738f226c62 Mon Sep 17 00:00:00 2001 From: lbrande Date: Wed, 16 Mar 2022 14:19:25 +0100 Subject: [PATCH] Derived Clone and Copy for DataKind. Added locals to LocalFunction. --- crates/tests/tests/custom_sections.rs | 3 ++- examples/build-wasm-from-scratch.rs | 2 +- src/function_builder.rs | 15 ++++++++++----- src/ir/traversals.rs | 2 +- src/module/data.rs | 4 ++-- src/module/exports.rs | 6 +++--- src/module/functions/local_function/mod.rs | 17 +++++++++++++++-- src/module/functions/mod.rs | 7 +++++-- 8 files changed, 39 insertions(+), 17 deletions(-) diff --git a/crates/tests/tests/custom_sections.rs b/crates/tests/tests/custom_sections.rs index ec2122bb..2897491c 100644 --- a/crates/tests/tests/custom_sections.rs +++ b/crates/tests/tests/custom_sections.rs @@ -101,8 +101,9 @@ fn smoke_test_code_transform() { let mut builder = walrus::FunctionBuilder::new(&mut module.types, &[], &[ValType::I32]); builder.func_body().i32_const(1337); + let args = vec![]; let locals = vec![]; - let f_id = builder.finish(locals, &mut module.funcs); + let f_id = builder.finish(args, locals, &mut module.funcs); module.exports.add("f", f_id); diff --git a/examples/build-wasm-from-scratch.rs b/examples/build-wasm-from-scratch.rs index 35dbb6a1..94979280 100644 --- a/examples/build-wasm-from-scratch.rs +++ b/examples/build-wasm-from-scratch.rs @@ -95,7 +95,7 @@ fn main() -> walrus::Result<()> { }) .local_get(res); - let factorial = factorial.finish(vec![n], &mut module.funcs); + let factorial = factorial.finish(vec![], vec![n], &mut module.funcs); // Export the `factorial` function. module.exports.add("factorial", factorial); diff --git a/src/function_builder.rs b/src/function_builder.rs index b708adad..bc9b5cf9 100644 --- a/src/function_builder.rs +++ b/src/function_builder.rs @@ -147,17 +147,22 @@ impl FunctionBuilder { /// .i32_const(1234) /// .drop(); /// - /// let function_id = builder.finish(vec![], &mut module.funcs); + /// let function_id = builder.finish(vec![], vec![], &mut module.funcs); /// # let _ = function_id; /// ``` - pub fn finish(self, args: Vec, funcs: &mut ModuleFunctions) -> FunctionId { - let func = LocalFunction::new(args, self); + pub fn finish( + self, + args: Vec, + locals: Vec, + funcs: &mut ModuleFunctions, + ) -> FunctionId { + let func = LocalFunction::new(args, locals, self); funcs.add_local(func) } /// Returns the [crate::LocalFunction] built by this builder. - pub fn local_func(self, args: Vec) -> LocalFunction { - LocalFunction::new(args, self) + pub fn local_func(self, args: Vec, locals: Vec) -> LocalFunction { + LocalFunction::new(args, locals, self) } } diff --git a/src/ir/traversals.rs b/src/ir/traversals.rs index 6362bdbd..c3d00b10 100644 --- a/src/ir/traversals.rs +++ b/src/ir/traversals.rs @@ -320,7 +320,7 @@ mod tests { .i32_const(6) .drop(); - let func_id = builder.finish(vec![], &mut module.funcs); + let func_id = builder.finish(vec![], vec![], &mut module.funcs); module.funcs.get_mut(func_id).kind.unwrap_local_mut() } diff --git a/src/module/data.rs b/src/module/data.rs index 58acd1d6..943ca6c6 100644 --- a/src/module/data.rs +++ b/src/module/data.rs @@ -28,7 +28,7 @@ pub struct Data { } /// The kind of data segment: passive or active. -#[derive(Debug)] +#[derive(Clone, Copy, Debug)] pub enum DataKind { /// An active data segment that is automatically initialized at some address /// in a static memory. @@ -41,7 +41,7 @@ pub enum DataKind { } /// The parts of a data segment that are only present in active data segments. -#[derive(Clone, Debug)] +#[derive(Clone, Copy, Debug)] pub struct ActiveData { /// The memory that this active data segment will be automatically /// initialized in. diff --git a/src/module/exports.rs b/src/module/exports.rs index 17bbab2b..7901ce6b 100644 --- a/src/module/exports.rs +++ b/src/module/exports.rs @@ -242,7 +242,7 @@ mod tests { let mut module = Module::default(); let mut builder = FunctionBuilder::new(&mut module.types, &[], &[]); builder.func_body().i32_const(1234).drop(); - let id: FunctionId = builder.finish(vec![], &mut module.funcs); + let id: FunctionId = builder.finish(vec![], vec![], &mut module.funcs); module.exports.add("dummy", id); let actual: Option<&Export> = module.exports.get_exported_func(id); @@ -352,11 +352,11 @@ mod tests { let mut builder = FunctionBuilder::new(&mut module.types, &[], &[]); builder.func_body().i32_const(1234).drop(); - let fn_id0: FunctionId = builder.finish(vec![], &mut module.funcs); + let fn_id0: FunctionId = builder.finish(vec![], vec![], &mut module.funcs); let mut builder = FunctionBuilder::new(&mut module.types, &[], &[]); builder.func_body().i32_const(1234).drop(); - let fn_id1: FunctionId = builder.finish(vec![], &mut module.funcs); + let fn_id1: FunctionId = builder.finish(vec![], vec![], &mut module.funcs); assert_ne!(fn_id0, fn_id1); diff --git a/src/module/functions/local_function/mod.rs b/src/module/functions/local_function/mod.rs index c4507c9d..8094a23a 100644 --- a/src/module/functions/local_function/mod.rs +++ b/src/module/functions/local_function/mod.rs @@ -21,6 +21,9 @@ pub struct LocalFunction { /// Arguments to this function, and the locals that they're assigned to. pub args: Vec, + + /// Locals of this function, excluding arguments. + pub locals: Vec, // // TODO: provenance: (InstrSeqId, usize) -> offset in code section of the // original instruction. This will be necessary for preserving debug info. @@ -28,8 +31,16 @@ pub struct LocalFunction { impl LocalFunction { /// Creates a new definition of a local function from its components. - pub(crate) fn new(args: Vec, builder: FunctionBuilder) -> LocalFunction { - LocalFunction { args, builder } + pub(crate) fn new( + args: Vec, + locals: Vec, + builder: FunctionBuilder, + ) -> LocalFunction { + LocalFunction { + args, + locals, + builder, + } } /// Construct a new `LocalFunction`. @@ -42,6 +53,7 @@ impl LocalFunction { id: FunctionId, ty: TypeId, args: Vec, + locals: Vec, mut body: wasmparser::BinaryReader<'_>, on_instr_pos: Option<&(dyn Fn(&usize) -> InstrLocId + Sync + Send + 'static)>, mut validator: FuncValidator, @@ -49,6 +61,7 @@ impl LocalFunction { let mut func = LocalFunction { builder: FunctionBuilder::without_entry(ty), args, + locals, }; let result: Vec<_> = module.types.get(ty).results().iter().cloned().collect(); diff --git a/src/module/functions/mod.rs b/src/module/functions/mod.rs index e782240b..c5cbfcba 100644 --- a/src/module/functions/mod.rs +++ b/src/module/functions/mod.rs @@ -366,6 +366,7 @@ impl Module { // Next up comes all the locals of the function. let mut reader = body.get_binary_reader(); + let mut locals = Vec::new(); for _ in 0..reader.read_var_u32()? { let pos = reader.original_position(); let count = reader.read_var_u32()?; @@ -375,6 +376,7 @@ impl Module { for _ in 0..count { let local_id = self.locals.add(ty); let idx = indices.push_local(id, local_id); + locals.push(local_id); if self.config.generate_synthetic_names_for_anonymous_items { let name = format!("l{}", idx); self.locals.get_mut(local_id).name = Some(name); @@ -382,13 +384,13 @@ impl Module { } } - bodies.push((id, reader, args, ty, validator)); + bodies.push((id, reader, args, locals, ty, validator)); } // Wasm modules can often have a lot of functions and this operation can // take some time, so parse all function bodies in parallel. let results = maybe_parallel!(bodies.(into_iter | into_par_iter)) - .map(|(id, body, args, ty, validator)| { + .map(|(id, body, args, locals, ty, validator)| { ( id, LocalFunction::parse( @@ -397,6 +399,7 @@ impl Module { id, ty, args, + locals, body, on_instr_pos, validator,