wasm_smith/core/
encode.rs

1use super::*;
2
3impl Module {
4    /// Encode this Wasm module into bytes.
5    pub fn to_bytes(&self) -> Vec<u8> {
6        self.encoded().finish()
7    }
8
9    fn encoded(&self) -> wasm_encoder::Module {
10        let mut module = wasm_encoder::Module::new();
11
12        self.encode_types(&mut module);
13        self.encode_imports(&mut module);
14        self.encode_funcs(&mut module);
15        self.encode_tables(&mut module);
16        self.encode_memories(&mut module);
17        self.encode_tags(&mut module);
18        self.encode_globals(&mut module);
19        self.encode_exports(&mut module);
20        self.encode_start(&mut module);
21        self.encode_elems(&mut module);
22        self.encode_data_count(&mut module);
23        self.encode_code(&mut module);
24        self.encode_data(&mut module);
25
26        module
27    }
28
29    fn encode_types(&self, module: &mut wasm_encoder::Module) {
30        if !self.should_encode_types {
31            return;
32        }
33
34        let mut section = wasm_encoder::TypeSection::new();
35
36        for group in &self.rec_groups {
37            if group.end - group.start == 1 {
38                let ty = &self.types[group.start];
39                section.ty().subtype(&wasm_encoder::SubType {
40                    is_final: ty.is_final,
41                    supertype_idx: ty.supertype,
42                    composite_type: (&ty.composite_type).into(),
43                });
44            } else {
45                section.ty().rec(self.types[group.clone()].iter().map(|ty| {
46                    wasm_encoder::SubType {
47                        is_final: ty.is_final,
48                        supertype_idx: ty.supertype,
49                        composite_type: (&ty.composite_type).into(),
50                    }
51                }));
52            }
53        }
54
55        module.section(&section);
56    }
57
58    fn encode_imports(&self, module: &mut wasm_encoder::Module) {
59        if !self.should_encode_imports {
60            return;
61        }
62
63        let mut section = wasm_encoder::ImportSection::new();
64        for im in &self.imports {
65            section.import(&im.module, &im.name, translate_entity_type(&im.entity_type));
66        }
67        module.section(&section);
68    }
69
70    fn encode_tags(&self, module: &mut wasm_encoder::Module) {
71        if self.num_defined_tags == 0 {
72            return;
73        }
74        let mut tags = wasm_encoder::TagSection::new();
75        for tag in self.tags[self.tags.len() - self.num_defined_tags..].iter() {
76            tags.tag(wasm_encoder::TagType {
77                kind: wasm_encoder::TagKind::Exception,
78                func_type_idx: tag.func_type_idx,
79            });
80        }
81        module.section(&tags);
82    }
83
84    fn encode_funcs(&self, module: &mut wasm_encoder::Module) {
85        if self.num_defined_funcs == 0 {
86            return;
87        }
88        let mut funcs = wasm_encoder::FunctionSection::new();
89        for (ty, _) in self.funcs[self.funcs.len() - self.num_defined_funcs..].iter() {
90            funcs.function(*ty);
91        }
92        module.section(&funcs);
93    }
94
95    fn encode_tables(&self, module: &mut wasm_encoder::Module) {
96        if self.defined_tables.is_empty() {
97            return;
98        }
99        let mut tables = wasm_encoder::TableSection::new();
100        for (t, init) in self.tables[self.tables.len() - self.defined_tables.len()..]
101            .iter()
102            .zip(&self.defined_tables)
103        {
104            match init {
105                Some(init) => {
106                    tables.table_with_init(*t, init);
107                }
108                None => {
109                    tables.table(*t);
110                }
111            }
112        }
113        module.section(&tables);
114    }
115
116    fn encode_memories(&self, module: &mut wasm_encoder::Module) {
117        if self.num_defined_memories == 0 {
118            return;
119        }
120        let mut mems = wasm_encoder::MemorySection::new();
121        for m in self.memories[self.memories.len() - self.num_defined_memories..].iter() {
122            mems.memory(*m);
123        }
124        module.section(&mems);
125    }
126
127    fn encode_globals(&self, module: &mut wasm_encoder::Module) {
128        if self.globals.is_empty() {
129            return;
130        }
131        let mut globals = wasm_encoder::GlobalSection::new();
132        for (idx, expr) in &self.defined_globals {
133            let ty = &self.globals[*idx as usize];
134            globals.global(*ty, expr);
135        }
136        module.section(&globals);
137    }
138
139    fn encode_exports(&self, module: &mut wasm_encoder::Module) {
140        if self.exports.is_empty() {
141            return;
142        }
143        let mut exports = wasm_encoder::ExportSection::new();
144        for (name, kind, idx) in &self.exports {
145            exports.export(name, *kind, *idx);
146        }
147        module.section(&exports);
148    }
149
150    fn encode_start(&self, module: &mut wasm_encoder::Module) {
151        if let Some(f) = self.start {
152            module.section(&wasm_encoder::StartSection { function_index: f });
153        }
154    }
155
156    fn encode_elems(&self, module: &mut wasm_encoder::Module) {
157        if self.elems.is_empty() {
158            return;
159        }
160        let mut elems = wasm_encoder::ElementSection::new();
161        for el in &self.elems {
162            let elements = match &el.items {
163                Elements::Expressions(es) => wasm_encoder::Elements::Expressions(el.ty, es.into()),
164                Elements::Functions(fs) => {
165                    assert_eq!(el.ty, RefType::FUNCREF);
166                    wasm_encoder::Elements::Functions(fs.into())
167                }
168            };
169            match &el.kind {
170                ElementKind::Active { table, offset } => {
171                    let offset = match *offset {
172                        Offset::Const32(n) => ConstExpr::i32_const(n),
173                        Offset::Const64(n) => ConstExpr::i64_const(n),
174                        Offset::Global(g) => ConstExpr::global_get(g),
175                    };
176                    elems.active(*table, &offset, elements);
177                }
178                ElementKind::Passive => {
179                    elems.passive(elements);
180                }
181                ElementKind::Declared => {
182                    elems.declared(elements);
183                }
184            }
185        }
186        module.section(&elems);
187    }
188
189    fn encode_data_count(&self, module: &mut wasm_encoder::Module) {
190        // Without bulk memory there's no need for a data count section,
191        if !self.config.bulk_memory_enabled {
192            return;
193        }
194        // ... and also if there's no data no need for a data count section.
195        if self.data.is_empty() {
196            return;
197        }
198        module.section(&wasm_encoder::DataCountSection {
199            count: u32::try_from(self.data.len()).unwrap(),
200        });
201    }
202
203    fn encode_code(&self, module: &mut wasm_encoder::Module) {
204        if self.code.is_empty() {
205            return;
206        }
207        let mut code = wasm_encoder::CodeSection::new();
208        for c in &self.code {
209            // Skip the run-length encoding because it is a little
210            // annoying to compute; use a length of one for every local.
211            let mut func = wasm_encoder::Function::new(c.locals.iter().map(|l| (1, *l)));
212            match &c.instructions {
213                Instructions::Generated(instrs) => {
214                    for instr in instrs {
215                        func.instruction(instr);
216                    }
217                    func.instructions().end();
218                }
219                Instructions::Arbitrary(body) => {
220                    func.raw(body.iter().copied());
221                }
222            }
223            code.function(&func);
224        }
225        module.section(&code);
226    }
227
228    fn encode_data(&self, module: &mut wasm_encoder::Module) {
229        if self.data.is_empty() {
230            return;
231        }
232        let mut data = wasm_encoder::DataSection::new();
233        for seg in &self.data {
234            match &seg.kind {
235                DataSegmentKind::Active {
236                    memory_index,
237                    offset,
238                } => {
239                    let offset = match *offset {
240                        Offset::Const32(n) => ConstExpr::i32_const(n),
241                        Offset::Const64(n) => ConstExpr::i64_const(n),
242                        Offset::Global(g) => ConstExpr::global_get(g),
243                    };
244                    data.active(*memory_index, &offset, seg.init.iter().copied());
245                }
246                DataSegmentKind::Passive => {
247                    data.passive(seg.init.iter().copied());
248                }
249            }
250        }
251        module.section(&data);
252    }
253}
254
255pub(crate) fn translate_entity_type(ty: &EntityType) -> wasm_encoder::EntityType {
256    match ty {
257        EntityType::Tag(t) => wasm_encoder::EntityType::Tag(wasm_encoder::TagType {
258            kind: wasm_encoder::TagKind::Exception,
259            func_type_idx: t.func_type_idx,
260        }),
261        EntityType::Func(f, _) => wasm_encoder::EntityType::Function(*f),
262        EntityType::Table(ty) => (*ty).into(),
263        EntityType::Memory(m) => (*m).into(),
264        EntityType::Global(g) => (*g).into(),
265    }
266}