Skip to content

Commit e26933a

Browse files
committed
[SILGen] Fix a crash when a closure is converted to a pointer to a
function returning a non-trivial C++ type rdar://124501345
1 parent 0971654 commit e26933a

File tree

5 files changed

+50
-13
lines changed

5 files changed

+50
-13
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: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,8 +1363,10 @@ emitObjCThunkArguments(SILGenFunction &SGF, SILLocation loc, SILDeclRef thunk,
13631363
}
13641364

13651365
// We don't know what to do with indirect results from the Objective-C side.
1366-
assert(objcFnTy->getNumIndirectFormalResults() == 0
1367-
&& "Objective-C methods cannot have indirect results");
1366+
assert((SGF.F.getRepresentation() ==
1367+
SILFunctionType::Representation::CFunctionPointer ||
1368+
objcFnTy->getNumIndirectFormalResults() == 0) &&
1369+
"Objective-C methods cannot have indirect results");
13681370

13691371
auto bridgedFormalTypes = getParameterTypes(objcFormalFnTy.getParams());
13701372
bridgedFormalResultTy = objcFormalFnTy.getResult();
@@ -1625,12 +1627,18 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
16251627
// stack allocation to hold the result(s), since Any is address-only.
16261628
SmallVector<SILValue, 4> args;
16271629
if (substConv.hasIndirectSILResults()) {
1628-
for (auto result : substConv.getResults()) {
1629-
if (!substConv.isSILIndirect(result)) {
1630-
continue;
1630+
if (F.getRepresentation() ==
1631+
SILFunctionType::Representation::CFunctionPointer) {
1632+
args.push_back(F.begin()->createFunctionArgument(
1633+
substConv.getSingleSILResultType(getTypeExpansionContext())));
1634+
} else {
1635+
for (auto result : substConv.getResults()) {
1636+
if (!substConv.isSILIndirect(result)) {
1637+
continue;
1638+
}
1639+
args.push_back(emitTemporaryAllocation(
1640+
loc, substConv.getSILType(result, getTypeExpansionContext())));
16311641
}
1632-
args.push_back(emitTemporaryAllocation(
1633-
loc, substConv.getSILType(result, getTypeExpansionContext())));
16341642
}
16351643
}
16361644

@@ -1868,12 +1876,14 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
18681876
if (foreignAsync) {
18691877
result = passResultToCompletionHandler(result);
18701878
} else {
1871-
if (substConv.hasIndirectSILResults()) {
1872-
assert(substTy->getNumResults() == 1);
1873-
result = args[0];
1879+
if (F.getRepresentation() != SILFunctionType::Representation::CFunctionPointer) {
1880+
if (substConv.hasIndirectSILResults()) {
1881+
assert(substTy->getNumResults() == 1);
1882+
result = args[0];
1883+
}
1884+
result = emitBridgeReturnValue(*this, loc, result, nativeFormalResultType,
1885+
bridgedFormalResultType, objcResultTy);
18741886
}
1875-
result = emitBridgeReturnValue(*this, loc, result, nativeFormalResultType,
1876-
bridgedFormalResultType, objcResultTy);
18771887
}
18781888
} else {
18791889
SILBasicBlock *contBB = createBasicBlock();

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 cfuncReturnNonTrivial2(NonTrivial (*_Nonnull)());
24+
2325
#endif // __CLOSURE__
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %target-swiftxx-frontend -I %S/Inputs -emit-irgen %s | %FileCheck %s
2+
3+
// REQUIRES: OS=macosx || OS=linux-android
4+
5+
import Closure
6+
7+
// CHECK: define internal void @"$s4main36testClosureToFuncPtrReturnNonTrivialyyFSo0hI0VycfU_To"(ptr noalias sret(%{{.*}}) %[[V0:.*]])
8+
// CHECK: call swiftcc void @"$s4main36testClosureToFuncPtrReturnNonTrivialyyFSo0hI0VycfU_"(ptr noalias sret(%{{.*}}) %[[V0]])
9+
// CHECK: ret void
10+
11+
public func testClosureToFuncPtrReturnNonTrivial() {
12+
cfuncReturnNonTrivial2({() -> NonTrivial in return NonTrivial()});
13+
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,13 @@ import Closure
1919
public func testClosureToFuncPtr() {
2020
cfunc2({N in})
2121
}
22+
23+
// CHECK: sil private [thunk] [ossa] @$s4main36testClosureToFuncPtrReturnNonTrivialyyFSo0hI0VycfU_To : $@convention(c) () -> @out NonTrivial {
24+
// CHECK: bb0(%[[V0:.*]] : $*NonTrivial):
25+
// CHECK: %[[V1:.*]] = function_ref @$s4main36testClosureToFuncPtrReturnNonTrivialyyFSo0hI0VycfU_ : $@convention(thin) () -> @out NonTrivial // user: %[[V2]]
26+
// CHECK: %[[V2:.*]] = apply %[[V1]](%[[V0]]) : $@convention(thin) () -> @out NonTrivial // user: %[[V3]]
27+
// CHECK: return %[[V2]] : $()
28+
29+
public func testClosureToFuncPtrReturnNonTrivial() {
30+
cfuncReturnNonTrivial2({() -> NonTrivial in return NonTrivial()});
31+
}

0 commit comments

Comments
 (0)