|
1 | | -use crate::component::{MAX_FLAT_PARAMS, MAX_FLAT_RESULTS}; |
| 1 | +use crate::component::{FlatTypesStorage, MAX_FLAT_PARAMS, MAX_FLAT_RESULTS}; |
2 | 2 | use crate::{EntityType, ModuleInternedTypeIndex, ModuleTypes, PrimaryMap}; |
3 | 3 | use crate::{TypeTrace, prelude::*}; |
4 | 4 | use core::hash::{Hash, Hasher}; |
@@ -364,6 +364,162 @@ impl ComponentTypes { |
364 | 364 | } |
365 | 365 | } |
366 | 366 |
|
| 367 | + /// Returns the flat storage representation for an interface type. |
| 368 | + pub fn flat_types_storage(&self, ty: &InterfaceType) -> FlatTypesStorage { |
| 369 | + let mut storage_buf = FlatTypesStorage::new(); |
| 370 | + |
| 371 | + let push_discrim = |
| 372 | + |storage: &mut FlatTypesStorage| storage.push(FlatType::I32, FlatType::I32); |
| 373 | + |
| 374 | + let push_storage = |storage: &mut FlatTypesStorage, other: FlatTypesStorage| -> bool { |
| 375 | + let len = usize::from(storage.len); |
| 376 | + let other_len = usize::from(other.len); |
| 377 | + if len < (MAX_FLAT_TYPES - other_len + 1) { |
| 378 | + storage.memory32[len..len + other_len] |
| 379 | + .copy_from_slice(&other.memory32[..other_len]); |
| 380 | + storage.memory64[len..len + other_len] |
| 381 | + .copy_from_slice(&other.memory64[..other_len]); |
| 382 | + storage.len += other.len; |
| 383 | + true |
| 384 | + } else { |
| 385 | + storage.len = MAX_FLAT_TYPES as u8 + 1; |
| 386 | + false |
| 387 | + } |
| 388 | + }; |
| 389 | + |
| 390 | + let push_storage_variant_case = |
| 391 | + |storage: &mut FlatTypesStorage, case: Option<FlatTypesStorage>| -> bool { |
| 392 | + if let Some(case) = case { |
| 393 | + if case.len as usize >= MAX_FLAT_TYPES { |
| 394 | + storage.len = u8::try_from(MAX_FLAT_TYPES + 1).unwrap(); |
| 395 | + false |
| 396 | + } else { |
| 397 | + let dst = storage |
| 398 | + .memory32 |
| 399 | + .iter_mut() |
| 400 | + .zip(&mut storage.memory64) |
| 401 | + .skip(1); |
| 402 | + for (i, ((t32, t64), (dst32, dst64))) in case |
| 403 | + .memory32 |
| 404 | + .iter() |
| 405 | + .zip(case.memory64.iter()) |
| 406 | + .zip(dst) |
| 407 | + .enumerate() |
| 408 | + { |
| 409 | + if i + 1 < usize::from(storage.len) { |
| 410 | + // Populated Index |
| 411 | + dst32.join(*t32); |
| 412 | + dst64.join(*t64); |
| 413 | + } else { |
| 414 | + // New Index |
| 415 | + storage.len += 1; |
| 416 | + *dst32 = *t32; |
| 417 | + *dst64 = *t64; |
| 418 | + } |
| 419 | + } |
| 420 | + true |
| 421 | + } |
| 422 | + } else { |
| 423 | + true |
| 424 | + } |
| 425 | + }; |
| 426 | + |
| 427 | + let storage = &mut storage_buf; |
| 428 | + |
| 429 | + match ty { |
| 430 | + InterfaceType::U8 |
| 431 | + | InterfaceType::S8 |
| 432 | + | InterfaceType::Bool |
| 433 | + | InterfaceType::U16 |
| 434 | + | InterfaceType::S16 |
| 435 | + | InterfaceType::U32 |
| 436 | + | InterfaceType::S32 |
| 437 | + | InterfaceType::Char |
| 438 | + | InterfaceType::Own(_) |
| 439 | + | InterfaceType::Future(_) |
| 440 | + | InterfaceType::Stream(_) |
| 441 | + | InterfaceType::ErrorContext(_) |
| 442 | + | InterfaceType::Borrow(_) |
| 443 | + | InterfaceType::Enum(_) => { |
| 444 | + storage.push(FlatType::I32, FlatType::I32); |
| 445 | + } |
| 446 | + |
| 447 | + InterfaceType::U64 | InterfaceType::S64 => { |
| 448 | + storage.push(FlatType::I64, FlatType::I64); |
| 449 | + } |
| 450 | + InterfaceType::Float32 => { |
| 451 | + storage.push(FlatType::F32, FlatType::F32); |
| 452 | + } |
| 453 | + InterfaceType::Float64 => { |
| 454 | + storage.push(FlatType::F64, FlatType::F64); |
| 455 | + } |
| 456 | + InterfaceType::String | InterfaceType::List(_) => { |
| 457 | + // Pointer pair |
| 458 | + storage.push(FlatType::I32, FlatType::I64); |
| 459 | + storage.push(FlatType::I32, FlatType::I64); |
| 460 | + } |
| 461 | + |
| 462 | + InterfaceType::Record(i) => { |
| 463 | + for field in self[*i].fields.iter() { |
| 464 | + if !push_storage(storage, self.flat_types_storage(&field.ty)) { |
| 465 | + break; |
| 466 | + } |
| 467 | + } |
| 468 | + } |
| 469 | + InterfaceType::Tuple(i) => { |
| 470 | + for ty in self[*i].types.iter() { |
| 471 | + if !push_storage(storage, self.flat_types_storage(ty)) { |
| 472 | + break; |
| 473 | + } |
| 474 | + } |
| 475 | + } |
| 476 | + InterfaceType::Flags(i) => match FlagsSize::from_count(self[*i].names.len()) { |
| 477 | + FlagsSize::Size0 => {} |
| 478 | + FlagsSize::Size1 | FlagsSize::Size2 => { |
| 479 | + storage.push(FlatType::I32, FlatType::I32); |
| 480 | + } |
| 481 | + FlagsSize::Size4Plus(n) => { |
| 482 | + for _ in 0..n { |
| 483 | + if !storage.push(FlatType::I32, FlatType::I32) { |
| 484 | + break; |
| 485 | + } |
| 486 | + } |
| 487 | + } |
| 488 | + }, |
| 489 | + InterfaceType::Variant(i) => { |
| 490 | + push_discrim(storage); |
| 491 | + for case in self[*i].cases.values() { |
| 492 | + let case_flat = case.as_ref().map(|ty| self.flat_types_storage(ty)); |
| 493 | + if !push_storage_variant_case(storage, case_flat) { |
| 494 | + break; |
| 495 | + } |
| 496 | + } |
| 497 | + } |
| 498 | + InterfaceType::Option(i) => { |
| 499 | + push_discrim(storage); |
| 500 | + push_storage_variant_case(storage, None); |
| 501 | + push_storage_variant_case(storage, Some(self.flat_types_storage(&self[*i].ty))); |
| 502 | + } |
| 503 | + InterfaceType::Result(i) => { |
| 504 | + push_discrim(storage); |
| 505 | + let result = &self[*i]; |
| 506 | + push_storage_variant_case( |
| 507 | + storage, |
| 508 | + result.ok.map(|ty| self.flat_types_storage(&ty)), |
| 509 | + ); |
| 510 | + push_storage_variant_case( |
| 511 | + storage, |
| 512 | + result.err.map(|ty| self.flat_types_storage(&ty)), |
| 513 | + ); |
| 514 | + } |
| 515 | + } |
| 516 | + assert_eq!( |
| 517 | + storage.len as usize, |
| 518 | + self.canonical_abi(ty).flat_count(usize::MAX).unwrap() |
| 519 | + ); |
| 520 | + storage_buf |
| 521 | + } |
| 522 | + |
367 | 523 | /// Adds a new `table` to the list of resource tables for this component. |
368 | 524 | pub fn push_resource_table(&mut self, table: TypeResourceTable) -> TypeResourceTableIndex { |
369 | 525 | self.resource_tables.push(table) |
@@ -1185,3 +1341,12 @@ pub enum FlatType { |
1185 | 1341 | F32, |
1186 | 1342 | F64, |
1187 | 1343 | } |
| 1344 | + |
| 1345 | +impl FlatType { |
| 1346 | + const fn byte_size(&self) -> u8 { |
| 1347 | + match self { |
| 1348 | + FlatType::I32 | FlatType::F32 => 4, |
| 1349 | + FlatType::I64 | FlatType::F64 => 8, |
| 1350 | + } |
| 1351 | + } |
| 1352 | +} |
0 commit comments