Skip to content

Commit 9f3f3c4

Browse files
committed
[IRGen] Only use value witness getEnumTag function for "normal" enums
rdar://115013153 For special enum cases, e.g. effectively optional references, the layout string will be the same as the payload, because we don't have to check for the particular case. For those cases we have to use the regular witnesses, which should be shared among all those cases.
1 parent 43ea121 commit 9f3f3c4

File tree

3 files changed

+39
-0
lines changed

3 files changed

+39
-0
lines changed

lib/IRGen/GenValueWitness.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,9 @@ static llvm::Constant *getEnumTagFunction(IRGenModule &IGM,
905905
if (!typeLayoutEntry->layoutString(IGM, genericSig) &&
906906
!isRuntimeInstatiatedLayoutString(IGM, typeLayoutEntry)) {
907907
return nullptr;
908+
} else if (typeLayoutEntry->copyDestroyKind(IGM) !=
909+
EnumTypeLayoutEntry::CopyDestroyStrategy::Normal) {
910+
return nullptr;
908911
} else if (typeLayoutEntry->isSingleton()) {
909912
return IGM.getSingletonEnumGetEnumTagFn();
910913
} else if (!typeLayoutEntry->isFixedSize(IGM)) {
@@ -939,6 +942,9 @@ getDestructiveInjectEnumTagFunction(IRGenModule &IGM,
939942
if ((!typeLayoutEntry->layoutString(IGM, genericSig) &&
940943
!isRuntimeInstatiatedLayoutString(IGM, typeLayoutEntry))) {
941944
return nullptr;
945+
} else if (typeLayoutEntry->copyDestroyKind(IGM) !=
946+
EnumTypeLayoutEntry::CopyDestroyStrategy::Normal) {
947+
return nullptr;
942948
} else if (typeLayoutEntry->isSingleton()) {
943949
return IGM.getSingletonEnumDestructiveInjectEnumTagFn();
944950
} else if (!typeLayoutEntry->isFixedSize(IGM)) {

test/Interpreter/Inputs/layout_string_witnesses_types_resilient.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ public enum ResilientSinglePayloadEnumGeneric<T> {
2525
case nonEmpty(T)
2626
}
2727

28+
public enum ResilientSinglePayloadEnumIndirect {
29+
case empty
30+
indirect case nonEmpty(AnyObject)
31+
}
32+
2833
public enum ResilientMultiPayloadEnumGeneric<T> {
2934
case empty0
3035
case empty1
@@ -55,6 +60,14 @@ public enum ResilientSingletonEnum {
5560
case nonEmpty(AnyObject)
5661
}
5762

63+
public func getResilientSinglePayloadEnumIndirectEmpty() -> ResilientSinglePayloadEnumIndirect {
64+
return .empty
65+
}
66+
67+
public func getResilientSinglePayloadEnumIndirectNonEmpty(_ x: AnyObject) -> ResilientSinglePayloadEnumIndirect {
68+
return .nonEmpty(x)
69+
}
70+
5871
public func getResilientSinglePayloadEnumGenericEmpty0<T>(_ t: T.Type) -> ResilientSinglePayloadEnumGeneric<T> {
5972
return .empty0
6073
}

test/Interpreter/layout_string_witnesses_dynamic.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,26 @@ func testResilientSinglePayloadEnumSimpleTag() {
842842

843843
testResilientSinglePayloadEnumSimpleTag()
844844

845+
func testResilientSinglePayloadEnumIndirectTag() {
846+
let x = switch getResilientSinglePayloadEnumIndirectNonEmpty(SimpleClass(x: 23)) {
847+
case .nonEmpty: 0
848+
case .empty: 1
849+
}
850+
851+
// CHECK: Enum case: 0
852+
print("Enum case: \(x)")
853+
854+
let y = switch getResilientSinglePayloadEnumIndirectEmpty() {
855+
case .nonEmpty: 0
856+
case .empty: 1
857+
}
858+
859+
// CHECK: Enum case: 1
860+
print("Enum case: \(y)")
861+
}
862+
863+
testResilientSinglePayloadEnumIndirectTag()
864+
845865
func testResilientSinglePayloadEnumComplexTag() {
846866
let x = switch getResilientSinglePayloadEnumComplexEmpty0() {
847867
case .nonEmpty: 0

0 commit comments

Comments
 (0)