Skip to content

Commit b5cc561

Browse files
authored
[SILGen] Fix a crash when a closure is converted to a block returning a value indirectly (swiftlang#73520)
1 parent 58cc2a4 commit b5cc561

File tree

5 files changed

+46
-2
lines changed

5 files changed

+46
-2
lines changed

lib/IRGen/IRGenSIL.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2338,7 +2338,9 @@ static void emitEntryPointArgumentsCOrObjC(IRGenSILFunction &IGF,
23382338
// First, claim all the indirect results.
23392339
ArrayRef<SILArgument *> args = emitEntryPointIndirectReturn(
23402340
*emission, IGF, entry, funcTy, [&](SILType directResultType) -> bool {
2341-
return FI.getReturnInfo().isIndirect();
2341+
// Indirect at the IR level but direct at the SIL level.
2342+
return FI.getReturnInfo().isIndirect() &&
2343+
!funcTy->hasIndirectFormalResults();
23422344
});
23432345

23442346
unsigned nextArgTyIdx = 0;

lib/SILGen/SILGenBridging.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,8 @@ static void buildFuncToBlockInvokeBody(SILGenFunction &SGF,
392392
if (blockTy->getNumResults() != 0) {
393393
auto result = blockTy->getSingleResult();
394394
if (result.getConvention() == ResultConvention::Indirect) {
395-
indirectResult = entry->createFunctionArgument(blockResultTy);
395+
indirectResult =
396+
entry->createFunctionArgument(blockResultTy.getAddressType());
396397
}
397398
}
398399

test/Interop/Cxx/class/Inputs/closure.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@ struct ARCStrong {
2020
void cfuncARCStrong(void (*_Nonnull)(ARCStrong));
2121
#endif
2222

23+
void cfuncReturnNonTrivial(NonTrivial (^_Nonnull)()) noexcept;
24+
2325
#endif // __CLOSURE__
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %target-swiftxx-frontend -I %S/Inputs -emit-irgen %s | %FileCheck %s
2+
3+
// REQUIRES: OS=macosx
4+
5+
import Closure
6+
7+
// CHECK: define internal swiftcc void @"$s4main34testClosureToBlockReturnNonTrivialyyFSo0gH0VycfU_"(ptr noalias sret(%{{.*}}) %[[V0:.*]])
8+
// CHECK: call {{void|ptr}} @__swift_cxx_ctor_ZN10NonTrivialC1Ev(ptr %[[V0]])
9+
// CHECK: ret void
10+
11+
// CHECK: define linkonce_odr hidden void @"$sSo10NonTrivialVIegr_ABIeyBr_TR"(ptr noalias sret(%{{.*}}) %[[V0:.*]], ptr %[[V1:.*]])
12+
// CHECK: %[[V2:.*]] = getelementptr inbounds { %{{.*}}, %{{.*}} }, ptr %[[V1]], i32 0, i32 1
13+
// CHECK: %[[_FN:.*]] = getelementptr inbounds %{{.*}}, ptr %[[V2]], i32 0, i32 0
14+
// CHECK: %[[V3:.*]] = load ptr, ptr %[[_FN]], align 8
15+
// CHECK: %[[_DATA:.*]] = getelementptr inbounds %{{.*}}, ptr %[[V2]], i32 0, i32 1
16+
// CHECK: %[[V4:.*]] = load ptr, ptr %[[_DATA]], align 8
17+
// CHECK: call ptr @swift_retain(ptr returned %[[V4]])
18+
// CHECK: call swiftcc void %[[V3]](ptr noalias sret(%{{.*}}) %[[V0]], ptr swiftself %[[V4]])
19+
// CHECK: call void @swift_release(ptr %[[V4]])
20+
// CHECK: ret void
21+
22+
public func testClosureToBlockReturnNonTrivial() {
23+
cfuncReturnNonTrivial({() -> NonTrivial in return NonTrivial() })
24+
}

test/Interop/Cxx/class/closure-thunk-macosx.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,18 @@ import Closure
2020
public func testClosureToFuncPtr() {
2121
cfuncARCStrong({N in})
2222
}
23+
24+
// CHECK: sil shared [transparent] [serialized] [reabstraction_thunk] [ossa] @$sSo10NonTrivialVIegr_ABIeyBr_TR : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed () -> @out NonTrivial) -> @out NonTrivial {
25+
// CHECK: bb0(%[[V0:.*]] : $*NonTrivial, %[[V1:.*]] : $*@block_storage @callee_guaranteed () -> @out NonTrivial):
26+
// CHECK: %[[V2:.*]] = project_block_storage %[[V1]] : $*@block_storage @callee_guaranteed () -> @out NonTrivial
27+
// CHECK: %[[V3:.*]] = load [copy] %[[V2]] : $*@callee_guaranteed () -> @out NonTrivial
28+
// CHECK: %[[V4:.*]] = begin_borrow %[[V3]] : $@callee_guaranteed () -> @out NonTrivial
29+
// CHECK: apply %[[V4]](%[[V0]]) : $@callee_guaranteed () -> @out NonTrivial
30+
// CHECK: end_borrow %[[V4]] : $@callee_guaranteed () -> @out NonTrivial
31+
// CHECK: %[[V8:.*]] = tuple ()
32+
// CHECK: destroy_value %[[V3]] : $@callee_guaranteed () -> @out NonTrivial
33+
// CHECK: return %[[V8]] : $()
34+
35+
public func testClosureToBlockReturnNonTrivial() {
36+
cfuncReturnNonTrivial({() -> NonTrivial in return NonTrivial() })
37+
}

0 commit comments

Comments
 (0)