@@ -238,6 +238,7 @@ pub(crate) struct CanonicalOptions {
238
238
pub ( crate ) realloc : Option < u32 > ,
239
239
pub ( crate ) post_return : Option < u32 > ,
240
240
pub ( crate ) concurrency : Concurrency ,
241
+ pub ( crate ) core_type : Option < CoreTypeId > ,
241
242
}
242
243
243
244
impl CanonicalOptions {
@@ -341,8 +342,50 @@ impl CanonicalOptions {
341
342
}
342
343
}
343
344
345
+ if self . core_type . is_some ( ) {
346
+ bail ! (
347
+ offset,
348
+ "canonical option `core-type` is not allowed in `canon lift`"
349
+ )
350
+ }
351
+
344
352
Ok ( self )
345
353
}
354
+
355
+ pub ( crate ) fn check_core_type (
356
+ & self ,
357
+ types : & mut TypeAlloc ,
358
+ actual : FuncType ,
359
+ offset : usize ,
360
+ ) -> Result < CoreTypeId > {
361
+ if let Some ( declared_id) = self . core_type {
362
+ let declared = types[ declared_id] . unwrap_func ( ) ;
363
+
364
+ if actual. params ( ) != declared. params ( ) {
365
+ bail ! (
366
+ offset,
367
+ "declared core type has `{:?}` parameter types, but actual lowering has \
368
+ `{:?}` parameter types",
369
+ declared. params( ) ,
370
+ actual. params( ) ,
371
+ ) ;
372
+ }
373
+
374
+ if actual. results ( ) != declared. results ( ) {
375
+ bail ! (
376
+ offset,
377
+ "declared core type has `{:?}` result types, but actual lowering has \
378
+ `{:?}` result types",
379
+ declared. results( ) ,
380
+ actual. results( ) ,
381
+ ) ;
382
+ }
383
+
384
+ Ok ( declared_id)
385
+ } else {
386
+ Ok ( types. intern_func_type ( actual, offset) )
387
+ }
388
+ }
346
389
}
347
390
348
391
impl ComponentState {
@@ -1185,6 +1228,7 @@ impl ComponentState {
1185
1228
let options = self . check_options ( types, options, offset) ?;
1186
1229
options. check_lift ( types, self , core_ty, offset) ?;
1187
1230
let func_ty = ty. lower ( types, & options, Abi :: Lift , offset) ?;
1231
+ debug_assert ! ( options. core_type. is_none( ) ) ;
1188
1232
let lowered_core_ty_id = types. intern_func_type ( func_ty, offset) ;
1189
1233
1190
1234
if core_ty_id == lowered_core_ty_id {
@@ -1241,9 +1285,9 @@ impl ComponentState {
1241
1285
let options = self . check_options ( types, options, offset) ?;
1242
1286
options. check_lower ( offset) ?;
1243
1287
let func_ty = ty. lower ( types, & options, Abi :: Lower , offset) ?;
1244
- let core_ty_id = types . intern_func_type ( func_ty, offset) ;
1288
+ let ty_id = options . check_core_type ( types , func_ty, offset) ? ;
1245
1289
1246
- self . core_funcs . push ( core_ty_id ) ;
1290
+ self . core_funcs . push ( ty_id ) ;
1247
1291
Ok ( ( ) )
1248
1292
}
1249
1293
@@ -1349,9 +1393,9 @@ impl ComponentState {
1349
1393
1350
1394
let func_ty = func_ty. lower ( types, & options, Abi :: Lower , offset) ?;
1351
1395
assert ! ( func_ty. results( ) . is_empty( ) ) ;
1396
+ let ty_id = options. check_core_type ( types, func_ty, offset) ?;
1352
1397
1353
- self . core_funcs
1354
- . push ( types. intern_func_type ( func_ty, offset) ) ;
1398
+ self . core_funcs . push ( ty_id) ;
1355
1399
Ok ( ( ) )
1356
1400
}
1357
1401
@@ -1485,13 +1529,18 @@ impl ComponentState {
1485
1529
bail ! ( offset, "`stream.read` requires a stream type" )
1486
1530
} ;
1487
1531
1488
- self . check_options ( types, options, offset) ?
1532
+ let ty_id = self
1533
+ . check_options ( types, options, offset) ?
1489
1534
. require_memory ( offset) ?
1490
1535
. require_realloc_if ( offset, || elem_ty. is_some_and ( |ty| ty. contains_ptr ( types) ) ) ?
1491
- . check_lower ( offset) ?;
1536
+ . check_lower ( offset) ?
1537
+ . check_core_type (
1538
+ types,
1539
+ FuncType :: new ( [ ValType :: I32 ; 3 ] , [ ValType :: I32 ] ) ,
1540
+ offset,
1541
+ ) ?;
1492
1542
1493
- self . core_funcs
1494
- . push ( types. intern_func_type ( FuncType :: new ( [ ValType :: I32 ; 3 ] , [ ValType :: I32 ] ) , offset) ) ;
1543
+ self . core_funcs . push ( ty_id) ;
1495
1544
Ok ( ( ) )
1496
1545
}
1497
1546
@@ -1514,12 +1563,17 @@ impl ComponentState {
1514
1563
bail ! ( offset, "`stream.write` requires a stream type" )
1515
1564
} ;
1516
1565
1517
- self . check_options ( types, options, offset) ?
1566
+ let ty_id = self
1567
+ . check_options ( types, options, offset) ?
1518
1568
. require_memory ( offset) ?
1519
- . check_lower ( offset) ?;
1569
+ . check_lower ( offset) ?
1570
+ . check_core_type (
1571
+ types,
1572
+ FuncType :: new ( [ ValType :: I32 ; 3 ] , [ ValType :: I32 ] ) ,
1573
+ offset,
1574
+ ) ?;
1520
1575
1521
- self . core_funcs
1522
- . push ( types. intern_func_type ( FuncType :: new ( [ ValType :: I32 ; 3 ] , [ ValType :: I32 ] ) , offset) ) ;
1576
+ self . core_funcs . push ( ty_id) ;
1523
1577
Ok ( ( ) )
1524
1578
}
1525
1579
@@ -1666,13 +1720,18 @@ impl ComponentState {
1666
1720
bail ! ( offset, "`future.read` requires a future type" )
1667
1721
} ;
1668
1722
1669
- self . check_options ( types, options, offset) ?
1723
+ let ty_id = self
1724
+ . check_options ( types, options, offset) ?
1670
1725
. require_memory ( offset) ?
1671
1726
. require_realloc_if ( offset, || elem_ty. is_some_and ( |ty| ty. contains_ptr ( types) ) ) ?
1672
- . check_lower ( offset) ?;
1727
+ . check_lower ( offset) ?
1728
+ . check_core_type (
1729
+ types,
1730
+ FuncType :: new ( [ ValType :: I32 ; 2 ] , [ ValType :: I32 ] ) ,
1731
+ offset,
1732
+ ) ?;
1673
1733
1674
- self . core_funcs
1675
- . push ( types. intern_func_type ( FuncType :: new ( [ ValType :: I32 ; 2 ] , [ ValType :: I32 ] ) , offset) ) ;
1734
+ self . core_funcs . push ( ty_id) ;
1676
1735
Ok ( ( ) )
1677
1736
}
1678
1737
@@ -1695,12 +1754,17 @@ impl ComponentState {
1695
1754
bail ! ( offset, "`future.write` requires a future type" )
1696
1755
} ;
1697
1756
1698
- self . check_options ( types, & options, offset) ?
1757
+ let ty_id = self
1758
+ . check_options ( types, & options, offset) ?
1699
1759
. require_memory ( offset) ?
1700
- . check_lower ( offset) ?;
1760
+ . check_lower ( offset) ?
1761
+ . check_core_type (
1762
+ types,
1763
+ FuncType :: new ( [ ValType :: I32 ; 2 ] , [ ValType :: I32 ] ) ,
1764
+ offset,
1765
+ ) ?;
1701
1766
1702
- self . core_funcs
1703
- . push ( types. intern_func_type ( FuncType :: new ( [ ValType :: I32 ; 2 ] , [ ValType :: I32 ] ) , offset) ) ;
1767
+ self . core_funcs . push ( ty_id) ;
1704
1768
Ok ( ( ) )
1705
1769
}
1706
1770
@@ -1823,13 +1887,18 @@ impl ComponentState {
1823
1887
)
1824
1888
}
1825
1889
1826
- self . check_options ( types, & options, offset) ?
1890
+ let ty_id = self
1891
+ . check_options ( types, & options, offset) ?
1827
1892
. require_memory ( offset) ?
1828
1893
. require_sync ( offset, "error-context.new" ) ?
1829
- . check_lower ( offset) ?;
1894
+ . check_lower ( offset) ?
1895
+ . check_core_type (
1896
+ types,
1897
+ FuncType :: new ( [ ValType :: I32 ; 2 ] , [ ValType :: I32 ] ) ,
1898
+ offset,
1899
+ ) ?;
1830
1900
1831
- self . core_funcs
1832
- . push ( types. intern_func_type ( FuncType :: new ( [ ValType :: I32 ; 2 ] , [ ValType :: I32 ] ) , offset) ) ;
1901
+ self . core_funcs . push ( ty_id) ;
1833
1902
Ok ( ( ) )
1834
1903
}
1835
1904
@@ -1846,14 +1915,15 @@ impl ComponentState {
1846
1915
)
1847
1916
}
1848
1917
1849
- self . check_options ( types, & options, offset) ?
1918
+ let ty_id = self
1919
+ . check_options ( types, & options, offset) ?
1850
1920
. require_memory ( offset) ?
1851
1921
. require_realloc ( offset) ?
1852
1922
. require_sync ( offset, "error-context.debug-message" ) ?
1853
- . check_lower ( offset) ?;
1923
+ . check_lower ( offset) ?
1924
+ . check_core_type ( types, FuncType :: new ( [ ValType :: I32 ; 2 ] , [ ] ) , offset) ?;
1854
1925
1855
- self . core_funcs
1856
- . push ( types. intern_func_type ( FuncType :: new ( [ ValType :: I32 ; 2 ] , [ ] ) , offset) ) ;
1926
+ self . core_funcs . push ( ty_id) ;
1857
1927
Ok ( ( ) )
1858
1928
}
1859
1929
@@ -2264,6 +2334,7 @@ impl ComponentState {
2264
2334
CanonicalOption :: PostReturn ( _) => "post-return" ,
2265
2335
CanonicalOption :: Async => "async" ,
2266
2336
CanonicalOption :: Callback ( _) => "callback" ,
2337
+ CanonicalOption :: CoreType ( _) => "core type" ,
2267
2338
}
2268
2339
}
2269
2340
@@ -2273,6 +2344,7 @@ impl ComponentState {
2273
2344
let mut post_return = None ;
2274
2345
let mut is_async = false ;
2275
2346
let mut callback = None ;
2347
+ let mut core_type = None ;
2276
2348
2277
2349
for option in options {
2278
2350
match option {
@@ -2366,6 +2438,43 @@ impl ComponentState {
2366
2438
}
2367
2439
}
2368
2440
}
2441
+ CanonicalOption :: CoreType ( idx) => {
2442
+ core_type = match core_type {
2443
+ None => {
2444
+ if !self . features . cm_gc ( ) {
2445
+ bail ! (
2446
+ offset,
2447
+ "canonical option `core type` requires the component model gc feature"
2448
+ )
2449
+ }
2450
+ let ty = match self . core_type_at ( * idx, offset) ? {
2451
+ ComponentCoreTypeId :: Sub ( ty) => ty,
2452
+ ComponentCoreTypeId :: Module ( _) => return Err ( BinaryReaderError :: new (
2453
+ "canonical option `core type` must reference a core function \
2454
+ type",
2455
+ offset,
2456
+ ) ) ,
2457
+ } ;
2458
+ match & types[ ty] . composite_type . inner {
2459
+ CompositeInnerType :: Func ( _) => { }
2460
+ CompositeInnerType :: Array ( _) |
2461
+ CompositeInnerType :: Struct ( _) |
2462
+ CompositeInnerType :: Cont ( _) => return Err ( BinaryReaderError :: new (
2463
+ "canonical option `core type` must reference a core function \
2464
+ type",
2465
+ offset,
2466
+ ) ) ,
2467
+ }
2468
+ Some ( ty)
2469
+ }
2470
+ Some ( _) => {
2471
+ return Err ( BinaryReaderError :: new (
2472
+ "canonical option `core type` is specified more than once" ,
2473
+ offset,
2474
+ ) )
2475
+ }
2476
+ } ;
2477
+ }
2369
2478
}
2370
2479
}
2371
2480
@@ -2385,6 +2494,7 @@ impl ComponentState {
2385
2494
realloc,
2386
2495
post_return,
2387
2496
concurrency,
2497
+ core_type,
2388
2498
} )
2389
2499
}
2390
2500
0 commit comments