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