-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: nerodesu017 <[email protected]> Signed-off-by: nerodesu017 <[email protected]>
- Loading branch information
1 parent
400533d
commit dbca01a
Showing
25 changed files
with
5,233 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
use super::RefType; | ||
use crate::core::reader::span::Span; | ||
use crate::core::reader::WasmReader; | ||
use crate::read_constant_expression::read_constant_instructions; | ||
use crate::{Error, Result}; | ||
|
||
use alloc::collections::btree_set::BTreeSet; | ||
use alloc::vec::Vec; | ||
use core::fmt::Debug; | ||
|
||
#[derive(Clone)] | ||
pub struct ElemType { | ||
pub init: ElemItems, | ||
pub mode: ElemMode, | ||
} | ||
|
||
impl Debug for ElemType { | ||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { | ||
write!( | ||
f, | ||
"ElemType {{\n\tinit: {:?},\n\tmode: {:?},\n\t#ty: {:?}\n}}", | ||
self.init, | ||
self.mode, | ||
self.init.ty() | ||
) | ||
} | ||
} | ||
|
||
impl ElemType { | ||
pub fn ty(&self) -> RefType { | ||
self.init.ty() | ||
} | ||
|
||
pub fn to_ref_type(&self) -> RefType { | ||
match self.init { | ||
ElemItems::Exprs(rref, _) => rref, | ||
ElemItems::RefFuncs(_) => RefType::FuncRef, | ||
} | ||
} | ||
|
||
// TODO: @nerodesu017 maybe split up the validation from the parsing? | ||
/// Here we can't implement WasmReadable because we also want a mutable | ||
/// reference to a [`BTreeSet<u32>`] (`referenced_functions`) | ||
/// | ||
/// This comes in handy later on when we are validating the actual code of | ||
/// the functions so that we can make sure we are not referencing invalid | ||
/// functions | ||
pub fn read_from_wasm( | ||
wasm: &mut WasmReader, | ||
functions: &[usize], | ||
referenced_functions: &mut BTreeSet<u32>, | ||
tables_length: usize, | ||
) -> Result<Vec<Self>> { | ||
wasm.read_vec(|wasm| { | ||
let prop = wasm.read_var_u32()?; | ||
|
||
// TODO: @nerodesu017 revisit this comment | ||
// https://webassembly.github.io/spec/core/syntax/modules.html#element-segments | ||
// https://webassembly.github.io/spec/core/binary/modules.html#element-section | ||
// We can treat the ty as a 3bit integer | ||
// If it's not 3 bits I am not sure what to do | ||
// bit 0 => diff between passive|declartive and active segment | ||
// bit 1 => presence of an explicit table index for an active segment | ||
// bit 2 => use of element type and element expressions instead of element kind and element indices | ||
// decide if we should | ||
|
||
// TODO: @nerodesu017 error, this is a parse error, not validation FYI | ||
// NOTE: This assert breaks my rustfmt :( | ||
// assert!(prop <= 0b111, "Element section is not encoded correctly. The type of this element is over 7 (0b111)"); | ||
|
||
let elem_mode = if prop & 0b011 == 0b011 { | ||
ElemMode::Declarative | ||
} else if prop & 0b001 == 0b001 { | ||
ElemMode::Passive | ||
} else { | ||
let table_idx = if prop & 0b010 == 0b010 { | ||
wasm.read_var_u32()? | ||
} else { | ||
0 | ||
}; | ||
|
||
if tables_length <= table_idx as usize { | ||
return Err(Error::UnknownTable); | ||
} | ||
|
||
let init_expr = read_constant_instructions(wasm, None, None, Some(functions))?; | ||
|
||
ElemMode::Active(ActiveElem { | ||
table_idx, | ||
init_expr, | ||
}) | ||
}; | ||
|
||
let third_bit_set = prop & 0b100 == 0b100; | ||
|
||
let type_kind = if prop & 0b011 != 0 { | ||
if third_bit_set { | ||
Some(wasm.read_u8()?) | ||
} else { | ||
match wasm.read_u8()? { | ||
0x00 => None, | ||
_ => return Err(Error::OnlyFuncRefIsAllowed), | ||
} | ||
} | ||
} else { | ||
None | ||
}; | ||
|
||
let reftype_or_elemkind: Option<RefType> = match type_kind { | ||
Some(ty) => Some(RefType::from_byte(ty)?), | ||
None => None, | ||
}; | ||
|
||
let items: ElemItems = if third_bit_set { | ||
ElemItems::Exprs( | ||
reftype_or_elemkind.unwrap_or(RefType::FuncRef), | ||
wasm.read_vec(|w| read_constant_instructions(w, None, None, Some(functions)))?, | ||
) | ||
} else { | ||
assert!(reftype_or_elemkind.is_none()); | ||
ElemItems::RefFuncs(wasm.read_vec(|w| { | ||
let offset = w.read_var_u32()?; | ||
referenced_functions.insert(offset); | ||
Ok(offset) | ||
})?) | ||
}; | ||
|
||
let el = ElemType { | ||
init: items, | ||
mode: elem_mode, | ||
}; | ||
|
||
Ok(el) | ||
}) | ||
} | ||
} | ||
|
||
#[derive(Debug, Clone)] | ||
pub enum ElemItems { | ||
RefFuncs(Vec<u32>), | ||
Exprs(RefType, Vec<Span>), | ||
} | ||
|
||
impl ElemItems { | ||
pub fn ty(&self) -> RefType { | ||
match self { | ||
Self::RefFuncs(_) => RefType::FuncRef, | ||
Self::Exprs(rty, _) => *rty, | ||
} | ||
} | ||
} | ||
|
||
#[derive(Debug, Clone)] | ||
pub enum ElemMode { | ||
Passive, | ||
Active(ActiveElem), | ||
Declarative, | ||
} | ||
|
||
#[derive(Debug, Clone)] | ||
pub struct ActiveElem { | ||
pub table_idx: u32, | ||
pub init_expr: Span, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.