@@ -241,9 +241,7 @@ public struct ILType: Hashable {
241
241
}
242
242
243
243
static func wasmSelfReference( ) -> ILType {
244
- let type = wasmTypeDef ( )
245
- type. wasmTypeDefinition!. description = . selfReference
246
- return type
244
+ wasmTypeDef ( description: . selfReference)
247
245
}
248
246
249
247
static func wasmRef( _ kind: WasmReferenceType . Kind , nullability: Bool ) -> ILType {
@@ -252,7 +250,7 @@ public struct ILType: Hashable {
252
250
wasmExt: WasmReferenceType ( kind, nullability: nullability) ) )
253
251
}
254
252
255
- static func wasmIndexRef( _ desc: WasmTypeDescription ? , nullability: Bool ) -> ILType {
253
+ static func wasmIndexRef( _ desc: WasmTypeDescription , nullability: Bool ) -> ILType {
256
254
return wasmRef ( . Index( UnownedWasmTypeDescription ( desc) ) , nullability: nullability)
257
255
}
258
256
@@ -1325,7 +1323,7 @@ public class WasmTypeDefinition: WasmTypeExtension {
1325
1323
1326
1324
func getReferenceTypeTo( nullability: Bool ) -> ILType {
1327
1325
assert ( description != nil )
1328
- return . wasmIndexRef( description, nullability: nullability)
1326
+ return . wasmIndexRef( description! , nullability: nullability)
1329
1327
}
1330
1328
}
1331
1329
@@ -1455,23 +1453,72 @@ public class WasmReferenceType: WasmTypeExtension {
1455
1453
case Index( UnownedWasmTypeDescription = UnownedWasmTypeDescription ( ) )
1456
1454
case Abstract( WasmAbstractHeapType )
1457
1455
1458
- func subsumes ( _ other: Kind ) -> Bool {
1456
+ func union ( _ other: Self ) -> Self ? {
1459
1457
switch self {
1460
1458
case . Index( let desc) :
1461
1459
switch other {
1462
1460
case . Index( let otherDesc) :
1463
- return desc. get ( ) == nil || desc. get ( ) == otherDesc. get ( )
1464
- case . Abstract( _) :
1465
- return false
1461
+ if desc. get ( ) == nil || otherDesc. get ( ) == nil {
1462
+ return . Index( . init( ) )
1463
+ }
1464
+ if desc. get ( ) == otherDesc. get ( ) {
1465
+ return self
1466
+ }
1467
+ if let abstract = desc. get ( ) ? . abstractHeapSupertype,
1468
+ let otherAbstract = otherDesc. get ( ) ? . abstractHeapSupertype,
1469
+ let upperBound = abstract. union ( otherAbstract) {
1470
+ return . Abstract( upperBound)
1471
+ }
1472
+ case . Abstract( let otherAbstract) :
1473
+ if let abstractSuper = desc. get ( ) ? . abstractHeapSupertype,
1474
+ let upperBound = abstractSuper. union ( otherAbstract) {
1475
+ return . Abstract( upperBound)
1476
+ }
1466
1477
}
1467
1478
case . Abstract( let heapType) :
1468
1479
switch other {
1469
- case . Index( _) :
1470
- return false
1480
+ case . Index( let otherDesc) :
1481
+ if let otherAbstract = otherDesc. get ( ) ? . abstractHeapSupertype,
1482
+ let upperBound = heapType. union ( otherAbstract) {
1483
+ return . Abstract( upperBound)
1484
+ }
1485
+ case . Abstract( let otherHeapType) :
1486
+ if let upperBound = heapType. union ( otherHeapType) {
1487
+ return . Abstract( upperBound)
1488
+ }
1489
+ }
1490
+ }
1491
+ return nil
1492
+ }
1493
+
1494
+ func intersection( _ other: Self ) -> Self ? {
1495
+ switch self {
1496
+ case . Index( let desc) :
1497
+ switch other {
1498
+ case . Index( let otherDesc) :
1499
+ if desc. get ( ) == otherDesc. get ( ) || desc. get ( ) == nil || otherDesc. get ( ) == nil {
1500
+ return . Index( desc)
1501
+ }
1502
+ case . Abstract( let otherAbstract) :
1503
+ if let abstractSuper = desc. get ( ) ? . abstractHeapSupertype,
1504
+ otherAbstract. subsumes ( abstractSuper) {
1505
+ return self
1506
+ }
1507
+ }
1508
+ case . Abstract( let heapType) :
1509
+ switch other {
1510
+ case . Index( let otherDesc) :
1511
+ if let otherAbstract = otherDesc. get ( ) ? . abstractHeapSupertype,
1512
+ heapType. subsumes ( otherAbstract) {
1513
+ return other
1514
+ }
1471
1515
case . Abstract( let otherHeapType) :
1472
- return heapType. subsumes ( otherHeapType)
1516
+ if let lowerBound = heapType. intersection ( otherHeapType) {
1517
+ return . Abstract( lowerBound)
1518
+ }
1473
1519
}
1474
1520
}
1521
+ return nil
1475
1522
}
1476
1523
}
1477
1524
var kind : Kind
@@ -1498,61 +1545,27 @@ public class WasmReferenceType: WasmTypeExtension {
1498
1545
1499
1546
override func subsumes( _ other: WasmTypeExtension ) -> Bool {
1500
1547
guard let other = other as? WasmReferenceType else { return false }
1501
- return self . kind. subsumes ( other. kind) && ( self . nullability || !other. nullability)
1548
+ return self . kind. union ( other. kind) == self . kind && ( self . nullability || !other. nullability)
1502
1549
}
1503
1550
1504
1551
override func union( _ other: WasmTypeExtension ) -> WasmTypeExtension ? {
1505
1552
guard let other = other as? WasmReferenceType else { return nil }
1506
- // The union is nullable if either of the two types input types is nullable.
1507
- let nullability = self . nullability || other. nullability
1508
- // TODO(gc): Add subtyping between different index types, different abstract types and
1509
- // between index and abstract types.
1510
- switch self . kind {
1511
- case . Index( let desc) :
1512
- switch other. kind {
1513
- case . Index( let otherDesc) :
1514
- return desc. get ( ) == otherDesc. get ( ) ? WasmReferenceType ( . Index( desc) , nullability: nullability) : nil
1515
- case . Abstract( _) :
1516
- return nil
1517
- }
1518
- case . Abstract( let heapType) :
1519
- switch other. kind {
1520
- case . Index( _) :
1521
- return nil
1522
- case . Abstract( let otherHeapType) :
1523
- if let upperBound = heapType. union ( otherHeapType) {
1524
- return WasmReferenceType ( . Abstract( upperBound) , nullability: nullability)
1525
- }
1526
- return nil
1527
- }
1553
+ if let kind = self . kind. union ( other. kind) {
1554
+ // The union is nullable if either of the two types input types is nullable.
1555
+ let nullability = self . nullability || other. nullability
1556
+ return WasmReferenceType ( kind, nullability: nullability)
1528
1557
}
1558
+ return nil
1529
1559
}
1530
1560
1531
1561
override func intersection( _ other: WasmTypeExtension ) -> WasmTypeExtension ? {
1532
1562
guard let other = other as? WasmReferenceType else { return nil }
1533
- // The intersection is nullable if both are nullable.
1534
- let nullability = self . nullability && other. nullability
1535
- // TODO(gc): Add subtyping between different index types, different abstract types and
1536
- // between index and abstract types.
1537
- switch self . kind {
1538
- case . Index( let desc) :
1539
- switch other. kind {
1540
- case . Index( let otherDesc) :
1541
- return desc. get ( ) == otherDesc. get ( ) ? WasmReferenceType ( . Index( desc) , nullability: nullability) : nil
1542
- case . Abstract( _) :
1543
- return nil
1544
- }
1545
- case . Abstract( let heapType) :
1546
- switch other. kind {
1547
- case . Index( _) :
1548
- return nil
1549
- case . Abstract( let otherHeapType) :
1550
- if let lowerBound = heapType. intersection ( otherHeapType) {
1551
- return WasmReferenceType ( . Abstract( lowerBound) , nullability: nullability)
1552
- }
1553
- return nil
1554
- }
1563
+ if let kind = self . kind. intersection ( other. kind) {
1564
+ // The intersection is nullable if both are nullable.
1565
+ let nullability = self . nullability && other. nullability
1566
+ return WasmReferenceType ( kind, nullability: nullability)
1555
1567
}
1568
+ return nil
1556
1569
}
1557
1570
1558
1571
override public func hash( into hasher: inout Hasher ) {
@@ -1935,9 +1948,15 @@ func => (parameters: [ILType], returnTypes: [ILType]) -> WasmSignature {
1935
1948
class WasmTypeDescription : Hashable {
1936
1949
static let selfReference = WasmTypeDescription ( typeGroupIndex: - 1 )
1937
1950
public let typeGroupIndex : Int
1951
+ // The "closest" super type that is an abstract type (.WasmArray for arrays, .WasmStruct for
1952
+ // structs). It is nil for unresolved forward/self references for which the concrete abstract
1953
+ // super type is still undecided.
1954
+ public let abstractHeapSupertype : WasmAbstractHeapType ?
1938
1955
1939
- init ( typeGroupIndex: Int ) {
1956
+ // TODO(gc): We will also need to support subtyping of struct and array types at some point.
1957
+ init ( typeGroupIndex: Int , superType: WasmAbstractHeapType ? = nil ) {
1940
1958
self . typeGroupIndex = typeGroupIndex
1959
+ self . abstractHeapSupertype = superType
1941
1960
}
1942
1961
1943
1962
static func == ( lhs: WasmTypeDescription , rhs: WasmTypeDescription ) -> Bool {
@@ -1956,7 +1975,7 @@ class WasmArrayTypeDescription: WasmTypeDescription {
1956
1975
init ( elementType: ILType , mutability: Bool , typeGroupIndex: Int ) {
1957
1976
self . elementType = elementType
1958
1977
self . mutability = mutability
1959
- super. init ( typeGroupIndex: typeGroupIndex)
1978
+ super. init ( typeGroupIndex: typeGroupIndex, superType : . WasmArray )
1960
1979
}
1961
1980
}
1962
1981
@@ -1975,6 +1994,6 @@ class WasmStructTypeDescription: WasmTypeDescription {
1975
1994
1976
1995
init ( fields: [ Field ] , typeGroupIndex: Int ) {
1977
1996
self . fields = fields
1978
- super. init ( typeGroupIndex: typeGroupIndex)
1997
+ super. init ( typeGroupIndex: typeGroupIndex, superType : . WasmStruct )
1979
1998
}
1980
1999
}
0 commit comments