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