1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//! Types in a wasm module.

use crate::arena_set::ArenaSet;
use crate::emit::{Emit, EmitContext, Section};
use crate::error::Result;
use crate::module::Module;
use crate::parse::IndicesToIds;
use crate::ty::{Type, TypeId, ValType};

/// The set of de-duplicated types within a module.
#[derive(Debug, Default)]
pub struct ModuleTypes {
    arena: ArenaSet<Type>,
}

impl ModuleTypes {
    /// Get a type associated with an ID
    pub fn get(&self, id: TypeId) -> &Type {
        &self.arena[id]
    }

    /// Get a type associated with an ID
    pub fn get_mut(&mut self, id: TypeId) -> &mut Type {
        &mut self.arena[id]
    }

    /// Get a shared reference to this module's types.
    pub fn iter(&self) -> impl Iterator<Item = &Type> {
        self.arena.iter().map(|(_, f)| f)
    }

    /// Add a new type to this module, and return its `Id`
    pub fn add(&mut self, params: &[ValType], results: &[ValType]) -> TypeId {
        let id = self.arena.next_id();
        self.arena.insert(Type::new(
            id,
            params.to_vec().into_boxed_slice(),
            results.to_vec().into_boxed_slice(),
        ))
    }
}

impl Module {
    /// Construct the set of types within a module.
    pub(crate) fn parse_types(
        &mut self,
        section: wasmparser::TypeSectionReader,
        ids: &mut IndicesToIds,
    ) -> Result<()> {
        log::debug!("parsing type section");
        for ty in section {
            let fun_ty = ty?;
            let id = self.types.arena.next_id();
            let params = fun_ty
                .params
                .iter()
                .map(ValType::parse)
                .collect::<Result<Vec<_>>>()?
                .into_boxed_slice();
            let results = fun_ty
                .returns
                .iter()
                .map(ValType::parse)
                .collect::<Result<Vec<_>>>()?
                .into_boxed_slice();
            let id = self.types.arena.insert(Type::new(id, params, results));
            ids.push_type(id);
        }

        Ok(())
    }
}

impl Emit for ModuleTypes {
    fn emit(&self, cx: &mut EmitContext) {
        log::debug!("emitting type section");
        let ntypes = cx.used.types.len();
        if ntypes == 0 {
            return;
        }
        let mut cx = cx.start_section(Section::Type);
        cx.encoder.usize(ntypes);

        for (id, ty) in self.arena.iter() {
            if !cx.used.types.contains(&id) {
                continue;
            }
            cx.indices.push_type(id);
            ty.emit(&mut cx);
        }
    }
}