wasm_smith/core/
encode.rs1use super::*;
2
3impl Module {
4 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(§ion);
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 group in &self.imports {
65 match group {
66 crate::core::Imports::Single(im) => {
67 section.imports(wasm_encoder::Imports::Single(wasm_encoder::Import {
68 module: &im.module,
69 name: &im.name,
70 ty: translate_entity_type(&im.entity_type),
71 }));
72 }
73 crate::core::Imports::Compact1 { module, items } => {
74 section.imports(wasm_encoder::Imports::Compact1 {
75 module,
76 items: items
77 .iter()
78 .map(|im| wasm_encoder::ImportCompact {
79 name: &im.name,
80 ty: translate_entity_type(&im.entity_type),
81 })
82 .collect(),
83 });
84 }
85 crate::core::Imports::Compact2 {
86 module,
87 entity_type,
88 names,
89 } => {
90 section.imports(wasm_encoder::Imports::Compact2 {
91 module,
92 ty: translate_entity_type(entity_type),
93 names: names.iter().map(String::as_str).collect(),
94 });
95 }
96 }
97 }
98 module.section(§ion);
99 }
100
101 fn encode_tags(&self, module: &mut wasm_encoder::Module) {
102 if self.num_defined_tags == 0 {
103 return;
104 }
105 let mut tags = wasm_encoder::TagSection::new();
106 for tag in self.tags[self.tags.len() - self.num_defined_tags..].iter() {
107 tags.tag(wasm_encoder::TagType {
108 kind: wasm_encoder::TagKind::Exception,
109 func_type_idx: tag.func_type_idx,
110 });
111 }
112 module.section(&tags);
113 }
114
115 fn encode_funcs(&self, module: &mut wasm_encoder::Module) {
116 if self.num_defined_funcs == 0 {
117 return;
118 }
119 let mut funcs = wasm_encoder::FunctionSection::new();
120 for (ty, _) in self.funcs[self.funcs.len() - self.num_defined_funcs..].iter() {
121 funcs.function(*ty);
122 }
123 module.section(&funcs);
124 }
125
126 fn encode_tables(&self, module: &mut wasm_encoder::Module) {
127 if self.defined_tables.is_empty() {
128 return;
129 }
130 let mut tables = wasm_encoder::TableSection::new();
131 for (t, init) in self.tables[self.tables.len() - self.defined_tables.len()..]
132 .iter()
133 .zip(&self.defined_tables)
134 {
135 match init {
136 Some(init) => {
137 tables.table_with_init(*t, init);
138 }
139 None => {
140 tables.table(*t);
141 }
142 }
143 }
144 module.section(&tables);
145 }
146
147 fn encode_memories(&self, module: &mut wasm_encoder::Module) {
148 if self.num_defined_memories == 0 {
149 return;
150 }
151 let mut mems = wasm_encoder::MemorySection::new();
152 for m in self.memories[self.memories.len() - self.num_defined_memories..].iter() {
153 mems.memory(*m);
154 }
155 module.section(&mems);
156 }
157
158 fn encode_globals(&self, module: &mut wasm_encoder::Module) {
159 if self.globals.is_empty() {
160 return;
161 }
162 let mut globals = wasm_encoder::GlobalSection::new();
163 for (idx, expr) in &self.defined_globals {
164 let ty = &self.globals[*idx as usize];
165 globals.global(*ty, expr);
166 }
167 module.section(&globals);
168 }
169
170 fn encode_exports(&self, module: &mut wasm_encoder::Module) {
171 if self.exports.is_empty() {
172 return;
173 }
174 let mut exports = wasm_encoder::ExportSection::new();
175 for (name, kind, idx) in &self.exports {
176 exports.export(name, *kind, *idx);
177 }
178 module.section(&exports);
179 }
180
181 fn encode_start(&self, module: &mut wasm_encoder::Module) {
182 if let Some(f) = self.start {
183 module.section(&wasm_encoder::StartSection { function_index: f });
184 }
185 }
186
187 fn encode_elems(&self, module: &mut wasm_encoder::Module) {
188 if self.elems.is_empty() {
189 return;
190 }
191 let mut elems = wasm_encoder::ElementSection::new();
192 for el in &self.elems {
193 let elements = match &el.items {
194 Elements::Expressions(es) => wasm_encoder::Elements::Expressions(el.ty, es.into()),
195 Elements::Functions(fs) => {
196 assert_eq!(el.ty, RefType::FUNCREF);
197 wasm_encoder::Elements::Functions(fs.into())
198 }
199 };
200 match &el.kind {
201 ElementKind::Active { table, offset } => {
202 let offset = match *offset {
203 Offset::Const32(n) => ConstExpr::i32_const(n),
204 Offset::Const64(n) => ConstExpr::i64_const(n),
205 Offset::Global(g) => ConstExpr::global_get(g),
206 };
207 elems.active(*table, &offset, elements);
208 }
209 ElementKind::Passive => {
210 elems.passive(elements);
211 }
212 ElementKind::Declared => {
213 elems.declared(elements);
214 }
215 }
216 }
217 module.section(&elems);
218 }
219
220 fn encode_data_count(&self, module: &mut wasm_encoder::Module) {
221 if !self.config.bulk_memory_enabled {
223 return;
224 }
225 if self.data.is_empty() {
227 return;
228 }
229 module.section(&wasm_encoder::DataCountSection {
230 count: u32::try_from(self.data.len()).unwrap(),
231 });
232 }
233
234 fn encode_code(&self, module: &mut wasm_encoder::Module) {
235 if self.code.is_empty() {
236 return;
237 }
238 let mut code = wasm_encoder::CodeSection::new();
239 for c in &self.code {
240 let mut func = wasm_encoder::Function::new(c.locals.iter().map(|l| (1, *l)));
243 match &c.instructions {
244 Instructions::Generated(instrs) => {
245 for instr in instrs {
246 func.instruction(instr);
247 }
248 func.instructions().end();
249 }
250 Instructions::Arbitrary(body) => {
251 func.raw(body.iter().copied());
252 }
253 }
254 code.function(&func);
255 }
256 module.section(&code);
257 }
258
259 fn encode_data(&self, module: &mut wasm_encoder::Module) {
260 if self.data.is_empty() {
261 return;
262 }
263 let mut data = wasm_encoder::DataSection::new();
264 for seg in &self.data {
265 match &seg.kind {
266 DataSegmentKind::Active {
267 memory_index,
268 offset,
269 } => {
270 let offset = match *offset {
271 Offset::Const32(n) => ConstExpr::i32_const(n),
272 Offset::Const64(n) => ConstExpr::i64_const(n),
273 Offset::Global(g) => ConstExpr::global_get(g),
274 };
275 data.active(*memory_index, &offset, seg.init.iter().copied());
276 }
277 DataSegmentKind::Passive => {
278 data.passive(seg.init.iter().copied());
279 }
280 }
281 }
282 module.section(&data);
283 }
284}
285
286pub(crate) fn translate_entity_type(ty: &EntityType) -> wasm_encoder::EntityType {
287 match ty {
288 EntityType::Tag(t) => wasm_encoder::EntityType::Tag(wasm_encoder::TagType {
289 kind: wasm_encoder::TagKind::Exception,
290 func_type_idx: t.func_type_idx,
291 }),
292 EntityType::Func(f, _) => wasm_encoder::EntityType::Function(*f),
293 EntityType::Table(ty) => (*ty).into(),
294 EntityType::Memory(m) => (*m).into(),
295 EntityType::Global(g) => (*g).into(),
296 }
297}