Skip to content

Commit 2f19875

Browse files
Merge pull request #36016 from aschwaighofer/irgen_fix_partial_apply_self_5.4
[5.4] IRGen: We can only reuse methods for partial apply thunks if th…
2 parents eb5989d + cdb3e83 commit 2f19875

File tree

3 files changed

+56
-8
lines changed

3 files changed

+56
-8
lines changed

lib/IRGen/IRGenSIL.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2956,7 +2956,12 @@ static bool isSimplePartialApply(IRGenFunction &IGF, PartialApplyInst *i) {
29562956
// handled by a simplification pass in SIL.)
29572957
if (i->getNumArguments() != 1)
29582958
return false;
2959-
2959+
// The closure application is going to expect to pass the context in swiftself
2960+
// only methods where the call to `hasSelfContextParameter` returns true will
2961+
// use swiftself for the self parameter.
2962+
if (!hasSelfContextParameter(calleeTy))
2963+
return false;
2964+
29602965
auto appliedParam = calleeTy->getParameters().back();
29612966
if (resultTy->isNoEscape()) {
29622967
// A trivial closure accepts an unowned or guaranteed argument, possibly

test/IRGen/simple_partial_apply.sil

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@ entry(%body : $@convention(method) (Int, @guaranteed C) -> Int, %context : $C):
2323
return %closure : $@callee_guaranteed (Int) -> Int
2424
}
2525

26+
// Can't reuse the method because it does not have swiftself.
27+
2628
// CHECK-LABEL: define {{.*}} @escape_partial_apply_swift_single_refcount_struct
27-
// CHECK-arm64e: call i64 @llvm.ptrauth.resign.i64
28-
// CHECK: [[FPTR:%.*]] = insertvalue { i8*, %swift.refcounted* } undef, i8* {{.*}}, 0
29-
// CHECK-NEXT: [[FCTX:%.*]] = insertvalue { i8*, %swift.refcounted* } [[FPTR]], %swift.refcounted* {{.*}}, 1
29+
// CHECK: [[CTXT:%.*]] = call {{.*}} @swift_allocObject
30+
// CHECK: [[FCTX:%.*]] = insertvalue { i8*, %swift.refcounted* } { i8* bitcast (i{{(64|32)}} (i{{(64|32)}}, %swift.refcounted*)* @"$sTA" to i8*), %swift.refcounted* undef }, %swift.refcounted* [[CTXT]], 1
3031
// CHECK-NEXT: ret { i8*, %swift.refcounted* } [[FCTX]]
3132
sil @escape_partial_apply_swift_single_refcount_struct : $@convention(thin) (@convention(method) (Int, @guaranteed SingleRefcounted) -> Int, @guaranteed SingleRefcounted) -> @callee_guaranteed (Int) -> Int {
3233
entry(%body : $@convention(method) (Int, @guaranteed SingleRefcounted) -> Int, %context : $SingleRefcounted):
@@ -47,11 +48,9 @@ entry(%body : $@convention(method) (Int, @in_guaranteed C) -> Int, %context : $*
4748
return undef : $()
4849
}
4950

51+
// Can't reuse the method because it does not have swiftself.
5052
// CHECK-LABEL: define {{.*}} @noescape_partial_apply_swift_direct_word
51-
// CHECK-arm64e: call i64 @llvm.ptrauth.resign.i64
52-
// CHECK: [[CTX:%.*]] = inttoptr i{{.*}} %1 to %swift.opaque*
53-
// CHECK-NEXT: [[CONT:%.*]] = bitcast i8* %2
54-
// CHECK-NEXT: call {{.*}}void [[CONT]](i8* {{.*}}, %swift.opaque* [[CTX]], %swift.refcounted* {{.*}}%3)
53+
// CHECK: call swiftcc void %11(i8* bitcast (i{{(64|32)}} (i{{(64|32)}}, %swift.refcounted*)* @"$sTA.1" to i8*), %swift.opaque* {{.*}}, %swift.refcounted* swiftself {{.*}})
5554
sil @noescape_partial_apply_swift_direct_word : $@convention(thin) (@convention(method) (Int, Int) -> Int, Int, @guaranteed @callee_guaranteed (@noescape @callee_guaranteed (Int) -> Int) -> ()) -> () {
5655
entry(%body : $@convention(method) (Int, Int) -> Int, %context : $Int, %cont : $@callee_guaranteed (@noescape @callee_guaranteed (Int) -> Int) -> ()):
5756
%closure = partial_apply [callee_guaranteed] [on_stack] %body(%context) : $@convention(method) (Int, Int) -> Int
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// RUN: %target-swift-emit-ir -module-name test %s | %FileCheck %s
2+
// RUN: %target-run-simple-swift %s | %FileCheck %s --check-prefix=CHECK-EXEC
3+
4+
// REQUIRES: executable_test
5+
6+
@propertyWrapper
7+
struct State<T> {
8+
private class Reference {
9+
var value: T
10+
init(value: T) { self.value = value }
11+
}
12+
13+
private let ref: Reference
14+
15+
init(wrappedValue: T) {
16+
ref = Reference(value: wrappedValue)
17+
}
18+
19+
var wrappedValue: T {
20+
get { ref.value }
21+
nonmutating set { ref.value = newValue }
22+
}
23+
}
24+
25+
struct S {
26+
@State var value: Int = 1
27+
28+
init() {
29+
value = 10 // CRASH
30+
}
31+
}
32+
33+
print("Hello!")
34+
let s = S()
35+
print(s)
36+
37+
// CHECK: define {{.*}}swiftcc %T4test5StateV9Reference33_C903A018FCE7355FD30EF8324850EB90LLCySi_G* @"$s4test1SVACycfC"()
38+
// CHECK: call swiftcc void @"$s4test1SV5valueSivsTA"(i{{(32|64)}} 10, %swift.refcounted* swiftself {{.*}})
39+
// CHECK: ret %T4test5StateV9Reference33_C903A018FCE7355FD30EF8324850EB90LLCySi_G
40+
41+
// This used to crash.
42+
43+
// CHECK-EXEC: Hello!
44+
// CHECK-EXEC: S(_value: main.State<Swift.Int>(ref: main.State<Swift.Int>.(unknown context at {{.*}}).Reference))

0 commit comments

Comments
 (0)