Generates a text-format wasm function which takes a pointer and this type's flat representation as arguments and then stores this value in the first argument. This is used to store records/variants to cut down on the size of final functions and make codegen here a bit easier.
(
&'a self,
s: &mut String,
i: usize,
helpers: &mut IndexSet<Helper<'a>>,
)
| 328 | /// This is used to store records/variants to cut down on the size of final |
| 329 | /// functions and make codegen here a bit easier. |
| 330 | fn store_flat_helper<'a>( |
| 331 | &'a self, |
| 332 | s: &mut String, |
| 333 | i: usize, |
| 334 | helpers: &mut IndexSet<Helper<'a>>, |
| 335 | ) { |
| 336 | uwrite!(s, "(func $store_helper_{i} (param i32)"); |
| 337 | let lowered = self.lowered(); |
| 338 | for ty in &lowered { |
| 339 | uwrite!(s, " (param {ty})"); |
| 340 | } |
| 341 | s.push_str("\n"); |
| 342 | let locals = (0..lowered.len() as u32).map(|i| i + 1).collect::<Vec<_>>(); |
| 343 | let record = |s: &mut String, helpers: &mut IndexSet<Helper<'a>>, types: &'a [Type]| { |
| 344 | let mut locals = locals.iter().cloned().map(FlatSource::Local); |
| 345 | for (offset, ty) in record_field_offsets(types) { |
| 346 | ty.store_flat(s, "0", offset, &mut locals, helpers); |
| 347 | } |
| 348 | assert!(locals.next().is_none()); |
| 349 | }; |
| 350 | let variant = |s: &mut String, |
| 351 | helpers: &mut IndexSet<Helper<'a>>, |
| 352 | types: &[Option<&'a Type>]| { |
| 353 | let (size, offset) = variant_memory_info(types.iter().cloned()); |
| 354 | // One extra block for out-of-bounds discriminants. |
| 355 | for _ in 0..types.len() + 1 { |
| 356 | s.push_str("block\n"); |
| 357 | } |
| 358 | |
| 359 | // Store the discriminant in memory, then branch on it to figure |
| 360 | // out which case we're in. |
| 361 | let store = match size { |
| 362 | DiscriminantSize::Size1 => "i32.store8", |
| 363 | DiscriminantSize::Size2 => "i32.store16", |
| 364 | DiscriminantSize::Size4 => "i32.store", |
| 365 | }; |
| 366 | uwriteln!(s, "({store} (local.get 0) (local.get 1))"); |
| 367 | s.push_str("local.get 1\n"); |
| 368 | s.push_str("br_table"); |
| 369 | for i in 0..types.len() + 1 { |
| 370 | uwrite!(s, " {i}"); |
| 371 | } |
| 372 | s.push_str("\nend\n"); |
| 373 | |
| 374 | // Store each payload individually while converting locals from |
| 375 | // their source types to the precise type necessary for this |
| 376 | // variant. |
| 377 | for ty in types { |
| 378 | if let Some(ty) = ty { |
| 379 | let ty_lowered = ty.lowered(); |
| 380 | let mut locals = locals[1..].iter().zip(&lowered[1..]).zip(&ty_lowered).map( |
| 381 | |((i, from), to)| FlatSource::LocalConvert { |
| 382 | local: *i, |
| 383 | from: *from, |
| 384 | to: *to, |
| 385 | }, |
| 386 | ); |
| 387 | ty.store_flat(s, "0", offset, &mut locals, helpers); |
no test coverage detected