From 66c78ceed5ed03a1f06e2c3f61b6d1f8097cf0eb Mon Sep 17 00:00:00 2001 From: Brian Carroll Date: Sun, 22 May 2022 10:17:09 +0100 Subject: [PATCH] Replace some helper functions with Parse trait instances --- .../gen_wasm/src/wasm_module/dead_code.rs | 12 +++--- compiler/gen_wasm/src/wasm_module/parse.rs | 36 ++++------------ compiler/gen_wasm/src/wasm_module/sections.rs | 41 +++++++++---------- 3 files changed, 35 insertions(+), 54 deletions(-) diff --git a/compiler/gen_wasm/src/wasm_module/dead_code.rs b/compiler/gen_wasm/src/wasm_module/dead_code.rs index 939cdc642f..198d53c8ba 100644 --- a/compiler/gen_wasm/src/wasm_module/dead_code.rs +++ b/compiler/gen_wasm/src/wasm_module/dead_code.rs @@ -2,7 +2,7 @@ use bumpalo::collections::vec::Vec; use bumpalo::Bump; use super::opcodes::OpCode; -use super::parse::{parse_u32_or_panic, SkipBytes}; +use super::parse::{Parse, SkipBytes}; use super::serialize::{SerialBuffer, Serialize}; use super::CodeBuilder; @@ -92,13 +92,13 @@ pub fn parse_preloads_call_graph<'a>( call_graph.code_offsets.push(cursor as u32); call_graph.calls_offsets.push(call_graph.calls.len() as u32); - let func_size = parse_u32_or_panic(code_section_body, &mut cursor); + let func_size = u32::parse((), code_section_body, &mut cursor).unwrap(); let func_end = cursor + func_size as usize; // Skip over local variable declarations - let local_groups_count = parse_u32_or_panic(code_section_body, &mut cursor); + let local_groups_count = u32::parse((), code_section_body, &mut cursor).unwrap(); for _ in 0..local_groups_count { - parse_u32_or_panic(code_section_body, &mut cursor); + u32::parse((), code_section_body, &mut cursor).unwrap(); cursor += 1; // ValueType } @@ -107,12 +107,12 @@ pub fn parse_preloads_call_graph<'a>( let opcode_byte: u8 = code_section_body[cursor]; if opcode_byte == OpCode::CALL as u8 { cursor += 1; - let call_index = parse_u32_or_panic(code_section_body, &mut cursor); + let call_index = u32::parse((), code_section_body, &mut cursor).unwrap(); call_graph.calls.push(call_index as u32); } else if opcode_byte == OpCode::CALLINDIRECT as u8 { cursor += 1; // Insert all indirect callees with a matching type signature - let sig = parse_u32_or_panic(code_section_body, &mut cursor); + let sig = u32::parse((), code_section_body, &mut cursor).unwrap(); call_graph.calls.extend( indirect_callees .iter() diff --git a/compiler/gen_wasm/src/wasm_module/parse.rs b/compiler/gen_wasm/src/wasm_module/parse.rs index c45f4d1405..b90c4eb582 100644 --- a/compiler/gen_wasm/src/wasm_module/parse.rs +++ b/compiler/gen_wasm/src/wasm_module/parse.rs @@ -1,7 +1,5 @@ use super::serialize::MAX_SIZE_ENCODED_U32; -use bumpalo::collections::vec::Vec; use bumpalo::Bump; -use roc_error_macros::internal_error; /// Parse serialized bytes into a data structure /// Specific parsers may need contextual data from other parts of the .wasm file @@ -41,34 +39,18 @@ impl Parse<()> for u32 { } } -// Parse a vector of bytes (used for strings, but we don't bother with utf8 validation) -impl<'a> Parse<&'a Bump> for Vec<'a, u8> { +// Parse string bytes without utf8 validation +impl<'a> Parse<&'a Bump> for &'a [u8] { fn parse(arena: &'a Bump, bytes: &[u8], cursor: &mut usize) -> Result { - let len = parse_u32_or_panic(bytes, cursor); + let len = u32::parse((), bytes, cursor)?; let end = *cursor + len as usize; let bytes: &[u8] = &bytes[*cursor..end]; - let mut copy = Vec::with_capacity_in(bytes.len(), arena); - copy.extend_from_slice(bytes); + let copy = arena.alloc_slice_copy(bytes); *cursor = end; Ok(copy) } } -pub fn parse_u32_or_panic(bytes: &[u8], cursor: &mut usize) -> u32 { - let (value, len) = decode_u32(&bytes[*cursor..]).unwrap_or_else(|e| internal_error!("{}", e)); - *cursor += len; - value -} - -pub fn parse_string_bytes<'a>(arena: &'a Bump, bytes: &[u8], cursor: &mut usize) -> &'a [u8] { - let len = parse_u32_or_panic(bytes, cursor); - let end = *cursor + len as usize; - let bytes: &[u8] = &bytes[*cursor..end]; - let copy = arena.alloc_slice_copy(bytes); - *cursor = end; - copy -} - impl SkipBytes for u32 { fn skip_bytes(bytes: &[u8], cursor: &mut usize) -> Result<(), String> { const MAX_LEN: usize = 5; @@ -105,7 +87,7 @@ impl SkipBytes for u8 { /// Note: This is just for skipping over Wasm bytes. We don't actually care about String vs str! impl SkipBytes for String { fn skip_bytes(bytes: &[u8], cursor: &mut usize) -> Result<(), String> { - let len = parse_u32_or_panic(bytes, cursor); + let len = u32::parse((), bytes, cursor)?; if false { let str_bytes = &bytes[*cursor..(*cursor + len as usize)]; @@ -123,7 +105,7 @@ impl SkipBytes for String { #[cfg(test)] mod tests { use super::*; - use crate::wasm_module::parse::{decode_u32, parse_u32_or_panic}; + use crate::wasm_module::parse::decode_u32; #[test] fn test_decode_u32() { @@ -148,13 +130,13 @@ mod tests { let expected = [0, 128, u32::MAX]; let mut cursor = 0; - assert_eq!(parse_u32_or_panic(bytes, &mut cursor), expected[0]); + assert_eq!(u32::parse((), bytes, &mut cursor).unwrap(), expected[0]); assert_eq!(cursor, 1); - assert_eq!(parse_u32_or_panic(bytes, &mut cursor), expected[1]); + assert_eq!(u32::parse((), bytes, &mut cursor).unwrap(), expected[1]); assert_eq!(cursor, 3); - assert_eq!(parse_u32_or_panic(bytes, &mut cursor), expected[2]); + assert_eq!(u32::parse((), bytes, &mut cursor).unwrap(), expected[2]); assert_eq!(cursor, 8); } } diff --git a/compiler/gen_wasm/src/wasm_module/sections.rs b/compiler/gen_wasm/src/wasm_module/sections.rs index 4036a8e3e6..7eafa1d885 100644 --- a/compiler/gen_wasm/src/wasm_module/sections.rs +++ b/compiler/gen_wasm/src/wasm_module/sections.rs @@ -11,7 +11,7 @@ use super::dead_code::{ }; use super::linking::RelocationEntry; use super::opcodes::OpCode; -use super::parse::{parse_string_bytes, parse_u32_or_panic, Parse, SkipBytes}; +use super::parse::{Parse, SkipBytes}; use super::serialize::{SerialBuffer, Serialize, MAX_SIZE_ENCODED_U32}; use super::{CodeBuilder, ValueType}; @@ -118,9 +118,9 @@ fn parse_section<'a>(id: SectionId, module_bytes: &'a [u8], cursor: &mut usize) } *cursor += 1; - let section_size = parse_u32_or_panic(module_bytes, cursor); + let section_size = u32::parse((), module_bytes, cursor).unwrap(); let count_start = *cursor; - let count = parse_u32_or_panic(module_bytes, cursor); + let count = u32::parse((), module_bytes, cursor).unwrap(); let body_start = *cursor; let next_section_start = count_start + section_size as usize; @@ -237,7 +237,7 @@ impl<'a> TypeSection<'a> { debug_assert!(self.bytes[i] == Signature::SEPARATOR); i += 1; - let n_params = parse_u32_or_panic(&self.bytes, &mut i); + let n_params = u32::parse((), &self.bytes, &mut i).unwrap(); i += n_params as usize; // skip over one byte per param type let n_return_values = self.bytes[i]; @@ -421,7 +421,7 @@ impl<'a> FunctionSection<'a> { let mut signatures = Vec::with_capacity_in(count, arena); let mut cursor = 0; for _ in 0..count { - signatures.push(parse_u32_or_panic(&self.bytes, &mut cursor)); + signatures.push(u32::parse((), &self.bytes, &mut cursor).unwrap()); } signatures } @@ -579,9 +579,9 @@ impl Limits { let variant_id = bytes[*cursor]; *cursor += 1; - let min = parse_u32_or_panic(bytes, cursor); + let min = u32::parse((), bytes, cursor).unwrap(); if variant_id == LimitsId::MinMax as u8 { - let max = parse_u32_or_panic(bytes, cursor); + let max = u32::parse((), bytes, cursor).unwrap(); Limits::MinMax(min, max) } else { Limits::Min(min) @@ -663,7 +663,7 @@ impl ConstExpr { } *cursor += 1; - let value = parse_u32_or_panic(bytes, cursor); + let value = u32::parse((), bytes, cursor).unwrap(); if bytes[*cursor] != OpCode::END as u8 { return err; @@ -791,12 +791,12 @@ pub struct Export<'a> { impl<'a> Export<'a> { fn parse(arena: &'a Bump, bytes: &[u8], cursor: &mut usize) -> Self { - let name = parse_string_bytes(arena, bytes, cursor); + let name = <&'a [u8]>::parse(arena, bytes, cursor).unwrap(); let ty = ExportType::from(bytes[*cursor]); *cursor += 1; - let index = parse_u32_or_panic(bytes, cursor); + let index = u32::parse((), bytes, cursor).unwrap(); Export { name, ty, index } } @@ -895,14 +895,14 @@ impl<'a> ElementSegment<'a> { let const_expr_opcode = bytes[*cursor]; debug_assert!(const_expr_opcode == OpCode::I32CONST as u8); *cursor += 1; - let offset = parse_u32_or_panic(bytes, cursor); + let offset = u32::parse((), bytes, cursor).unwrap(); debug_assert!(bytes[*cursor] == OpCode::END as u8); *cursor += 1; - let num_elems = parse_u32_or_panic(bytes, cursor); + let num_elems = u32::parse((), bytes, cursor).unwrap(); let mut fn_indices = Vec::with_capacity_in(num_elems as usize, arena); for _ in 0..num_elems { - let fn_idx = parse_u32_or_panic(bytes, cursor); + let fn_idx = u32::parse((), bytes, cursor).unwrap(); fn_indices.push(fn_idx); } @@ -1219,7 +1219,7 @@ impl<'a> OpaqueSection<'a> { } else { let section_start = *cursor; *cursor += 1; - let section_size = parse_u32_or_panic(module_bytes, cursor); + let section_size = u32::parse((), module_bytes, cursor).unwrap(); let next_section_start = *cursor + section_size as usize; bytes = &module_bytes[section_start..next_section_start]; *cursor = next_section_start; @@ -1293,7 +1293,7 @@ impl<'a> NameSection<'a> { *cursor += 1; // Section size - let section_size = parse_u32_or_panic(module_bytes, cursor) as usize; + let section_size = u32::parse((), module_bytes, cursor).unwrap() as usize; let section_end = *cursor + section_size; let mut section = NameSection { @@ -1312,7 +1312,7 @@ impl<'a> NameSection<'a> { cursor: &mut usize, section_end: usize, ) { - let section_name = parse_string_bytes(arena, module_bytes, cursor); + let section_name = <&'a [u8]>::parse(arena, module_bytes, cursor).unwrap(); if section_name != Self::NAME.as_bytes() { internal_error!( "Expected Custom section {:?}, found {:?}", @@ -1326,7 +1326,7 @@ impl<'a> NameSection<'a> { for _possible_subsection_id in 0..2 { let subsection_id = module_bytes[*cursor]; *cursor += 1; - let subsection_size = parse_u32_or_panic(module_bytes, cursor); + let subsection_size = u32::parse((), module_bytes, cursor).unwrap(); if subsection_id == NameSubSections::FunctionNames as u8 { found_function_names = true; break; @@ -1341,12 +1341,11 @@ impl<'a> NameSection<'a> { } // Function names - let num_entries = parse_u32_or_panic(module_bytes, cursor) as usize; + let num_entries = u32::parse((), module_bytes, cursor).unwrap() as usize; let fn_names_start = *cursor; for _ in 0..num_entries { - let fn_index = parse_u32_or_panic(module_bytes, cursor); - let name_bytes = parse_string_bytes(arena, module_bytes, cursor); - + let fn_index = u32::parse((), module_bytes, cursor).unwrap(); + let name_bytes = <&'a [u8]>::parse(arena, module_bytes, cursor).unwrap(); self.functions .insert(arena.alloc_slice_copy(name_bytes), fn_index); }