1 | #[cfg (feature = "component-model" )] |
2 | use crate::component::Component; |
3 | use crate::core::*; |
4 | use crate::encode::Encode; |
5 | use crate::token::*; |
6 | use crate::Wat; |
7 | use std::borrow::Cow; |
8 | use std::marker; |
9 | #[cfg (feature = "dwarf" )] |
10 | use std::path::Path; |
11 | |
12 | /// Options that can be specified when encoding a component or a module to |
13 | /// customize what the final binary looks like. |
14 | /// |
15 | /// Methods such as [`Module::encode`], [`Wat::encode`], and |
16 | /// [`Component::encode`] will use the default options. |
17 | #[derive (Default)] |
18 | pub struct EncodeOptions<'a> { |
19 | #[cfg (feature = "dwarf" )] |
20 | dwarf_info: Option<(&'a Path, &'a str, GenerateDwarf)>, |
21 | |
22 | _marker: marker::PhantomData<&'a str>, |
23 | } |
24 | |
25 | #[cfg (feature = "dwarf" )] |
26 | mod dwarf; |
27 | |
28 | #[cfg (not(feature = "dwarf" ))] |
29 | mod dwarf_disabled; |
30 | #[cfg (not(feature = "dwarf" ))] |
31 | use self::dwarf_disabled as dwarf; |
32 | |
33 | /// Configuration of how DWARF debugging information may be generated. |
34 | #[derive (Copy, Clone, Debug)] |
35 | #[non_exhaustive ] |
36 | pub enum GenerateDwarf { |
37 | /// Only generate line tables to map binary offsets back to source |
38 | /// locations. |
39 | Lines, |
40 | |
41 | /// Generate full debugging information for both line numbers and |
42 | /// variables/locals/operands. |
43 | Full, |
44 | } |
45 | |
46 | impl<'a> EncodeOptions<'a> { |
47 | /// Creates a new set of default encoding options. |
48 | pub fn new() -> EncodeOptions<'a> { |
49 | EncodeOptions::default() |
50 | } |
51 | |
52 | /// Enables emission of DWARF debugging information in the final binary. |
53 | /// |
54 | /// This method will use the `file` specified as the source file for the |
55 | /// `*.wat` file whose `contents` must also be supplied here. These are |
56 | /// used to calculate filenames/line numbers and are referenced from the |
57 | /// generated DWARF. |
58 | #[cfg (feature = "dwarf" )] |
59 | pub fn dwarf(&mut self, file: &'a Path, contents: &'a str, style: GenerateDwarf) -> &mut Self { |
60 | self.dwarf_info = Some((file, contents, style)); |
61 | self |
62 | } |
63 | |
64 | /// Encodes the given [`Module`] with these options. |
65 | /// |
66 | /// For more information see [`Module::encode`]. |
67 | pub fn encode_module( |
68 | &self, |
69 | module: &mut Module<'_>, |
70 | ) -> std::result::Result<Vec<u8>, crate::Error> { |
71 | module.resolve()?; |
72 | Ok(match &module.kind { |
73 | ModuleKind::Text(fields) => encode(&module.id, &module.name, fields, self), |
74 | ModuleKind::Binary(blobs) => blobs.iter().flat_map(|b| b.iter().cloned()).collect(), |
75 | }) |
76 | } |
77 | |
78 | /// Encodes the given [`Component`] with these options. |
79 | /// |
80 | /// For more information see [`Component::encode`]. |
81 | #[cfg (feature = "component-model" )] |
82 | pub fn encode_component( |
83 | &self, |
84 | component: &mut Component<'_>, |
85 | ) -> std::result::Result<Vec<u8>, crate::Error> { |
86 | component.resolve()?; |
87 | Ok(crate::component::binary::encode(component, self)) |
88 | } |
89 | |
90 | /// Encodes the given [`Wat`] with these options. |
91 | /// |
92 | /// For more information see [`Wat::encode`]. |
93 | pub fn encode_wat(&self, wat: &mut Wat<'_>) -> std::result::Result<Vec<u8>, crate::Error> { |
94 | match wat { |
95 | Wat::Module(m) => self.encode_module(m), |
96 | #[cfg (feature = "component-model" )] |
97 | Wat::Component(c) => self.encode_component(c), |
98 | #[cfg (not(feature = "component-model" ))] |
99 | Wat::Component(_) => unreachable!(), |
100 | } |
101 | } |
102 | } |
103 | |
104 | pub(crate) fn encode( |
105 | module_id: &Option<Id<'_>>, |
106 | module_name: &Option<NameAnnotation<'_>>, |
107 | fields: &[ModuleField<'_>], |
108 | opts: &EncodeOptions, |
109 | ) -> Vec<u8> { |
110 | use CustomPlace::*; |
111 | use CustomPlaceAnchor::*; |
112 | |
113 | let mut types = Vec::new(); |
114 | let mut imports = Vec::new(); |
115 | let mut funcs = Vec::new(); |
116 | let mut tables = Vec::new(); |
117 | let mut memories = Vec::new(); |
118 | let mut globals = Vec::new(); |
119 | let mut exports = Vec::new(); |
120 | let mut start = Vec::new(); |
121 | let mut elem = Vec::new(); |
122 | let mut data = Vec::new(); |
123 | let mut tags = Vec::new(); |
124 | let mut customs = Vec::new(); |
125 | for field in fields { |
126 | match field { |
127 | ModuleField::Type(i) => types.push(RecOrType::Type(i)), |
128 | ModuleField::Rec(i) => types.push(RecOrType::Rec(i)), |
129 | ModuleField::Import(i) => imports.push(i), |
130 | ModuleField::Func(i) => funcs.push(i), |
131 | ModuleField::Table(i) => tables.push(i), |
132 | ModuleField::Memory(i) => memories.push(i), |
133 | ModuleField::Global(i) => globals.push(i), |
134 | ModuleField::Export(i) => exports.push(i), |
135 | ModuleField::Start(i) => start.push(i), |
136 | ModuleField::Elem(i) => elem.push(i), |
137 | ModuleField::Data(i) => data.push(i), |
138 | ModuleField::Tag(i) => tags.push(i), |
139 | ModuleField::Custom(i) => customs.push(i), |
140 | } |
141 | } |
142 | |
143 | let mut e = Encoder { |
144 | wasm: wasm_encoder::Module::new(), |
145 | customs: &customs, |
146 | }; |
147 | |
148 | e.custom_sections(BeforeFirst); |
149 | |
150 | e.typed_section(&types); |
151 | e.typed_section(&imports); |
152 | |
153 | let functys = funcs |
154 | .iter() |
155 | .map(|f| FuncSectionTy(&f.ty)) |
156 | .collect::<Vec<_>>(); |
157 | e.typed_section(&functys); |
158 | e.typed_section(&tables); |
159 | e.typed_section(&memories); |
160 | e.typed_section(&tags); |
161 | e.typed_section(&globals); |
162 | e.typed_section(&exports); |
163 | e.custom_sections(Before(Start)); |
164 | if let Some(start) = start.get(0) { |
165 | e.wasm.section(&wasm_encoder::StartSection { |
166 | function_index: start.unwrap_u32(), |
167 | }); |
168 | } |
169 | e.custom_sections(After(Start)); |
170 | e.typed_section(&elem); |
171 | if needs_data_count(&funcs) { |
172 | e.wasm.section(&wasm_encoder::DataCountSection { |
173 | count: data.len().try_into().unwrap(), |
174 | }); |
175 | } |
176 | |
177 | // Prepare to and emit the code section. This is where DWARF may optionally |
178 | // be emitted depending on configuration settings. Note that `code_section` |
179 | // will internally emit the branch hints section if necessary. |
180 | let names = find_names(module_id, module_name, fields); |
181 | let num_import_funcs = imports |
182 | .iter() |
183 | .filter(|i| matches!(i.item.kind, ItemKind::Func(..))) |
184 | .count() as u32; |
185 | let mut dwarf = dwarf::Dwarf::new(num_import_funcs, opts, &names, &types); |
186 | e.code_section(&funcs, num_import_funcs, dwarf.as_mut()); |
187 | |
188 | e.typed_section(&data); |
189 | |
190 | if !names.is_empty() { |
191 | e.wasm.section(&names.to_name_section()); |
192 | } |
193 | e.custom_sections(AfterLast); |
194 | if let Some(dwarf) = &mut dwarf { |
195 | dwarf.emit(&mut e); |
196 | } |
197 | |
198 | return e.wasm.finish(); |
199 | |
200 | fn needs_data_count(funcs: &[&crate::core::Func<'_>]) -> bool { |
201 | funcs |
202 | .iter() |
203 | .filter_map(|f| match &f.kind { |
204 | FuncKind::Inline { expression, .. } => Some(expression), |
205 | _ => None, |
206 | }) |
207 | .flat_map(|e| e.instrs.iter()) |
208 | .any(|i| i.needs_data_count()) |
209 | } |
210 | } |
211 | |
212 | struct Encoder<'a> { |
213 | wasm: wasm_encoder::Module, |
214 | customs: &'a [&'a Custom<'a>], |
215 | } |
216 | |
217 | impl Encoder<'_> { |
218 | fn custom_sections(&mut self, place: CustomPlace) { |
219 | for entry in self.customs.iter() { |
220 | if entry.place() == place { |
221 | entry.encode(&mut self.wasm); |
222 | } |
223 | } |
224 | } |
225 | |
226 | fn typed_section<T>(&mut self, list: &[T]) |
227 | where |
228 | T: SectionItem, |
229 | { |
230 | self.custom_sections(CustomPlace::Before(T::ANCHOR)); |
231 | if !list.is_empty() { |
232 | let mut section = T::Section::default(); |
233 | for item in list { |
234 | item.encode(&mut section); |
235 | } |
236 | self.wasm.section(§ion); |
237 | } |
238 | self.custom_sections(CustomPlace::After(T::ANCHOR)); |
239 | } |
240 | |
241 | /// Encodes the code section of a wasm module module while additionally |
242 | /// handling the branch hinting proposal. |
243 | /// |
244 | /// The branch hinting proposal requires to encode the offsets of the |
245 | /// instructions relative from the beginning of the function. Here we encode |
246 | /// each instruction and we save its offset. If needed, we use this |
247 | /// information to build the branch hint section and insert it before the |
248 | /// code section. |
249 | /// |
250 | /// The `list` provided is the list of functions that are emitted into the |
251 | /// code section. The `func_index` provided is the initial index of defined |
252 | /// functions, so it's the count of imported functions. The `dwarf` field is |
253 | /// optionally used to track debugging information. |
254 | fn code_section<'a>( |
255 | &'a mut self, |
256 | list: &[&'a Func<'_>], |
257 | mut func_index: u32, |
258 | mut dwarf: Option<&mut dwarf::Dwarf>, |
259 | ) { |
260 | self.custom_sections(CustomPlace::Before(CustomPlaceAnchor::Code)); |
261 | |
262 | if !list.is_empty() { |
263 | let mut branch_hints = wasm_encoder::BranchHints::new(); |
264 | let mut code_section = wasm_encoder::CodeSection::new(); |
265 | |
266 | for func in list.iter() { |
267 | let hints = func.encode(&mut code_section, dwarf.as_deref_mut()); |
268 | if !hints.is_empty() { |
269 | branch_hints.function_hints(func_index, hints.into_iter()); |
270 | } |
271 | func_index += 1; |
272 | } |
273 | |
274 | // Branch hints section has to be inserted before the Code section |
275 | // Insert the section only if we have some hints |
276 | if !branch_hints.is_empty() { |
277 | self.wasm.section(&branch_hints); |
278 | } |
279 | |
280 | // Finally, insert the Code section from the tmp buffer |
281 | self.wasm.section(&code_section); |
282 | |
283 | if let Some(dwarf) = &mut dwarf { |
284 | dwarf.set_code_section_size(code_section.byte_len()); |
285 | } |
286 | } |
287 | self.custom_sections(CustomPlace::After(CustomPlaceAnchor::Code)); |
288 | } |
289 | } |
290 | |
291 | trait SectionItem { |
292 | type Section: wasm_encoder::Section + Default; |
293 | const ANCHOR: CustomPlaceAnchor; |
294 | |
295 | fn encode(&self, section: &mut Self::Section); |
296 | } |
297 | |
298 | impl<T> SectionItem for &T |
299 | where |
300 | T: SectionItem, |
301 | { |
302 | type Section = T::Section; |
303 | const ANCHOR: CustomPlaceAnchor = T::ANCHOR; |
304 | |
305 | fn encode(&self, section: &mut Self::Section) { |
306 | T::encode(self, section) |
307 | } |
308 | } |
309 | |
310 | impl From<&FunctionType<'_>> for wasm_encoder::FuncType { |
311 | fn from(ft: &FunctionType) -> Self { |
312 | wasm_encoder::FuncType::new( |
313 | params:ft.params.iter().map(|(_, _, ty)| (*ty).into()), |
314 | results:ft.results.iter().map(|ty: &ValType<'_>| (*ty).into()), |
315 | ) |
316 | } |
317 | } |
318 | |
319 | impl From<&StructType<'_>> for wasm_encoder::StructType { |
320 | fn from(st: &StructType) -> wasm_encoder::StructType { |
321 | wasm_encoder::StructType { |
322 | fields: st.fields.iter().map(|f: &StructField<'_>| f.into()).collect(), |
323 | } |
324 | } |
325 | } |
326 | |
327 | impl From<&StructField<'_>> for wasm_encoder::FieldType { |
328 | fn from(f: &StructField) -> wasm_encoder::FieldType { |
329 | wasm_encoder::FieldType { |
330 | element_type: f.ty.into(), |
331 | mutable: f.mutable, |
332 | } |
333 | } |
334 | } |
335 | |
336 | impl From<&ArrayType<'_>> for wasm_encoder::ArrayType { |
337 | fn from(at: &ArrayType) -> Self { |
338 | let field: FieldType = wasm_encoder::FieldType { |
339 | element_type: at.ty.into(), |
340 | mutable: at.mutable, |
341 | }; |
342 | wasm_encoder::ArrayType(field) |
343 | } |
344 | } |
345 | |
346 | impl From<&ContType<'_>> for wasm_encoder::ContType { |
347 | fn from(at: &ContType) -> Self { |
348 | wasm_encoder::ContType(at.0.into()) |
349 | } |
350 | } |
351 | |
352 | enum RecOrType<'a> { |
353 | Type(&'a Type<'a>), |
354 | Rec(&'a Rec<'a>), |
355 | } |
356 | |
357 | impl SectionItem for RecOrType<'_> { |
358 | type Section = wasm_encoder::TypeSection; |
359 | const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Type; |
360 | |
361 | fn encode(&self, types: &mut wasm_encoder::TypeSection) { |
362 | match self { |
363 | RecOrType::Type(ty: &&Type<'_>) => types.ty().subtype(&ty.to_subtype()), |
364 | RecOrType::Rec(rec: &&Rec<'_>) => types.ty().rec(types:rec.types.iter().map(|t: &Type<'_>| t.to_subtype())), |
365 | } |
366 | } |
367 | } |
368 | |
369 | impl Type<'_> { |
370 | pub(crate) fn to_subtype(&self) -> wasm_encoder::SubType { |
371 | self.def.to_subtype() |
372 | } |
373 | } |
374 | |
375 | impl TypeDef<'_> { |
376 | pub(crate) fn to_subtype(&self) -> wasm_encoder::SubType { |
377 | use wasm_encoder::CompositeInnerType::*; |
378 | let composite_type: CompositeType = wasm_encoder::CompositeType { |
379 | inner: match &self.kind { |
380 | InnerTypeKind::Func(ft: &FunctionType<'_>) => Func(ft.into()), |
381 | InnerTypeKind::Struct(st: &StructType<'_>) => Struct(st.into()), |
382 | InnerTypeKind::Array(at: &ArrayType<'_>) => Array(at.into()), |
383 | InnerTypeKind::Cont(ct: &ContType<'_>) => Cont(ct.into()), |
384 | }, |
385 | shared: self.shared, |
386 | }; |
387 | wasm_encoder::SubType { |
388 | composite_type, |
389 | is_final: self.final_type.unwrap_or(default:true), |
390 | supertype_idx: self.parent.map(|i: Index<'_>| i.unwrap_u32()), |
391 | } |
392 | } |
393 | } |
394 | |
395 | impl From<ValType<'_>> for wasm_encoder::ValType { |
396 | fn from(ty: ValType) -> Self { |
397 | match ty { |
398 | ValType::I32 => Self::I32, |
399 | ValType::I64 => Self::I64, |
400 | ValType::F32 => Self::F32, |
401 | ValType::F64 => Self::F64, |
402 | ValType::V128 => Self::V128, |
403 | ValType::Ref(r: RefType<'_>) => Self::Ref(r.into()), |
404 | } |
405 | } |
406 | } |
407 | |
408 | impl From<RefType<'_>> for wasm_encoder::RefType { |
409 | fn from(r: RefType<'_>) -> Self { |
410 | wasm_encoder::RefType { |
411 | nullable: r.nullable, |
412 | heap_type: r.heap.into(), |
413 | } |
414 | } |
415 | } |
416 | |
417 | impl From<HeapType<'_>> for wasm_encoder::HeapType { |
418 | fn from(r: HeapType<'_>) -> Self { |
419 | use wasm_encoder::AbstractHeapType::*; |
420 | match r { |
421 | HeapType::Abstract { shared, ty } => { |
422 | let ty = match ty { |
423 | AbstractHeapType::Func => Func, |
424 | AbstractHeapType::Extern => Extern, |
425 | AbstractHeapType::Exn => Exn, |
426 | AbstractHeapType::NoExn => NoExn, |
427 | AbstractHeapType::Any => Any, |
428 | AbstractHeapType::Eq => Eq, |
429 | AbstractHeapType::Struct => Struct, |
430 | AbstractHeapType::Array => Array, |
431 | AbstractHeapType::NoFunc => NoFunc, |
432 | AbstractHeapType::NoExtern => NoExtern, |
433 | AbstractHeapType::None => None, |
434 | AbstractHeapType::I31 => I31, |
435 | AbstractHeapType::Cont => Cont, |
436 | AbstractHeapType::NoCont => NoCont, |
437 | }; |
438 | Self::Abstract { shared, ty } |
439 | } |
440 | HeapType::Concrete(i) => Self::Concrete(i.unwrap_u32()), |
441 | } |
442 | } |
443 | } |
444 | |
445 | impl Encode for Option<Id<'_>> { |
446 | fn encode(&self, _e: &mut Vec<u8>) { |
447 | // used for parameters in the tuple impl as well as instruction labels |
448 | } |
449 | } |
450 | |
451 | impl<'a> Encode for ValType<'a> { |
452 | fn encode(&self, e: &mut Vec<u8>) { |
453 | wasm_encoder::Encode::encode(&wasm_encoder::ValType::from(*self), sink:e) |
454 | } |
455 | } |
456 | |
457 | impl<'a> Encode for HeapType<'a> { |
458 | fn encode(&self, e: &mut Vec<u8>) { |
459 | wasm_encoder::Encode::encode(&wasm_encoder::HeapType::from(*self), sink:e) |
460 | } |
461 | } |
462 | |
463 | impl From<StorageType<'_>> for wasm_encoder::StorageType { |
464 | fn from(st: StorageType) -> Self { |
465 | use wasm_encoder::StorageType::*; |
466 | match st { |
467 | StorageType::I8 => I8, |
468 | StorageType::I16 => I16, |
469 | StorageType::Val(vt: ValType<'_>) => Val(vt.into()), |
470 | } |
471 | } |
472 | } |
473 | |
474 | impl SectionItem for Import<'_> { |
475 | type Section = wasm_encoder::ImportSection; |
476 | const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Import; |
477 | |
478 | fn encode(&self, section: &mut wasm_encoder::ImportSection) { |
479 | section.import(self.module, self.field, self.item.to_entity_type()); |
480 | } |
481 | } |
482 | |
483 | impl ItemSig<'_> { |
484 | pub(crate) fn to_entity_type(&self) -> wasm_encoder::EntityType { |
485 | self.kind.to_entity_type() |
486 | } |
487 | } |
488 | |
489 | impl ItemKind<'_> { |
490 | fn to_entity_type(&self) -> wasm_encoder::EntityType { |
491 | use wasm_encoder::EntityType as ET; |
492 | match self { |
493 | ItemKind::Func(t: &TypeUse<'_, FunctionType<'_>>) => ET::Function(t.unwrap_u32()), |
494 | ItemKind::Table(t: &TableType<'_>) => ET::Table(t.to_table_type()), |
495 | ItemKind::Memory(t: &MemoryType) => ET::Memory(t.to_memory_type()), |
496 | ItemKind::Global(t: &GlobalType<'_>) => ET::Global(t.to_global_type()), |
497 | ItemKind::Tag(t: &TagType<'_>) => ET::Tag(t.to_tag_type()), |
498 | } |
499 | } |
500 | } |
501 | |
502 | impl TableType<'_> { |
503 | fn to_table_type(&self) -> wasm_encoder::TableType { |
504 | wasm_encoder::TableType { |
505 | element_type: self.elem.into(), |
506 | minimum: self.limits.min, |
507 | maximum: self.limits.max, |
508 | table64: self.limits.is64, |
509 | shared: self.shared, |
510 | } |
511 | } |
512 | } |
513 | |
514 | impl MemoryType { |
515 | fn to_memory_type(&self) -> wasm_encoder::MemoryType { |
516 | wasm_encoder::MemoryType { |
517 | minimum: self.limits.min, |
518 | maximum: self.limits.max, |
519 | memory64: self.limits.is64, |
520 | shared: self.shared, |
521 | page_size_log2: self.page_size_log2, |
522 | } |
523 | } |
524 | } |
525 | |
526 | impl GlobalType<'_> { |
527 | fn to_global_type(&self) -> wasm_encoder::GlobalType { |
528 | wasm_encoder::GlobalType { |
529 | val_type: self.ty.into(), |
530 | mutable: self.mutable, |
531 | shared: self.shared, |
532 | } |
533 | } |
534 | } |
535 | |
536 | impl TagType<'_> { |
537 | fn to_tag_type(&self) -> wasm_encoder::TagType { |
538 | match self { |
539 | TagType::Exception(r: &TypeUse<'_, FunctionType<'_>>) => wasm_encoder::TagType { |
540 | kind: wasm_encoder::TagKind::Exception, |
541 | func_type_idx: r.unwrap_u32(), |
542 | }, |
543 | } |
544 | } |
545 | } |
546 | |
547 | impl<T> TypeUse<'_, T> { |
548 | fn unwrap_u32(&self) -> u32 { |
549 | self.index |
550 | .as_ref() |
551 | .expect(msg:"TypeUse should be filled in by this point" ) |
552 | .unwrap_u32() |
553 | } |
554 | } |
555 | |
556 | struct FuncSectionTy<'a>(&'a TypeUse<'a, FunctionType<'a>>); |
557 | |
558 | impl SectionItem for FuncSectionTy<'_> { |
559 | type Section = wasm_encoder::FunctionSection; |
560 | const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Func; |
561 | |
562 | fn encode(&self, section: &mut wasm_encoder::FunctionSection) { |
563 | section.function(self.0.unwrap_u32()); |
564 | } |
565 | } |
566 | |
567 | impl Encode for Index<'_> { |
568 | fn encode(&self, e: &mut Vec<u8>) { |
569 | self.unwrap_u32().encode(e) |
570 | } |
571 | } |
572 | |
573 | impl Index<'_> { |
574 | fn unwrap_u32(&self) -> u32 { |
575 | match self { |
576 | Index::Num(n: &u32, _) => *n, |
577 | Index::Id(n: &Id<'_>) => panic!("unresolved index in emission: {:?}" , n), |
578 | } |
579 | } |
580 | } |
581 | |
582 | impl From<Index<'_>> for u32 { |
583 | fn from(i: Index<'_>) -> Self { |
584 | match i { |
585 | Index::Num(i: u32, _) => i, |
586 | Index::Id(_) => unreachable!("unresolved index in encoding: {:?}" , i), |
587 | } |
588 | } |
589 | } |
590 | |
591 | impl SectionItem for Table<'_> { |
592 | type Section = wasm_encoder::TableSection; |
593 | const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Table; |
594 | |
595 | fn encode(&self, section: &mut wasm_encoder::TableSection) { |
596 | assert!(self.exports.names.is_empty()); |
597 | match &self.kind { |
598 | TableKind::Normal { |
599 | ty: &TableType<'_>, |
600 | init_expr: None, |
601 | } => { |
602 | section.table(ty.to_table_type()); |
603 | } |
604 | TableKind::Normal { |
605 | ty: &TableType<'_>, |
606 | init_expr: Some(init_expr: &Expression<'_>), |
607 | } => { |
608 | section.table_with_init(ty.to_table_type(), &init_expr.to_const_expr()); |
609 | } |
610 | _ => panic!("TableKind should be normal during encoding" ), |
611 | } |
612 | } |
613 | } |
614 | |
615 | impl SectionItem for Memory<'_> { |
616 | type Section = wasm_encoder::MemorySection; |
617 | const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Memory; |
618 | |
619 | fn encode(&self, section: &mut wasm_encoder::MemorySection) { |
620 | assert!(self.exports.names.is_empty()); |
621 | match &self.kind { |
622 | MemoryKind::Normal(t: &MemoryType) => { |
623 | section.memory(t.to_memory_type()); |
624 | } |
625 | _ => panic!("MemoryKind should be normal during encoding" ), |
626 | } |
627 | } |
628 | } |
629 | |
630 | impl SectionItem for Global<'_> { |
631 | type Section = wasm_encoder::GlobalSection; |
632 | const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Global; |
633 | |
634 | fn encode(&self, section: &mut wasm_encoder::GlobalSection) { |
635 | assert!(self.exports.names.is_empty()); |
636 | let init: ConstExpr = match &self.kind { |
637 | GlobalKind::Inline(expr: &Expression<'_>) => expr.to_const_expr(), |
638 | _ => panic!("GlobalKind should be inline during encoding" ), |
639 | }; |
640 | section.global(self.ty.to_global_type(), &init); |
641 | } |
642 | } |
643 | |
644 | impl SectionItem for Export<'_> { |
645 | type Section = wasm_encoder::ExportSection; |
646 | const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Export; |
647 | |
648 | fn encode(&self, section: &mut wasm_encoder::ExportSection) { |
649 | section.export(self.name, self.kind.into(), self.item.unwrap_u32()); |
650 | } |
651 | } |
652 | |
653 | impl From<ExportKind> for wasm_encoder::ExportKind { |
654 | fn from(kind: ExportKind) -> Self { |
655 | match kind { |
656 | ExportKind::Func => Self::Func, |
657 | ExportKind::Table => Self::Table, |
658 | ExportKind::Memory => Self::Memory, |
659 | ExportKind::Global => Self::Global, |
660 | ExportKind::Tag => Self::Tag, |
661 | } |
662 | } |
663 | } |
664 | |
665 | impl SectionItem for Elem<'_> { |
666 | type Section = wasm_encoder::ElementSection; |
667 | const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Elem; |
668 | |
669 | fn encode(&self, section: &mut wasm_encoder::ElementSection) { |
670 | use wasm_encoder::Elements; |
671 | |
672 | let elements = match &self.payload { |
673 | ElemPayload::Indices(v) => { |
674 | Elements::Functions(Cow::Owned(v.iter().map(|i| i.unwrap_u32()).collect())) |
675 | } |
676 | ElemPayload::Exprs { exprs, ty } => Elements::Expressions( |
677 | (*ty).into(), |
678 | Cow::Owned(exprs.iter().map(|e| e.to_const_expr()).collect()), |
679 | ), |
680 | }; |
681 | match &self.kind { |
682 | ElemKind::Active { table, offset } => { |
683 | section.active( |
684 | table.map(|t| t.unwrap_u32()), |
685 | &offset.to_const_expr(), |
686 | elements, |
687 | ); |
688 | } |
689 | ElemKind::Passive => { |
690 | section.passive(elements); |
691 | } |
692 | ElemKind::Declared => { |
693 | section.declared(elements); |
694 | } |
695 | } |
696 | } |
697 | } |
698 | |
699 | impl SectionItem for Data<'_> { |
700 | type Section = wasm_encoder::DataSection; |
701 | const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Data; |
702 | |
703 | fn encode(&self, section: &mut wasm_encoder::DataSection) { |
704 | let mut data: Vec = Vec::new(); |
705 | for val: &DataVal<'_> in self.data.iter() { |
706 | val.push_onto(&mut data); |
707 | } |
708 | match &self.kind { |
709 | DataKind::Passive => { |
710 | section.passive(data); |
711 | } |
712 | DataKind::Active { memory: &Index<'_>, offset: &Expression<'_> } => { |
713 | section.active(memory_index:memory.unwrap_u32(), &offset.to_const_expr(), data); |
714 | } |
715 | } |
716 | } |
717 | } |
718 | |
719 | impl Func<'_> { |
720 | /// Encodes the function into `e` while returning all branch hints with |
721 | /// known relative offsets after encoding. |
722 | /// |
723 | /// The `dwarf` field is optional and used to track debugging information |
724 | /// for each instruction. |
725 | fn encode( |
726 | &self, |
727 | section: &mut wasm_encoder::CodeSection, |
728 | mut dwarf: Option<&mut dwarf::Dwarf>, |
729 | ) -> Vec<wasm_encoder::BranchHint> { |
730 | assert!(self.exports.names.is_empty()); |
731 | let (expr, locals) = match &self.kind { |
732 | FuncKind::Inline { expression, locals } => (expression, locals), |
733 | _ => panic!("should only have inline functions in emission" ), |
734 | }; |
735 | |
736 | if let Some(dwarf) = &mut dwarf { |
737 | let index = match self.ty.index.as_ref().unwrap() { |
738 | Index::Num(n, _) => *n, |
739 | _ => unreachable!(), |
740 | }; |
741 | dwarf.start_func(self.span, index, locals); |
742 | } |
743 | |
744 | // Encode the function into a temporary vector because functions are |
745 | // prefixed with their length. The temporary vector, when encoded, |
746 | // encodes its length first then the body. |
747 | let mut func = |
748 | wasm_encoder::Function::new_with_locals_types(locals.iter().map(|t| t.ty.into())); |
749 | let branch_hints = expr.encode(&mut func, dwarf.as_deref_mut()); |
750 | let func_size = func.byte_len(); |
751 | section.function(&func); |
752 | |
753 | if let Some(dwarf) = &mut dwarf { |
754 | dwarf.end_func(func_size, section.byte_len()); |
755 | } |
756 | |
757 | branch_hints |
758 | } |
759 | } |
760 | |
761 | impl Expression<'_> { |
762 | /// Encodes this expression into `e` and optionally tracks debugging |
763 | /// information for each instruction in `dwarf`. |
764 | /// |
765 | /// Returns all branch hints, if any, found while parsing this function. |
766 | fn encode( |
767 | &self, |
768 | func: &mut wasm_encoder::Function, |
769 | mut dwarf: Option<&mut dwarf::Dwarf>, |
770 | ) -> Vec<wasm_encoder::BranchHint> { |
771 | let mut hints = Vec::with_capacity(self.branch_hints.len()); |
772 | let mut next_hint = self.branch_hints.iter().peekable(); |
773 | let mut tmp = Vec::new(); |
774 | |
775 | for (i, instr) in self.instrs.iter().enumerate() { |
776 | // Branch hints are stored in order of increasing `instr_index` so |
777 | // check to see if the next branch hint matches this instruction's |
778 | // index. |
779 | if let Some(hint) = next_hint.next_if(|h| h.instr_index == i) { |
780 | hints.push(wasm_encoder::BranchHint { |
781 | branch_func_offset: u32::try_from(func.byte_len() + tmp.len()).unwrap(), |
782 | branch_hint_value: hint.value, |
783 | }); |
784 | } |
785 | |
786 | // If DWARF is enabled then track this instruction's binary offset |
787 | // and source location. |
788 | if let Some(dwarf) = &mut dwarf { |
789 | if let Some(span) = self.instr_spans.as_ref().map(|s| s[i]) { |
790 | dwarf.instr(func.byte_len() + tmp.len(), span); |
791 | } |
792 | } |
793 | |
794 | // Finally emit the instruction and move to the next. |
795 | instr.encode(&mut tmp); |
796 | } |
797 | func.raw(tmp.iter().copied()); |
798 | func.instruction(&wasm_encoder::Instruction::End); |
799 | |
800 | hints |
801 | } |
802 | |
803 | fn to_const_expr(&self) -> wasm_encoder::ConstExpr { |
804 | let mut tmp = Vec::new(); |
805 | for instr in self.instrs.iter() { |
806 | instr.encode(&mut tmp); |
807 | } |
808 | wasm_encoder::ConstExpr::raw(tmp) |
809 | } |
810 | } |
811 | |
812 | impl Encode for BlockType<'_> { |
813 | fn encode(&self, e: &mut Vec<u8>) { |
814 | // block types using an index are encoded as an sleb, not a uleb |
815 | if let Some(Index::Num(n: &u32, _)) = &self.ty.index { |
816 | return i64::from(*n).encode(e); |
817 | } |
818 | let ty: &FunctionType<'_> = self |
819 | .ty |
820 | .inline |
821 | .as_ref() |
822 | .expect(msg:"function type not filled in" ); |
823 | if ty.params.is_empty() && ty.results.is_empty() { |
824 | return e.push(0x40); |
825 | } |
826 | if ty.params.is_empty() && ty.results.len() == 1 { |
827 | return ty.results[0].encode(e); |
828 | } |
829 | panic!("multi-value block types should have an index" ); |
830 | } |
831 | } |
832 | |
833 | impl Encode for LaneArg { |
834 | fn encode(&self, e: &mut Vec<u8>) { |
835 | self.lane.encode(e); |
836 | } |
837 | } |
838 | |
839 | impl Encode for MemArg<'_> { |
840 | fn encode(&self, e: &mut Vec<u8>) { |
841 | match &self.memory { |
842 | Index::Num(0, _) => { |
843 | self.align.trailing_zeros().encode(e); |
844 | self.offset.encode(e); |
845 | } |
846 | _ => { |
847 | (self.align.trailing_zeros() | (1 << 6)).encode(e); |
848 | self.memory.encode(e); |
849 | self.offset.encode(e); |
850 | } |
851 | } |
852 | } |
853 | } |
854 | |
855 | impl Encode for Ordering { |
856 | fn encode(&self, buf: &mut Vec<u8>) { |
857 | let flag: u8 = match self { |
858 | Ordering::SeqCst => 0, |
859 | Ordering::AcqRel => 1, |
860 | }; |
861 | flag.encode(buf); |
862 | } |
863 | } |
864 | |
865 | impl<T> Encode for Ordered<T> |
866 | where |
867 | T: Encode, |
868 | { |
869 | fn encode(&self, buf: &mut Vec<u8>) { |
870 | self.ordering.encode(buf); |
871 | self.inner.encode(buf); |
872 | } |
873 | } |
874 | |
875 | impl Encode for LoadOrStoreLane<'_> { |
876 | fn encode(&self, e: &mut Vec<u8>) { |
877 | self.memarg.encode(e); |
878 | self.lane.encode(e); |
879 | } |
880 | } |
881 | |
882 | impl Encode for CallIndirect<'_> { |
883 | fn encode(&self, e: &mut Vec<u8>) { |
884 | self.ty.unwrap_u32().encode(e); |
885 | self.table.encode(e); |
886 | } |
887 | } |
888 | |
889 | impl Encode for TableInit<'_> { |
890 | fn encode(&self, e: &mut Vec<u8>) { |
891 | self.elem.encode(e); |
892 | self.table.encode(e); |
893 | } |
894 | } |
895 | |
896 | impl Encode for TableCopy<'_> { |
897 | fn encode(&self, e: &mut Vec<u8>) { |
898 | self.dst.encode(e); |
899 | self.src.encode(e); |
900 | } |
901 | } |
902 | |
903 | impl Encode for TableArg<'_> { |
904 | fn encode(&self, e: &mut Vec<u8>) { |
905 | self.dst.encode(e); |
906 | } |
907 | } |
908 | |
909 | impl Encode for MemoryArg<'_> { |
910 | fn encode(&self, e: &mut Vec<u8>) { |
911 | self.mem.encode(e); |
912 | } |
913 | } |
914 | |
915 | impl Encode for MemoryInit<'_> { |
916 | fn encode(&self, e: &mut Vec<u8>) { |
917 | self.data.encode(e); |
918 | self.mem.encode(e); |
919 | } |
920 | } |
921 | |
922 | impl Encode for MemoryCopy<'_> { |
923 | fn encode(&self, e: &mut Vec<u8>) { |
924 | self.dst.encode(e); |
925 | self.src.encode(e); |
926 | } |
927 | } |
928 | |
929 | impl Encode for BrTableIndices<'_> { |
930 | fn encode(&self, e: &mut Vec<u8>) { |
931 | self.labels.encode(e); |
932 | self.default.encode(e); |
933 | } |
934 | } |
935 | |
936 | impl Encode for F32 { |
937 | fn encode(&self, e: &mut Vec<u8>) { |
938 | e.extend_from_slice(&self.bits.to_le_bytes()); |
939 | } |
940 | } |
941 | |
942 | impl Encode for F64 { |
943 | fn encode(&self, e: &mut Vec<u8>) { |
944 | e.extend_from_slice(&self.bits.to_le_bytes()); |
945 | } |
946 | } |
947 | |
948 | #[derive (Default)] |
949 | struct Names<'a> { |
950 | module: Option<&'a str>, |
951 | funcs: Vec<(u32, &'a str)>, |
952 | func_idx: u32, |
953 | locals: Vec<(u32, Vec<(u32, &'a str)>)>, |
954 | labels: Vec<(u32, Vec<(u32, &'a str)>)>, |
955 | globals: Vec<(u32, &'a str)>, |
956 | global_idx: u32, |
957 | memories: Vec<(u32, &'a str)>, |
958 | memory_idx: u32, |
959 | tables: Vec<(u32, &'a str)>, |
960 | table_idx: u32, |
961 | tags: Vec<(u32, &'a str)>, |
962 | tag_idx: u32, |
963 | types: Vec<(u32, &'a str)>, |
964 | type_idx: u32, |
965 | data: Vec<(u32, &'a str)>, |
966 | data_idx: u32, |
967 | elems: Vec<(u32, &'a str)>, |
968 | elem_idx: u32, |
969 | fields: Vec<(u32, Vec<(u32, &'a str)>)>, |
970 | } |
971 | |
972 | fn find_names<'a>( |
973 | module_id: &Option<Id<'a>>, |
974 | module_name: &Option<NameAnnotation<'a>>, |
975 | fields: &[ModuleField<'a>], |
976 | ) -> Names<'a> { |
977 | fn get_name<'a>(id: &Option<Id<'a>>, name: &Option<NameAnnotation<'a>>) -> Option<&'a str> { |
978 | name.as_ref().map(|n| n.name).or(id.and_then(|id| { |
979 | if id.is_gensym() { |
980 | None |
981 | } else { |
982 | Some(id.name()) |
983 | } |
984 | })) |
985 | } |
986 | |
987 | enum Name { |
988 | Type, |
989 | Global, |
990 | Func, |
991 | Memory, |
992 | Table, |
993 | Tag, |
994 | Elem, |
995 | Data, |
996 | } |
997 | |
998 | let mut ret = Names::default(); |
999 | ret.module = get_name(module_id, module_name); |
1000 | let mut names = Vec::new(); |
1001 | for field in fields { |
1002 | // Extract the kind/id/name from whatever kind of field this is... |
1003 | let (kind, id, name) = match field { |
1004 | ModuleField::Import(i) => ( |
1005 | match i.item.kind { |
1006 | ItemKind::Func(_) => Name::Func, |
1007 | ItemKind::Table(_) => Name::Table, |
1008 | ItemKind::Memory(_) => Name::Memory, |
1009 | ItemKind::Global(_) => Name::Global, |
1010 | ItemKind::Tag(_) => Name::Tag, |
1011 | }, |
1012 | &i.item.id, |
1013 | &i.item.name, |
1014 | ), |
1015 | ModuleField::Global(g) => (Name::Global, &g.id, &g.name), |
1016 | ModuleField::Table(t) => (Name::Table, &t.id, &t.name), |
1017 | ModuleField::Memory(m) => (Name::Memory, &m.id, &m.name), |
1018 | ModuleField::Tag(t) => (Name::Tag, &t.id, &t.name), |
1019 | ModuleField::Type(t) => (Name::Type, &t.id, &t.name), |
1020 | ModuleField::Rec(r) => { |
1021 | for ty in &r.types { |
1022 | names.push((Name::Type, &ty.id, &ty.name, field)); |
1023 | } |
1024 | continue; |
1025 | } |
1026 | ModuleField::Elem(e) => (Name::Elem, &e.id, &e.name), |
1027 | ModuleField::Data(d) => (Name::Data, &d.id, &d.name), |
1028 | ModuleField::Func(f) => (Name::Func, &f.id, &f.name), |
1029 | ModuleField::Export(_) | ModuleField::Start(_) | ModuleField::Custom(_) => continue, |
1030 | }; |
1031 | names.push((kind, id, name, field)); |
1032 | } |
1033 | |
1034 | for (kind, id, name, field) in names { |
1035 | // .. and using the kind we can figure out where to place this name |
1036 | let (list, idx) = match kind { |
1037 | Name::Func => (&mut ret.funcs, &mut ret.func_idx), |
1038 | Name::Table => (&mut ret.tables, &mut ret.table_idx), |
1039 | Name::Memory => (&mut ret.memories, &mut ret.memory_idx), |
1040 | Name::Global => (&mut ret.globals, &mut ret.global_idx), |
1041 | Name::Tag => (&mut ret.tags, &mut ret.tag_idx), |
1042 | Name::Type => (&mut ret.types, &mut ret.type_idx), |
1043 | Name::Elem => (&mut ret.elems, &mut ret.elem_idx), |
1044 | Name::Data => (&mut ret.data, &mut ret.data_idx), |
1045 | }; |
1046 | if let Some(name) = get_name(id, name) { |
1047 | list.push((*idx, name)); |
1048 | } |
1049 | |
1050 | // Handle module locals separately from above |
1051 | if let ModuleField::Func(f) = field { |
1052 | let mut local_names = Vec::new(); |
1053 | let mut label_names = Vec::new(); |
1054 | let mut local_idx = 0; |
1055 | let mut label_idx = 0; |
1056 | |
1057 | // Consult the inline type listed for local names of parameters. |
1058 | // This is specifically preserved during the name resolution |
1059 | // pass, but only for functions, so here we can look at the |
1060 | // original source's names. |
1061 | if let Some(ty) = &f.ty.inline { |
1062 | for (id, name, _) in ty.params.iter() { |
1063 | if let Some(name) = get_name(id, name) { |
1064 | local_names.push((local_idx, name)); |
1065 | } |
1066 | local_idx += 1; |
1067 | } |
1068 | } |
1069 | if let FuncKind::Inline { |
1070 | locals, expression, .. |
1071 | } = &f.kind |
1072 | { |
1073 | for local in locals.iter() { |
1074 | if let Some(name) = get_name(&local.id, &local.name) { |
1075 | local_names.push((local_idx, name)); |
1076 | } |
1077 | local_idx += 1; |
1078 | } |
1079 | |
1080 | for i in expression.instrs.iter() { |
1081 | match i { |
1082 | Instruction::If(block) |
1083 | | Instruction::Block(block) |
1084 | | Instruction::Loop(block) |
1085 | | Instruction::Try(block) |
1086 | | Instruction::TryTable(TryTable { block, .. }) => { |
1087 | if let Some(name) = get_name(&block.label, &block.label_name) { |
1088 | label_names.push((label_idx, name)); |
1089 | } |
1090 | label_idx += 1; |
1091 | } |
1092 | _ => {} |
1093 | } |
1094 | } |
1095 | } |
1096 | if local_names.len() > 0 { |
1097 | ret.locals.push((*idx, local_names)); |
1098 | } |
1099 | if label_names.len() > 0 { |
1100 | ret.labels.push((*idx, label_names)); |
1101 | } |
1102 | } |
1103 | |
1104 | // Handle struct fields separately from above |
1105 | if let ModuleField::Type(ty) = field { |
1106 | let mut field_names = vec![]; |
1107 | match &ty.def.kind { |
1108 | InnerTypeKind::Func(_) | InnerTypeKind::Array(_) | InnerTypeKind::Cont(_) => {} |
1109 | InnerTypeKind::Struct(ty_struct) => { |
1110 | for (idx, field) in ty_struct.fields.iter().enumerate() { |
1111 | if let Some(name) = get_name(&field.id, &None) { |
1112 | field_names.push((idx as u32, name)) |
1113 | } |
1114 | } |
1115 | } |
1116 | } |
1117 | if field_names.len() > 0 { |
1118 | ret.fields.push((*idx, field_names)) |
1119 | } |
1120 | } |
1121 | |
1122 | *idx += 1; |
1123 | } |
1124 | |
1125 | return ret; |
1126 | } |
1127 | |
1128 | impl Names<'_> { |
1129 | fn is_empty(&self) -> bool { |
1130 | self.module.is_none() |
1131 | && self.funcs.is_empty() |
1132 | && self.locals.is_empty() |
1133 | && self.labels.is_empty() |
1134 | && self.globals.is_empty() |
1135 | && self.memories.is_empty() |
1136 | && self.tables.is_empty() |
1137 | && self.types.is_empty() |
1138 | && self.elems.is_empty() |
1139 | && self.data.is_empty() |
1140 | && self.fields.is_empty() |
1141 | && self.tags.is_empty() |
1142 | } |
1143 | } |
1144 | |
1145 | impl Names<'_> { |
1146 | fn to_name_section(&self) -> wasm_encoder::NameSection { |
1147 | let mut names = wasm_encoder::NameSection::default(); |
1148 | |
1149 | if let Some(id) = self.module { |
1150 | names.module(id); |
1151 | } |
1152 | let name_map = |indices: &[(u32, &str)]| { |
1153 | if indices.is_empty() { |
1154 | return None; |
1155 | } |
1156 | let mut map = wasm_encoder::NameMap::default(); |
1157 | for (idx, name) in indices { |
1158 | map.append(*idx, *name); |
1159 | } |
1160 | Some(map) |
1161 | }; |
1162 | let indirect_name_map = |indices: &[(u32, Vec<(u32, &str)>)]| { |
1163 | if indices.is_empty() { |
1164 | return None; |
1165 | } |
1166 | let mut map = wasm_encoder::IndirectNameMap::default(); |
1167 | for (idx, names) in indices { |
1168 | if let Some(names) = name_map(names) { |
1169 | map.append(*idx, &names); |
1170 | } |
1171 | } |
1172 | Some(map) |
1173 | }; |
1174 | if let Some(map) = name_map(&self.funcs) { |
1175 | names.functions(&map); |
1176 | } |
1177 | if let Some(map) = indirect_name_map(&self.locals) { |
1178 | names.locals(&map); |
1179 | } |
1180 | if let Some(map) = indirect_name_map(&self.labels) { |
1181 | names.labels(&map); |
1182 | } |
1183 | if let Some(map) = name_map(&self.types) { |
1184 | names.types(&map); |
1185 | } |
1186 | if let Some(map) = name_map(&self.tables) { |
1187 | names.tables(&map); |
1188 | } |
1189 | if let Some(map) = name_map(&self.memories) { |
1190 | names.memories(&map); |
1191 | } |
1192 | if let Some(map) = name_map(&self.globals) { |
1193 | names.globals(&map); |
1194 | } |
1195 | if let Some(map) = name_map(&self.elems) { |
1196 | names.elements(&map); |
1197 | } |
1198 | if let Some(map) = name_map(&self.data) { |
1199 | names.data(&map); |
1200 | } |
1201 | if let Some(map) = indirect_name_map(&self.fields) { |
1202 | names.fields(&map); |
1203 | } |
1204 | if let Some(map) = name_map(&self.tags) { |
1205 | names.tags(&map); |
1206 | } |
1207 | names |
1208 | } |
1209 | } |
1210 | |
1211 | impl Encode for Id<'_> { |
1212 | fn encode(&self, dst: &mut Vec<u8>) { |
1213 | assert!(!self.is_gensym()); |
1214 | self.name().encode(dst); |
1215 | } |
1216 | } |
1217 | |
1218 | impl<'a> Encode for TryTable<'a> { |
1219 | fn encode(&self, dst: &mut Vec<u8>) { |
1220 | self.block.encode(dst); |
1221 | self.catches.encode(dst); |
1222 | } |
1223 | } |
1224 | |
1225 | impl<'a> Encode for TryTableCatch<'a> { |
1226 | fn encode(&self, dst: &mut Vec<u8>) { |
1227 | let flag_byte: u8 = match self.kind { |
1228 | TryTableCatchKind::Catch(..) => 0, |
1229 | TryTableCatchKind::CatchRef(..) => 1, |
1230 | TryTableCatchKind::CatchAll => 2, |
1231 | TryTableCatchKind::CatchAllRef => 3, |
1232 | }; |
1233 | flag_byte.encode(dst); |
1234 | match self.kind { |
1235 | TryTableCatchKind::Catch(tag: Index<'_>) | TryTableCatchKind::CatchRef(tag: Index<'_>) => { |
1236 | tag.encode(dst); |
1237 | } |
1238 | TryTableCatchKind::CatchAll | TryTableCatchKind::CatchAllRef => {} |
1239 | } |
1240 | self.label.encode(dst); |
1241 | } |
1242 | } |
1243 | |
1244 | impl<'a> Encode for ContBind<'a> { |
1245 | fn encode(&self, dst: &mut Vec<u8>) { |
1246 | self.argument_index.encode(dst); |
1247 | self.result_index.encode(dst); |
1248 | } |
1249 | } |
1250 | |
1251 | impl<'a> Encode for Resume<'a> { |
1252 | fn encode(&self, dst: &mut Vec<u8>) { |
1253 | self.type_index.encode(dst); |
1254 | self.table.encode(dst); |
1255 | } |
1256 | } |
1257 | |
1258 | impl<'a> Encode for ResumeThrow<'a> { |
1259 | fn encode(&self, dst: &mut Vec<u8>) { |
1260 | self.type_index.encode(dst); |
1261 | self.tag_index.encode(dst); |
1262 | self.table.encode(dst); |
1263 | } |
1264 | } |
1265 | |
1266 | impl<'a> Encode for ResumeTable<'a> { |
1267 | fn encode(&self, dst: &mut Vec<u8>) { |
1268 | self.handlers.encode(dst); |
1269 | } |
1270 | } |
1271 | |
1272 | impl<'a> Encode for Handle<'a> { |
1273 | fn encode(&self, dst: &mut Vec<u8>) { |
1274 | match self { |
1275 | Handle::OnLabel { tag: &Index<'_>, label: &Index<'_> } => { |
1276 | dst.push(0x00); |
1277 | tag.encode(dst); |
1278 | label.encode(dst); |
1279 | } |
1280 | Handle::OnSwitch { tag: &Index<'_> } => { |
1281 | dst.push(0x01); |
1282 | tag.encode(dst); |
1283 | } |
1284 | } |
1285 | } |
1286 | } |
1287 | |
1288 | impl<'a> Encode for Switch<'a> { |
1289 | fn encode(&self, dst: &mut Vec<u8>) { |
1290 | self.type_index.encode(dst); |
1291 | self.tag_index.encode(dst); |
1292 | } |
1293 | } |
1294 | |
1295 | impl Encode for V128Const { |
1296 | fn encode(&self, dst: &mut Vec<u8>) { |
1297 | dst.extend_from_slice(&self.to_le_bytes()); |
1298 | } |
1299 | } |
1300 | |
1301 | impl Encode for I8x16Shuffle { |
1302 | fn encode(&self, dst: &mut Vec<u8>) { |
1303 | dst.extend_from_slice(&self.lanes); |
1304 | } |
1305 | } |
1306 | |
1307 | impl<'a> Encode for SelectTypes<'a> { |
1308 | fn encode(&self, dst: &mut Vec<u8>) { |
1309 | match &self.tys { |
1310 | Some(list: &Vec>) => { |
1311 | dst.push(0x1c); |
1312 | list.encode(dst); |
1313 | } |
1314 | None => dst.push(0x1b), |
1315 | } |
1316 | } |
1317 | } |
1318 | |
1319 | impl Custom<'_> { |
1320 | fn encode(&self, module: &mut wasm_encoder::Module) { |
1321 | match self { |
1322 | Custom::Raw(r: &RawCustomSection<'_>) => { |
1323 | module.section(&r.to_section()); |
1324 | } |
1325 | Custom::Producers(p: &Producers<'_>) => { |
1326 | module.section(&p.to_section()); |
1327 | } |
1328 | Custom::Dylink0(p: &Dylink0<'_>) => { |
1329 | module.section(&p.to_section()); |
1330 | } |
1331 | } |
1332 | } |
1333 | } |
1334 | |
1335 | impl RawCustomSection<'_> { |
1336 | fn to_section(&self) -> wasm_encoder::CustomSection<'_> { |
1337 | let mut ret: Vec = Vec::new(); |
1338 | for list: &&[u8] in self.data.iter() { |
1339 | ret.extend_from_slice(list); |
1340 | } |
1341 | wasm_encoder::CustomSection { |
1342 | name: self.name.into(), |
1343 | data: ret.into(), |
1344 | } |
1345 | } |
1346 | } |
1347 | |
1348 | impl Producers<'_> { |
1349 | pub(crate) fn to_section(&self) -> wasm_encoder::ProducersSection { |
1350 | let mut ret: ProducersSection = wasm_encoder::ProducersSection::default(); |
1351 | for (name: &&str, fields: &Vec<(&str, &str)>) in self.fields.iter() { |
1352 | let mut field: ProducersField = wasm_encoder::ProducersField::new(); |
1353 | for (key: &&str, value: &&str) in fields { |
1354 | field.value(name:key, version:value); |
1355 | } |
1356 | ret.field(name, &field); |
1357 | } |
1358 | ret |
1359 | } |
1360 | } |
1361 | |
1362 | impl Dylink0<'_> { |
1363 | fn to_section(&self) -> wasm_encoder::CustomSection<'_> { |
1364 | let mut e: Vec = Vec::new(); |
1365 | for section: &Dylink0Subsection<'_> in self.subsections.iter() { |
1366 | e.push(section.id()); |
1367 | let mut tmp: Vec = Vec::new(); |
1368 | section.encode(&mut tmp); |
1369 | tmp.encode(&mut e); |
1370 | } |
1371 | wasm_encoder::CustomSection { |
1372 | name: "dylink.0" .into(), |
1373 | data: e.into(), |
1374 | } |
1375 | } |
1376 | } |
1377 | |
1378 | impl Encode for Dylink0Subsection<'_> { |
1379 | fn encode(&self, e: &mut Vec<u8>) { |
1380 | match self { |
1381 | Dylink0Subsection::MemInfo { |
1382 | memory_size: &u32, |
1383 | memory_align: &u32, |
1384 | table_size: &u32, |
1385 | table_align: &u32, |
1386 | } => { |
1387 | memory_size.encode(e); |
1388 | memory_align.encode(e); |
1389 | table_size.encode(e); |
1390 | table_align.encode(e); |
1391 | } |
1392 | Dylink0Subsection::Needed(libs: &Vec<&str>) => libs.encode(e), |
1393 | Dylink0Subsection::ExportInfo(list: &Vec<(&str, u32)>) => list.encode(e), |
1394 | Dylink0Subsection::ImportInfo(list: &Vec<(&str, &str, u32)>) => list.encode(e), |
1395 | } |
1396 | } |
1397 | } |
1398 | |
1399 | impl SectionItem for Tag<'_> { |
1400 | type Section = wasm_encoder::TagSection; |
1401 | const ANCHOR: CustomPlaceAnchor = CustomPlaceAnchor::Tag; |
1402 | |
1403 | fn encode(&self, section: &mut wasm_encoder::TagSection) { |
1404 | section.tag(self.ty.to_tag_type()); |
1405 | match &self.kind { |
1406 | TagKind::Inline() => {} |
1407 | _ => panic!("TagKind should be inline during encoding" ), |
1408 | } |
1409 | } |
1410 | } |
1411 | |
1412 | impl Encode for StructAccess<'_> { |
1413 | fn encode(&self, e: &mut Vec<u8>) { |
1414 | self.r#struct.encode(e); |
1415 | self.field.encode(e); |
1416 | } |
1417 | } |
1418 | |
1419 | impl Encode for ArrayFill<'_> { |
1420 | fn encode(&self, e: &mut Vec<u8>) { |
1421 | self.array.encode(e); |
1422 | } |
1423 | } |
1424 | |
1425 | impl Encode for ArrayCopy<'_> { |
1426 | fn encode(&self, e: &mut Vec<u8>) { |
1427 | self.dest_array.encode(e); |
1428 | self.src_array.encode(e); |
1429 | } |
1430 | } |
1431 | |
1432 | impl Encode for ArrayInit<'_> { |
1433 | fn encode(&self, e: &mut Vec<u8>) { |
1434 | self.array.encode(e); |
1435 | self.segment.encode(e); |
1436 | } |
1437 | } |
1438 | |
1439 | impl Encode for ArrayNewFixed<'_> { |
1440 | fn encode(&self, e: &mut Vec<u8>) { |
1441 | self.array.encode(e); |
1442 | self.length.encode(e); |
1443 | } |
1444 | } |
1445 | |
1446 | impl Encode for ArrayNewData<'_> { |
1447 | fn encode(&self, e: &mut Vec<u8>) { |
1448 | self.array.encode(e); |
1449 | self.data_idx.encode(e); |
1450 | } |
1451 | } |
1452 | |
1453 | impl Encode for ArrayNewElem<'_> { |
1454 | fn encode(&self, e: &mut Vec<u8>) { |
1455 | self.array.encode(e); |
1456 | self.elem_idx.encode(e); |
1457 | } |
1458 | } |
1459 | |
1460 | impl Encode for RefTest<'_> { |
1461 | fn encode(&self, e: &mut Vec<u8>) { |
1462 | e.push(0xfb); |
1463 | if self.r#type.nullable { |
1464 | e.push(0x15); |
1465 | } else { |
1466 | e.push(0x14); |
1467 | } |
1468 | self.r#type.heap.encode(e); |
1469 | } |
1470 | } |
1471 | |
1472 | impl Encode for RefCast<'_> { |
1473 | fn encode(&self, e: &mut Vec<u8>) { |
1474 | e.push(0xfb); |
1475 | if self.r#type.nullable { |
1476 | e.push(0x17); |
1477 | } else { |
1478 | e.push(0x16); |
1479 | } |
1480 | self.r#type.heap.encode(e); |
1481 | } |
1482 | } |
1483 | |
1484 | fn br_on_cast_flags(from_nullable: bool, to_nullable: bool) -> u8 { |
1485 | let mut flag: u8 = 0; |
1486 | if from_nullable { |
1487 | flag |= 1 << 0; |
1488 | } |
1489 | if to_nullable { |
1490 | flag |= 1 << 1; |
1491 | } |
1492 | flag |
1493 | } |
1494 | |
1495 | impl Encode for BrOnCast<'_> { |
1496 | fn encode(&self, e: &mut Vec<u8>) { |
1497 | e.push(0xfb); |
1498 | e.push(0x18); |
1499 | e.push(br_on_cast_flags( |
1500 | self.from_type.nullable, |
1501 | self.to_type.nullable, |
1502 | )); |
1503 | self.label.encode(e); |
1504 | self.from_type.heap.encode(e); |
1505 | self.to_type.heap.encode(e); |
1506 | } |
1507 | } |
1508 | |
1509 | impl Encode for BrOnCastFail<'_> { |
1510 | fn encode(&self, e: &mut Vec<u8>) { |
1511 | e.push(0xfb); |
1512 | e.push(0x19); |
1513 | e.push(br_on_cast_flags( |
1514 | self.from_type.nullable, |
1515 | self.to_type.nullable, |
1516 | )); |
1517 | self.label.encode(e); |
1518 | self.from_type.heap.encode(e); |
1519 | self.to_type.heap.encode(e); |
1520 | } |
1521 | } |
1522 | |