wasmparser/readers/core/
branch_hinting.rs

1use crate::{BinaryReader, FromReader, Result, SectionLimited};
2
3/// A reader for the `metadata.code.branch_hint` custom section.
4pub type BranchHintSectionReader<'a> = SectionLimited<'a, BranchHintFunction<'a>>;
5
6/// Branch hints for a single function.
7///
8/// Produced from [`BranchHintSectionReader`].
9#[derive(Debug, Clone)]
10pub struct BranchHintFunction<'a> {
11    /// The function that these branch hints apply to.
12    pub func: u32,
13    /// The branch hints available for this function.
14    pub hints: SectionLimited<'a, BranchHint>,
15}
16
17impl<'a> FromReader<'a> for BranchHintFunction<'a> {
18    fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
19        let func = reader.read_var_u32()?;
20        // FIXME(#188) ideally wouldn't have to do skips here
21        let hints = reader.skip(|reader| {
22            let items_count = reader.read_var_u32()?;
23            for _ in 0..items_count {
24                reader.read::<BranchHint>()?;
25            }
26            Ok(())
27        })?;
28        Ok(BranchHintFunction {
29            func,
30            hints: SectionLimited::new(hints)?,
31        })
32    }
33}
34
35/// A hint for a single branch.
36#[derive(Debug, Copy, Clone)]
37pub struct BranchHint {
38    /// The byte offset, from the start of the function's body, of where the
39    /// hinted instruction lives.
40    pub func_offset: u32,
41    /// Whether or not the branch is hinted to be taken or not.
42    pub taken: bool,
43}
44
45impl<'a> FromReader<'a> for BranchHint {
46    fn from_reader(reader: &mut BinaryReader<'a>) -> Result<Self> {
47        let func_offset = reader.read_var_u32()?;
48        match reader.read_u8()? {
49            1 => {}
50            n => reader.invalid_leading_byte(n, "invalid branch hint byte")?,
51        }
52        let taken = match reader.read_u8()? {
53            0 => false,
54            1 => true,
55            n => reader.invalid_leading_byte(n, "invalid branch hint taken byte")?,
56        };
57        Ok(BranchHint { func_offset, taken })
58    }
59}