mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 14:54:47 +00:00
wasm: add some utility Parser instances and todos
This commit is contained in:
parent
2732d46f37
commit
73d79d68b0
2 changed files with 171 additions and 0 deletions
|
@ -4,6 +4,7 @@ use bumpalo::Bump;
|
||||||
use super::sections::{update_section_size, write_custom_section_header};
|
use super::sections::{update_section_size, write_custom_section_header};
|
||||||
use super::serialize::{SerialBuffer, Serialize};
|
use super::serialize::{SerialBuffer, Serialize};
|
||||||
use super::Align;
|
use super::Align;
|
||||||
|
use crate::wasm_module::{Parse, ParseError};
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
*
|
*
|
||||||
|
@ -136,6 +137,43 @@ impl Serialize for RelocationEntry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Parse<()> for RelocationEntry {
|
||||||
|
fn parse(_: (), bytes: &[u8], cursor: &mut usize) -> Result<Self, ParseError> {
|
||||||
|
use IndexRelocType::*;
|
||||||
|
|
||||||
|
let type_id = bytes[*cursor];
|
||||||
|
*cursor += 1;
|
||||||
|
let offset = u32::parse((), bytes, cursor)?;
|
||||||
|
let symbol_index = u32::parse((), bytes, cursor)?;
|
||||||
|
|
||||||
|
if type_id == (FunctionIndexLeb as u8)
|
||||||
|
|| type_id == (TableIndexSleb as u8)
|
||||||
|
|| type_id == (TableIndexI32 as u8)
|
||||||
|
|| type_id == (TypeIndexLeb as u8)
|
||||||
|
|| type_id == (GlobalIndexLeb as u8)
|
||||||
|
|| type_id == (EventIndexLeb as u8)
|
||||||
|
|| type_id == (GlobalIndexI32 as u8)
|
||||||
|
|| type_id == (TableIndexSleb64 as u8)
|
||||||
|
|| type_id == (TableIndexI64 as u8)
|
||||||
|
|| type_id == (TableNumberLeb as u8)
|
||||||
|
{
|
||||||
|
Ok(RelocationEntry::Index {
|
||||||
|
type_id: unsafe { std::mem::transmute(type_id) },
|
||||||
|
offset,
|
||||||
|
symbol_index,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
let addend = i32::parse((), bytes, cursor)?;
|
||||||
|
Ok(RelocationEntry::Offset {
|
||||||
|
type_id: unsafe { std::mem::transmute(type_id) },
|
||||||
|
offset,
|
||||||
|
symbol_index,
|
||||||
|
addend,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RelocationSection<'a> {
|
pub struct RelocationSection<'a> {
|
||||||
pub name: &'a str,
|
pub name: &'a str,
|
||||||
|
@ -165,6 +203,13 @@ impl<'a> Serialize for RelocationSection<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Parse<&'a Bump> for RelocationSection<'a> {
|
||||||
|
fn parse(arena: &'a Bump, bytes: &[u8], cursor: &mut usize) -> Result<Self, ParseError> {
|
||||||
|
let name = <&'a str>::parse(arena, bytes, cursor)?;
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
*
|
*
|
||||||
* Linking section
|
* Linking section
|
||||||
|
@ -191,6 +236,12 @@ impl<'a> Serialize for LinkingSegment<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Parse<&'a Bump> for LinkingSegment<'a> {
|
||||||
|
fn parse(arena: &'a Bump, bytes: &[u8], cursor: &mut usize) -> Result<Self, ParseError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Linking metadata for init (start) functions
|
/// Linking metadata for init (start) functions
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LinkingInitFunc {
|
pub struct LinkingInitFunc {
|
||||||
|
@ -204,6 +255,12 @@ impl Serialize for LinkingInitFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Parse<()> for LinkingInitFunc {
|
||||||
|
fn parse(_: (), bytes: &[u8], cursor: &mut usize) -> Result<Self, ParseError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------
|
//------------------------------------------------
|
||||||
// Common data
|
// Common data
|
||||||
//------------------------------------------------
|
//------------------------------------------------
|
||||||
|
@ -231,6 +288,12 @@ impl Serialize for ComdatSym {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Parse<()> for ComdatSym {
|
||||||
|
fn parse(_: (), bytes: &[u8], cursor: &mut usize) -> Result<Self, ParseError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Linking metadata for common data
|
/// Linking metadata for common data
|
||||||
/// A COMDAT group may contain one or more functions, data segments, and/or custom sections.
|
/// A COMDAT group may contain one or more functions, data segments, and/or custom sections.
|
||||||
/// The linker will include all of these elements with a given group name from one object file,
|
/// The linker will include all of these elements with a given group name from one object file,
|
||||||
|
@ -249,6 +312,12 @@ impl<'a> Serialize for LinkingComdat<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Parse<&'a Bump> for LinkingComdat<'a> {
|
||||||
|
fn parse(arena: &'a Bump, bytes: &[u8], cursor: &mut usize) -> Result<Self, ParseError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------------------
|
//------------------------------------------------
|
||||||
// Symbol table
|
// Symbol table
|
||||||
//------------------------------------------------
|
//------------------------------------------------
|
||||||
|
@ -321,6 +390,12 @@ impl<'a> Serialize for WasmObjectSymbol<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Parse<&'a Bump> for WasmObjectSymbol<'a> {
|
||||||
|
fn parse(arena: &'a Bump, bytes: &[u8], cursor: &mut usize) -> Result<Self, ParseError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum DataSymbol<'a> {
|
pub enum DataSymbol<'a> {
|
||||||
Defined {
|
Defined {
|
||||||
|
@ -362,6 +437,12 @@ impl<'a> Serialize for DataSymbol<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Parse<&'a Bump> for DataSymbol<'a> {
|
||||||
|
fn parse(arena: &'a Bump, bytes: &[u8], cursor: &mut usize) -> Result<Self, ParseError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// section index (not section id!)
|
/// section index (not section id!)
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct SectionSymbol {
|
pub struct SectionSymbol {
|
||||||
|
@ -376,6 +457,12 @@ impl Serialize for SectionSymbol {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Parse<()> for SectionSymbol {
|
||||||
|
fn parse(_: (), bytes: &[u8], cursor: &mut usize) -> Result<Self, ParseError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum SymInfo<'a> {
|
pub enum SymInfo<'a> {
|
||||||
Function(WasmObjectSymbol<'a>),
|
Function(WasmObjectSymbol<'a>),
|
||||||
|
@ -417,6 +504,12 @@ impl<'a> Serialize for SymInfo<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Parse<&'a Bump> for SymInfo<'a> {
|
||||||
|
fn parse(arena: &'a Bump, bytes: &[u8], cursor: &mut usize) -> Result<Self, ParseError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
// Linking subsections
|
// Linking subsections
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
|
@ -489,3 +582,9 @@ impl<'a> Serialize for LinkingSection<'a> {
|
||||||
update_section_size(buffer, header_indices);
|
update_section_size(buffer, header_indices);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Parse<&'a Bump> for LinkingSection<'a> {
|
||||||
|
fn parse(arena: &'a Bump, bytes: &[u8], cursor: &mut usize) -> Result<Self, ParseError> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +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;
|
||||||
|
|
||||||
/// Parse serialized bytes into a data structure
|
/// Parse serialized bytes into a data structure
|
||||||
|
@ -46,6 +47,43 @@ impl Parse<()> for u32 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Decode a signed 32-bit integer from the provided buffer in LEB-128 format
|
||||||
|
/// Return the integer itself and the offset after it ends
|
||||||
|
fn decode_i32(bytes: &[u8]) -> Result<(i32, usize), ()> {
|
||||||
|
let mut value = 0;
|
||||||
|
let mut shift = 0;
|
||||||
|
for (i, byte) in bytes.iter().take(MAX_SIZE_ENCODED_U32).enumerate() {
|
||||||
|
value |= ((byte & 0x7f) as i32) << shift;
|
||||||
|
if (byte & 0x80) == 0 {
|
||||||
|
let is_negative = byte & 0x40 != 0;
|
||||||
|
if shift < MAX_SIZE_ENCODED_U32 && is_negative {
|
||||||
|
value |= -1 << shift;
|
||||||
|
}
|
||||||
|
return Ok((value, i + 1));
|
||||||
|
}
|
||||||
|
shift += 7;
|
||||||
|
}
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse<()> for i32 {
|
||||||
|
fn parse(_ctx: (), bytes: &[u8], cursor: &mut usize) -> Result<Self, ParseError> {
|
||||||
|
match decode_i32(&bytes[*cursor..]) {
|
||||||
|
Ok((value, len)) => {
|
||||||
|
*cursor += len;
|
||||||
|
Ok(value)
|
||||||
|
}
|
||||||
|
Err(()) => Err(ParseError {
|
||||||
|
offset: *cursor,
|
||||||
|
message: format!(
|
||||||
|
"Failed to decode i32 as LEB-128 from bytes: {:2x?}",
|
||||||
|
&bytes[*cursor..][..MAX_SIZE_ENCODED_U32]
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Parse<&'a Bump> for &'a str {
|
impl<'a> Parse<&'a Bump> for &'a str {
|
||||||
fn parse(arena: &'a Bump, bytes: &[u8], cursor: &mut usize) -> Result<Self, ParseError> {
|
fn parse(arena: &'a Bump, bytes: &[u8], cursor: &mut usize) -> Result<Self, ParseError> {
|
||||||
let len = u32::parse((), bytes, cursor)?;
|
let len = u32::parse((), bytes, cursor)?;
|
||||||
|
@ -58,6 +96,40 @@ impl<'a> Parse<&'a Bump> for &'a str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_variable_size_items<'a, T>(
|
||||||
|
arena: &'a Bump,
|
||||||
|
bytes: &[u8],
|
||||||
|
cursor: &mut usize,
|
||||||
|
) -> Result<Vec<'a, T>, ParseError>
|
||||||
|
where
|
||||||
|
T: Parse<&'a Bump>,
|
||||||
|
{
|
||||||
|
let len = u32::parse((), bytes, cursor)?;
|
||||||
|
let mut vector: Vec<'a, T> = Vec::with_capacity_in(len as usize, arena);
|
||||||
|
for _ in 0..len {
|
||||||
|
let item = T::parse(arena, bytes, cursor)?;
|
||||||
|
vector.push(item);
|
||||||
|
}
|
||||||
|
Ok(vector)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_fixed_size_items<'a, T>(
|
||||||
|
arena: &'a Bump,
|
||||||
|
bytes: &[u8],
|
||||||
|
cursor: &mut usize,
|
||||||
|
) -> Result<Vec<'a, T>, ParseError>
|
||||||
|
where
|
||||||
|
T: Parse<()>,
|
||||||
|
{
|
||||||
|
let len = u32::parse((), bytes, cursor)?;
|
||||||
|
let mut vector: Vec<'a, T> = Vec::with_capacity_in(len as usize, arena);
|
||||||
|
for _ in 0..len {
|
||||||
|
let item = T::parse((), bytes, cursor)?;
|
||||||
|
vector.push(item);
|
||||||
|
}
|
||||||
|
Ok(vector)
|
||||||
|
}
|
||||||
|
|
||||||
/// Skip over serialized bytes for a type
|
/// Skip over serialized bytes for a type
|
||||||
/// This may, or may not, require looking at the byte values
|
/// This may, or may not, require looking at the byte values
|
||||||
pub trait SkipBytes: Sized {
|
pub trait SkipBytes: Sized {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue