Skip to content

Commit 11dec42

Browse files
Merge pull request #36011 from aschwaighofer/irgen_fix_partial_apply_self
IRGen: We can only reuse methods for partial apply thunks if their abi uses swiftself for self
2 parents 4768de0 + 29db401 commit 11dec42

File tree

3 files changed

+54
-8
lines changed

3 files changed

+54
-8
lines changed

lib/IRGen/IRGenSIL.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2974,7 +2974,12 @@ static bool isSimplePartialApply(IRGenFunction &IGF, PartialApplyInst *i) {
29742974
// handled by a simplification pass in SIL.)
29752975
if (i->getNumArguments() != 1)
29762976
return false;
2977-
2977+
// The closure application is going to expect to pass the context in swiftself
2978+
// only methods where the call to `hasSelfContextParameter` returns true will
2979+
// use swiftself for the self parameter.
2980+
if (!hasSelfContextParameter(calleeTy))
2981+
return false;
2982+
29782983
auto appliedParam = calleeTy->getParameters().back();
29792984
if (resultTy->isNoEscape()) {
29802985
// 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: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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+
@propertyWrapper
5+
struct State<T> {
6+
private class Reference {
7+
var value: T
8+
init(value: T) { self.value = value }
9+
}
10+
11+
private let ref: Reference
12+
13+
init(wrappedValue: T) {
14+
ref = Reference(value: wrappedValue)
15+
}
16+
17+
var wrappedValue: T {
18+
get { ref.value }
19+
nonmutating set { ref.value = newValue }
20+
}
21+
}
22+
23+
struct S {
24+
@State var value: Int = 1
25+
26+
init() {
27+
value = 10 // CRASH
28+
}
29+
}
30+
31+
print("Hello!")
32+
let s = S()
33+
print(s)
34+
35+
// CHECK: define {{.*}}swiftcc %T4test5StateV9Reference33_C903A018FCE7355FD30EF8324850EB90LLCySi_G* @"$s4test1SVACycfC"()
36+
// CHECK: call swiftcc void @"$s4test1SV5valueSivsTA"(i{{(32|64)}} 10, %swift.refcounted* swiftself {{.*}})
37+
// CHECK: ret %T4test5StateV9Reference33_C903A018FCE7355FD30EF8324850EB90LLCySi_G
38+
39+
// This used to crash.
40+
41+
// CHECK-EXEC: Hello!
42+
// CHECK-EXEC: S(_value: main.State<Swift.Int>(ref: main.State<Swift.Int>.(unknown context at {{.*}}).Reference))

0 commit comments

Comments
 (0)