Same as `store_flat_helper` but for loading the flat representation.
(
&'a self,
s: &mut String,
i: usize,
helpers: &mut IndexSet<Helper<'a>>,
)
| 481 | |
| 482 | /// Same as `store_flat_helper` but for loading the flat representation. |
| 483 | fn load_flat_helper<'a>( |
| 484 | &'a self, |
| 485 | s: &mut String, |
| 486 | i: usize, |
| 487 | helpers: &mut IndexSet<Helper<'a>>, |
| 488 | ) { |
| 489 | uwrite!(s, "(func $load_helper_{i} (param i32)"); |
| 490 | let lowered = self.lowered(); |
| 491 | for ty in &lowered { |
| 492 | uwrite!(s, " (result {ty})"); |
| 493 | } |
| 494 | s.push_str("\n"); |
| 495 | let record = |s: &mut String, helpers: &mut IndexSet<Helper<'a>>, types: &'a [Type]| { |
| 496 | for (offset, ty) in record_field_offsets(types) { |
| 497 | ty.load_flat(s, "0", offset, helpers); |
| 498 | } |
| 499 | }; |
| 500 | let variant = |s: &mut String, |
| 501 | helpers: &mut IndexSet<Helper<'a>>, |
| 502 | types: &[Option<&'a Type>]| { |
| 503 | let (size, offset) = variant_memory_info(types.iter().cloned()); |
| 504 | |
| 505 | // Destination locals where the flat representation will be stored. |
| 506 | // These are automatically zero which handles unused fields too. |
| 507 | for (i, ty) in lowered.iter().enumerate() { |
| 508 | uwriteln!(s, " (local $r{i} {ty})"); |
| 509 | } |
| 510 | |
| 511 | // Return block each case jumps to after setting all locals. |
| 512 | s.push_str("block $r\n"); |
| 513 | |
| 514 | // One extra block for "out of bounds discriminant". |
| 515 | for _ in 0..types.len() + 1 { |
| 516 | s.push_str("block\n"); |
| 517 | } |
| 518 | |
| 519 | // Load the discriminant and branch on it, storing it in |
| 520 | // `$r0` as well which is the first flat local representation. |
| 521 | let load = match size { |
| 522 | DiscriminantSize::Size1 => "i32.load8_u", |
| 523 | DiscriminantSize::Size2 => "i32.load16", |
| 524 | DiscriminantSize::Size4 => "i32.load", |
| 525 | }; |
| 526 | uwriteln!(s, "({load} (local.get 0))"); |
| 527 | s.push_str("local.tee $r0\n"); |
| 528 | s.push_str("br_table"); |
| 529 | for i in 0..types.len() + 1 { |
| 530 | uwrite!(s, " {i}"); |
| 531 | } |
| 532 | s.push_str("\nend\n"); |
| 533 | |
| 534 | // For each payload, which is in its own block, load payloads from |
| 535 | // memory as necessary and convert them into the final locals. |
| 536 | for ty in types { |
| 537 | if let Some(ty) = ty { |
| 538 | let ty_lowered = ty.lowered(); |
| 539 | ty.load_flat(s, "0", offset, helpers); |
| 540 | for (i, (from, to)) in ty_lowered.iter().zip(&lowered[1..]).enumerate().rev() { |
no test coverage detected