Skip to content

Commit d06aeee

Browse files
authored
Merge pull request #70505 from aschwaighofer/typed_throws_in_thunks
IRGen: Add support for typed throws to thunk code generation
2 parents 9261fa7 + b4ef029 commit d06aeee

File tree

4 files changed

+97
-5
lines changed

4 files changed

+97
-5
lines changed

lib/IRGen/GenCall.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4841,6 +4841,10 @@ Address IRGenFunction::getCalleeTypedErrorResultSlot(SILType errorType) {
48414841
return CalleeTypedErrorResultSlot;
48424842
}
48434843

4844+
void IRGenFunction::setCalleeTypedErrorResultSlot(Address addr) {
4845+
CalleeTypedErrorResultSlot = addr;
4846+
}
4847+
48444848

48454849
/// Fetch the error result slot received from the caller.
48464850
Address IRGenFunction::getCallerErrorResultSlot() {

lib/IRGen/GenThunk.cpp

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class IRGenThunk {
8585
llvm::Value *indirectReturnSlot = nullptr;
8686
llvm::Value *selfValue = nullptr;
8787
llvm::Value *errorResult = nullptr;
88+
llvm::Value *typedErrorIndirectErrorSlot = nullptr;
8889
WitnessMetadata witnessMetadata;
8990
Explosion params;
9091

@@ -137,16 +138,31 @@ void IRGenThunk::prepareArguments() {
137138
SILFunctionConventions conv(origTy, IGF.getSILModule());
138139

139140
if (origTy->hasErrorResult()) {
141+
typedErrorIndirectErrorSlot = nullptr;
142+
143+
// Set the typed error value result slot.
144+
if (conv.isTypedError() && !conv.hasIndirectSILErrorResults()) {
145+
auto directTypedErrorAddr = original.takeLast();
146+
auto errorType =
147+
conv.getSILErrorType(IGF.IGM.getMaximalTypeExpansionContext());
148+
auto &errorTI = cast<FixedTypeInfo>(IGF.getTypeInfo(errorType));
149+
150+
IGF.setCalleeTypedErrorResultSlot(Address(directTypedErrorAddr,
151+
errorTI.getStorageType(),
152+
errorTI.getFixedAlignment()));
153+
} else if (conv.isTypedError()) {
154+
auto directTypedErrorAddr = original.takeLast();
155+
// Store for later processing when we know the argument index.
156+
// (i.e. emission->setIndirectTypedErrorResultSlotArgsIndex was called)
157+
typedErrorIndirectErrorSlot = directTypedErrorAddr;
158+
}
159+
140160
if (isAsync) {
141161
// nothing to do.
142162
} else {
143163
errorResult = original.takeLast();
144-
auto errorType =
145-
conv.getSILErrorType(IGF.IGM.getMaximalTypeExpansionContext());
146-
auto &errorTI = cast<FixedTypeInfo>(IGF.getTypeInfo(errorType));
147-
148164
IGF.setCallerErrorResultSlot(Address(errorResult,
149-
errorTI.getStorageType(),
165+
IGF.IGM.Int8PtrTy,
150166
IGF.IGM.getPointerAlignment()));
151167
}
152168
}
@@ -276,6 +292,10 @@ void IRGenThunk::emit() {
276292
std::unique_ptr<CallEmission> emission =
277293
getCallEmission(IGF, callee.getSwiftContext(), std::move(callee));
278294

295+
if (typedErrorIndirectErrorSlot) {
296+
emission->setIndirectTypedErrorResultSlot(typedErrorIndirectErrorSlot);
297+
}
298+
279299
emission->begin();
280300

281301
emission->setArgs(params, /*isOutlined=*/false, &witnessMetadata);

lib/IRGen/IRGenFunction.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ class IRGenFunction {
136136

137137
Address getCallerTypedErrorResultSlot();
138138
Address getCalleeTypedErrorResultSlot(SILType errorType);
139+
void setCalleeTypedErrorResultSlot(Address addr);
139140

140141
/// Are we currently emitting a coroutine?
141142
bool isCoroutine() {

test/IRGen/typed_throws_thunks.swift

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// RUN: %target-swift-frontend -primary-file %s -emit-irgen -enable-experimental-feature TypedThrows -disable-availability-checking -runtime-compatibility-version none -target %module-target-future -enable-library-evolution | %FileCheck %s --check-prefix=CHECK
2+
3+
// REQUIRES: PTRSIZE=64
4+
// UNSUPPORTED: CPU=arm64e
5+
6+
@frozen
7+
public struct FixedSize : Error {
8+
var x = 0
9+
var y = 0
10+
}
11+
12+
public protocol P {
13+
associatedtype Failure: Error = any Error
14+
15+
func f(body: () throws -> Void) async rethrows
16+
func f2(body: () throws -> Void) rethrows
17+
18+
func g(body: () throws(Failure) -> Void) async throws(Failure)
19+
func g4(body: () throws(FixedSize) -> Void) async throws(FixedSize)
20+
21+
func g2(body: () throws(Failure) -> Void) throws(Failure)
22+
func g3(body: () throws(FixedSize) -> Void) throws(FixedSize)
23+
}
24+
25+
extension P {
26+
// CHECK-LABEL: define{{.*}} swifttailcc void @"$s19typed_throws_thunks1PP1g4bodyyyy7FailureQzYKXE_tYaAGYKFTj"(ptr swiftasync %0, ptr %1, ptr %2, ptr noalias swiftself %3, ptr %4, ptr %5, ptr %6)
27+
// CHECK-NOT: ret
28+
// CHECK: call { ptr, ptr } (i32, ptr, ptr, ...) @llvm.coro.suspend.async.sl_p0p0s({{.*}}, ptr %1, ptr %2, ptr %3, ptr %4, ptr %5, ptr %6)
29+
public func g(body: () throws(Failure) -> Void) async throws(Failure) {
30+
do {
31+
return try await f(body: body)
32+
} catch {
33+
throw error as! Failure
34+
}
35+
}
36+
37+
// CHECK-LABEL: define{{.*}} swifttailcc void @"$s19typed_throws_thunks1PP2g44bodyyyyAA9FixedSizeVYKXE_tYaAGYKFTj"(ptr swiftasync %0, ptr %1, ptr %2, ptr noalias swiftself %3, ptr %4, ptr %5, ptr %6)
38+
// CHECK-NOT: ret
39+
// CHECK: call { ptr, ptr } (i32, ptr, ptr, ...) @llvm.coro.suspend.async.sl_p0p0s({{.*}} ptr %1, ptr %2, ptr %3, ptr %4, ptr %5, ptr %6)
40+
public func g4(body: () throws(FixedSize) -> Void) async throws(FixedSize) {
41+
do {
42+
return try await f(body: body)
43+
} catch {
44+
throw error as! FixedSize
45+
}
46+
}
47+
48+
// CHECK-LABEL: define{{.*}} swiftcc void @"$s19typed_throws_thunks1PP2g24bodyyyy7FailureQzYKXE_tAGYKFTj"(ptr %0, ptr %1, ptr noalias swiftself %2, ptr noalias nocapture swifterror dereferenceable(8) %3, ptr %4, ptr %5, ptr %6)
49+
// CHECK-NOT: ret
50+
// CHECK: call swiftcc void {{.*}}(ptr %0, ptr %1, ptr noalias swiftself %2, ptr noalias nocapture swifterror dereferenceable(8) %3, ptr %4, ptr %5, ptr %6)
51+
52+
public func g2(body: () throws(Failure) -> Void) throws(Failure) {
53+
do {
54+
return try f2(body: body)
55+
} catch {
56+
throw error as! Failure
57+
}
58+
}
59+
60+
// CHECK-LABEL: define{{.*}} swiftcc void @"$s19typed_throws_thunks1PP2g34bodyyyyAA9FixedSizeVYKXE_tAGYKFTj"(ptr %0, ptr %1, ptr noalias swiftself %2, ptr noalias nocapture swifterror dereferenceable(8) %3, ptr %4, ptr %5, ptr %6)
61+
// CHECK-NOT: ret
62+
// CHECK: call swiftcc void {{.*}}(ptr %0, ptr %1, ptr noalias swiftself %2, ptr noalias nocapture swifterror dereferenceable(8) %3, ptr %4, ptr %5, ptr %6)
63+
64+
65+
public func g3(body: () throws(FixedSize) -> Void) throws(FixedSize) {
66+
}
67+
}

0 commit comments

Comments
 (0)