| 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 |  | 
|---|