Skip to content

Commit 1ba5415

Browse files
Merge pull request #16916 from aschwaighofer/irgen_fix_multipayload_indirect_mixed
IRGen: Fix multipayload enums with indirect cases
2 parents 63348bc + fcb0dcc commit 1ba5415

File tree

3 files changed

+88
-13
lines changed

3 files changed

+88
-13
lines changed

lib/IRGen/GenEnum.cpp

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3129,15 +3129,12 @@ namespace {
31293129
&refcounting)) {
31303130
allSingleRefcount = false;
31313131
} else if (haveRefcounting) {
3132-
// Different payloads have different reference counting styles.
3133-
if (refcounting != Refcounting) {
3134-
// Fall back to unknown entry points if the Objective-C runtime is
3135-
// available.
3136-
Refcounting = ReferenceCounting::Unknown;
3137-
// Otherwise, use value witnesses.
3138-
if (!IGM.ObjCInterop)
3139-
allSingleRefcount = false;
3140-
}
3132+
// Only support a single style of reference counting for now.
3133+
// swift_unknowRetain does not support the heap buffer of indirect
3134+
// enums. And I am not convinced that unknowRetain supports
3135+
// bridgedObjectRetain.
3136+
if (refcounting != Refcounting)
3137+
allSingleRefcount = false;
31413138
} else {
31423139
Refcounting = refcounting;
31433140
haveRefcounting = true;

test/IRGen/enum_value_semantics_special_cases_objc.sil

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ enum AllMixedRefcounted {
3535
// CHECK: %0 = bitcast %swift.opaque* %object to %T39enum_value_semantics_special_cases_objc18AllMixedRefcountedO*
3636
// CHECK: %1 = bitcast %T39enum_value_semantics_special_cases_objc18AllMixedRefcountedO* %0 to i64*
3737
// CHECK: %2 = load i64, i64* %1, align 8
38-
// -- 0x3fffffffffffffff
39-
// CHECK: %3 = and i64 %2, 4611686018427387903
40-
// CHECK: %4 = inttoptr i64 %3 to %objc_object*
41-
// CHECK: call void @swift_unknownRelease(%objc_object* %4) {{#[0-9]+}}
38+
// CHECK: %3 = lshr i64 %2, 62
39+
// CHECK: %4 = trunc i64 %3 to i8
40+
// CHECK: %5 = and i8 %4, 3
41+
// CHECK: call void @"$S39enum_value_semantics_special_cases_objc18AllMixedRefcountedOWOe"(i64 %2)
4242
// CHECK: ret void
4343
// CHECK: }
4444

@@ -52,3 +52,51 @@ enum AllMixedRefcountedTwoSimple {
5252

5353
// CHECK-LABEL: define linkonce_odr hidden void @"$S39enum_value_semantics_special_cases_objc27AllMixedRefcountedTwoSimpleOwxx"
5454
// CHECK: call void @"$S39enum_value_semantics_special_cases_objc27AllMixedRefcountedTwoSimpleOWOy"
55+
56+
struct Val {
57+
}
58+
59+
// Currently, swift_unknownRelease does not support the indirect heap object.
60+
61+
enum MixedRefcountedWithIndirect {
62+
indirect case Indirect(Builtin.Int64)
63+
case Ref(Builtin.UnknownObject)
64+
case None
65+
}
66+
67+
// CHECK-LABEL: define linkonce_odr hidden void @"$S39enum_value_semantics_special_cases_objc27MixedRefcountedWithIndirectOwxx"(%swift.opaque* noalias %object, %swift.type* %MixedRefcountedWithIndirect)
68+
// CHECK: entry:
69+
// CHECK: %0 = bitcast %swift.opaque* %object to %T39enum_value_semantics_special_cases_objc27MixedRefcountedWithIndirectO*
70+
// CHECK: %1 = bitcast %T39enum_value_semantics_special_cases_objc27MixedRefcountedWithIndirectO* %0 to i64*
71+
// CHECK: %2 = load i64, i64* %1, align 8
72+
// CHECK: %3 = lshr i64 %2, 62
73+
// CHECK: %4 = trunc i64 %3 to i8
74+
// CHECK: %5 = and i8 %4, 3
75+
// CHECK: call void @"$S39enum_value_semantics_special_cases_objc27MixedRefcountedWithIndirectOWOe"(i64 %2)
76+
// CHECK: ret void
77+
// CHECK: }
78+
79+
80+
// CHECK-LABEL: define linkonce_odr hidden void @"$S39enum_value_semantics_special_cases_objc27MixedRefcountedWithIndirectOWOe"(i64)
81+
// CHECK: entry:
82+
// CHECK: %1 = lshr i64 %0, 62
83+
// CHECK: %2 = trunc i64 %1 to i8
84+
// CHECK: %3 = and i8 %2, 3
85+
// CHECK: switch i8 %3, label %9 [
86+
// CHECK: i8 0, label %4
87+
// CHECK: i8 1, label %6
88+
// CHECK: ]
89+
90+
// CHECK: ; <label>:4:
91+
// CHECK: %5 = inttoptr i64 %0 to %swift.refcounted*
92+
// CHECK: call void @swift_release(%swift.refcounted* %5) #1
93+
// CHECK: br label %9
94+
95+
// CHECK: ; <label>:6:
96+
// CHECK: %7 = and i64 %0, 4611686018427387903
97+
// CHECK: %8 = inttoptr i64 %7 to %objc_object*
98+
// CHECK: call void @swift_unknownRelease(%objc_object* %8) #1
99+
// CHECK: br label %9
100+
101+
// CHECK: ; <label>:9:
102+
// CHECK: ret void

test/Interpreter/enum.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,3 +667,33 @@ public func testCase(_ closure: @escaping (Int) -> ()) -> Indirect<(Int) -> ()>
667667

668668
// CHECK: payload((Function), other: (Function))
669669
print(testCase({ _ in }))
670+
671+
672+
enum MultiIndirectRef {
673+
case empty
674+
indirect case ind(Int)
675+
case collection([Int])
676+
}
677+
678+
struct Container {
679+
var storage : MultiIndirectRef = .empty
680+
681+
mutating func adoptStyle(_ s: Int) {
682+
storage = .ind(s)
683+
}
684+
}
685+
686+
func copyStorage(_ s: Int, _ x : Container) -> Container {
687+
var c = x
688+
c.adoptStyle(s)
689+
return c
690+
}
691+
692+
func testCase() {
693+
let l = Container()
694+
let c = copyStorage(5, l)
695+
print(c)
696+
}
697+
698+
// CHECK: Container(storage: a.MultiIndirectRef.ind(5))
699+
testCase()

0 commit comments

Comments
 (0)