Replace some helper functions with Parse trait instances

This commit is contained in:
Brian Carroll 2022-05-22 10:17:09 +01:00
parent 8114ec60c1
commit 66c78ceed5
No known key found for this signature in database
GPG key ID: 9CF4E3BF9C4722C7
3 changed files with 35 additions and 54 deletions

View file

@ -2,7 +2,7 @@ use bumpalo::collections::vec::Vec;
use bumpalo::Bump; use bumpalo::Bump;
use super::opcodes::OpCode; use super::opcodes::OpCode;
use super::parse::{parse_u32_or_panic, SkipBytes}; use super::parse::{Parse, SkipBytes};
use super::serialize::{SerialBuffer, Serialize}; use super::serialize::{SerialBuffer, Serialize};
use super::CodeBuilder; use super::CodeBuilder;
@ -92,13 +92,13 @@ pub fn parse_preloads_call_graph<'a>(
call_graph.code_offsets.push(cursor as u32); call_graph.code_offsets.push(cursor as u32);
call_graph.calls_offsets.push(call_graph.calls.len() 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; let func_end = cursor + func_size as usize;
// Skip over local variable declarations // 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 { 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 cursor += 1; // ValueType
} }
@ -107,12 +107,12 @@ pub fn parse_preloads_call_graph<'a>(
let opcode_byte: u8 = code_section_body[cursor]; let opcode_byte: u8 = code_section_body[cursor];
if opcode_byte == OpCode::CALL as u8 { if opcode_byte == OpCode::CALL as u8 {
cursor += 1; 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); call_graph.calls.push(call_index as u32);
} else if opcode_byte == OpCode::CALLINDIRECT as u8 { } else if opcode_byte == OpCode::CALLINDIRECT as u8 {
cursor += 1; cursor += 1;
// Insert all indirect callees with a matching type signature // 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( call_graph.calls.extend(
indirect_callees indirect_callees
.iter() .iter()

View file

@ -1,7 +1,5 @@
use super::serialize::MAX_SIZE_ENCODED_U32; use super::serialize::MAX_SIZE_ENCODED_U32;
use bumpalo::collections::vec::Vec;
use bumpalo::Bump; use bumpalo::Bump;
use roc_error_macros::internal_error;
/// Parse serialized bytes into a data structure /// Parse serialized bytes into a data structure
/// Specific parsers may need contextual data from other parts of the .wasm file /// Specific parsers may need contextual data from other parts of the .wasm file
@ -41,32 +39,16 @@ impl Parse<()> for u32 {
} }
} }
// Parse a vector of bytes (used for strings, but we don't bother with utf8 validation) // Parse string bytes without utf8 validation
impl<'a> Parse<&'a Bump> for Vec<'a, u8> { impl<'a> Parse<&'a Bump> for &'a [u8] {
fn parse(arena: &'a Bump, bytes: &[u8], cursor: &mut usize) -> Result<Self, String> { fn parse(arena: &'a Bump, bytes: &[u8], cursor: &mut usize) -> Result<Self, String> {
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);
*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 end = *cursor + len as usize;
let bytes: &[u8] = &bytes[*cursor..end]; let bytes: &[u8] = &bytes[*cursor..end];
let copy = arena.alloc_slice_copy(bytes); let copy = arena.alloc_slice_copy(bytes);
*cursor = end; *cursor = end;
copy Ok(copy)
}
} }
impl SkipBytes for u32 { impl SkipBytes for u32 {
@ -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! /// Note: This is just for skipping over Wasm bytes. We don't actually care about String vs str!
impl SkipBytes for String { impl SkipBytes for String {
fn skip_bytes(bytes: &[u8], cursor: &mut usize) -> Result<(), 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 { if false {
let str_bytes = &bytes[*cursor..(*cursor + len as usize)]; let str_bytes = &bytes[*cursor..(*cursor + len as usize)];
@ -123,7 +105,7 @@ impl SkipBytes for String {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::wasm_module::parse::{decode_u32, parse_u32_or_panic}; use crate::wasm_module::parse::decode_u32;
#[test] #[test]
fn test_decode_u32() { fn test_decode_u32() {
@ -148,13 +130,13 @@ mod tests {
let expected = [0, 128, u32::MAX]; let expected = [0, 128, u32::MAX];
let mut cursor = 0; 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!(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!(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); assert_eq!(cursor, 8);
} }
} }

View file

@ -11,7 +11,7 @@ use super::dead_code::{
}; };
use super::linking::RelocationEntry; use super::linking::RelocationEntry;
use super::opcodes::OpCode; 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::serialize::{SerialBuffer, Serialize, MAX_SIZE_ENCODED_U32};
use super::{CodeBuilder, ValueType}; use super::{CodeBuilder, ValueType};
@ -118,9 +118,9 @@ fn parse_section<'a>(id: SectionId, module_bytes: &'a [u8], cursor: &mut usize)
} }
*cursor += 1; *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_start = *cursor;
let count = parse_u32_or_panic(module_bytes, cursor); let count = u32::parse((), module_bytes, cursor).unwrap();
let body_start = *cursor; let body_start = *cursor;
let next_section_start = count_start + section_size as usize; 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); debug_assert!(self.bytes[i] == Signature::SEPARATOR);
i += 1; 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 i += n_params as usize; // skip over one byte per param type
let n_return_values = self.bytes[i]; 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 signatures = Vec::with_capacity_in(count, arena);
let mut cursor = 0; let mut cursor = 0;
for _ in 0..count { for _ in 0..count {
signatures.push(parse_u32_or_panic(&self.bytes, &mut cursor)); signatures.push(u32::parse((), &self.bytes, &mut cursor).unwrap());
} }
signatures signatures
} }
@ -579,9 +579,9 @@ impl Limits {
let variant_id = bytes[*cursor]; let variant_id = bytes[*cursor];
*cursor += 1; *cursor += 1;
let min = parse_u32_or_panic(bytes, cursor); let min = u32::parse((), bytes, cursor).unwrap();
if variant_id == LimitsId::MinMax as u8 { 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) Limits::MinMax(min, max)
} else { } else {
Limits::Min(min) Limits::Min(min)
@ -663,7 +663,7 @@ impl ConstExpr {
} }
*cursor += 1; *cursor += 1;
let value = parse_u32_or_panic(bytes, cursor); let value = u32::parse((), bytes, cursor).unwrap();
if bytes[*cursor] != OpCode::END as u8 { if bytes[*cursor] != OpCode::END as u8 {
return err; return err;
@ -791,12 +791,12 @@ pub struct Export<'a> {
impl<'a> Export<'a> { impl<'a> Export<'a> {
fn parse(arena: &'a Bump, bytes: &[u8], cursor: &mut usize) -> Self { 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]); let ty = ExportType::from(bytes[*cursor]);
*cursor += 1; *cursor += 1;
let index = parse_u32_or_panic(bytes, cursor); let index = u32::parse((), bytes, cursor).unwrap();
Export { name, ty, index } Export { name, ty, index }
} }
@ -895,14 +895,14 @@ impl<'a> ElementSegment<'a> {
let const_expr_opcode = bytes[*cursor]; let const_expr_opcode = bytes[*cursor];
debug_assert!(const_expr_opcode == OpCode::I32CONST as u8); debug_assert!(const_expr_opcode == OpCode::I32CONST as u8);
*cursor += 1; *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); debug_assert!(bytes[*cursor] == OpCode::END as u8);
*cursor += 1; *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); let mut fn_indices = Vec::with_capacity_in(num_elems as usize, arena);
for _ in 0..num_elems { 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); fn_indices.push(fn_idx);
} }
@ -1219,7 +1219,7 @@ impl<'a> OpaqueSection<'a> {
} else { } else {
let section_start = *cursor; let section_start = *cursor;
*cursor += 1; *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; let next_section_start = *cursor + section_size as usize;
bytes = &module_bytes[section_start..next_section_start]; bytes = &module_bytes[section_start..next_section_start];
*cursor = next_section_start; *cursor = next_section_start;
@ -1293,7 +1293,7 @@ impl<'a> NameSection<'a> {
*cursor += 1; *cursor += 1;
// Section size // 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 section_end = *cursor + section_size;
let mut section = NameSection { let mut section = NameSection {
@ -1312,7 +1312,7 @@ impl<'a> NameSection<'a> {
cursor: &mut usize, cursor: &mut usize,
section_end: 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() { if section_name != Self::NAME.as_bytes() {
internal_error!( internal_error!(
"Expected Custom section {:?}, found {:?}", "Expected Custom section {:?}, found {:?}",
@ -1326,7 +1326,7 @@ impl<'a> NameSection<'a> {
for _possible_subsection_id in 0..2 { for _possible_subsection_id in 0..2 {
let subsection_id = module_bytes[*cursor]; let subsection_id = module_bytes[*cursor];
*cursor += 1; *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 { if subsection_id == NameSubSections::FunctionNames as u8 {
found_function_names = true; found_function_names = true;
break; break;
@ -1341,12 +1341,11 @@ impl<'a> NameSection<'a> {
} }
// Function names // 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; let fn_names_start = *cursor;
for _ in 0..num_entries { for _ in 0..num_entries {
let fn_index = parse_u32_or_panic(module_bytes, cursor); let fn_index = u32::parse((), module_bytes, cursor).unwrap();
let name_bytes = parse_string_bytes(arena, module_bytes, cursor); let name_bytes = <&'a [u8]>::parse(arena, module_bytes, cursor).unwrap();
self.functions self.functions
.insert(arena.alloc_slice_copy(name_bytes), fn_index); .insert(arena.alloc_slice_copy(name_bytes), fn_index);
} }