Skip to content

Commit 8564c94

Browse files
authored
Merge pull request swiftlang#35948 from slavapestov/async-dispatch-thunk-loadable-return
IRGen: Fix async dispatch thunk emission with loadable return value
2 parents 59b06e1 + 72e1f02 commit 8564c94

File tree

10 files changed

+66
-14
lines changed

10 files changed

+66
-14
lines changed

lib/IRGen/GenCall.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4753,6 +4753,23 @@ void irgen::emitAsyncReturn(IRGenFunction &IGF, AsyncContextLayout &asyncLayout,
47534753
call->setTailCall();
47544754
}
47554755

4756+
void irgen::emitAsyncReturn(IRGenFunction &IGF, AsyncContextLayout &asyncLayout,
4757+
CanSILFunctionType fnType, Explosion &result) {
4758+
llvm::Value *context = IGF.getAsyncContext();
4759+
4760+
Address dataAddr = asyncLayout.emitCastTo(IGF, context);
4761+
for (unsigned index = 0, count = asyncLayout.getDirectReturnCount();
4762+
index < count; ++index) {
4763+
auto fieldLayout = asyncLayout.getDirectReturnLayout(index);
4764+
Address fieldAddr =
4765+
fieldLayout.project(IGF, dataAddr, /*offsets*/ llvm::None);
4766+
cast<LoadableTypeInfo>(fieldLayout.getType())
4767+
.initialize(IGF, result, fieldAddr, /*isOutlined*/ false);
4768+
}
4769+
4770+
emitAsyncReturn(IGF, asyncLayout, fnType);
4771+
}
4772+
47564773
FunctionPointer
47574774
IRGenFunction::getFunctionPointerForResumeIntrinsic(llvm::Value *resume) {
47584775
auto *fnTy = llvm::FunctionType::get(

lib/IRGen/GenCall.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,9 @@ namespace irgen {
436436
void emitAsyncReturn(IRGenFunction &IGF, AsyncContextLayout &layout,
437437
CanSILFunctionType fnType);
438438

439+
void emitAsyncReturn(IRGenFunction &IGF, AsyncContextLayout &layout,
440+
CanSILFunctionType fnType, Explosion &result);
441+
439442
Address emitAutoDiffCreateLinearMapContext(
440443
IRGenFunction &IGF, llvm::Value *topLevelSubcontextSize);
441444
Address emitAutoDiffProjectTopLevelSubcontext(

lib/IRGen/GenThunk.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "ProtocolInfo.h"
3838
#include "Signature.h"
3939
#include "swift/AST/GenericEnvironment.h"
40+
#include "swift/AST/PrettyStackTrace.h"
4041
#include "swift/IRGen/Linking.h"
4142
#include "swift/SIL/SILDeclRef.h"
4243
#include "llvm/IR/Function.h"
@@ -282,6 +283,9 @@ Callee IRGenThunk::lookupMethod() {
282283
}
283284

284285
void IRGenThunk::emit() {
286+
PrettyStackTraceDecl stackTraceRAII("emitting dispatch thunk for",
287+
declRef.getDecl());
288+
285289
GenericContextScope scope(IGF.IGM, origTy->getInvocationGenericSignature());
286290

287291
if (isAsync) {
@@ -345,7 +349,7 @@ void IRGenThunk::emit() {
345349
}
346350

347351
if (isAsync) {
348-
emitAsyncReturn(IGF, *asyncLayout, origTy);
352+
emitAsyncReturn(IGF, *asyncLayout, origTy, result);
349353
IGF.emitCoroutineOrAsyncExit();
350354
return;
351355
}

lib/IRGen/IRGenSIL.cpp

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3233,19 +3233,9 @@ static void emitReturnInst(IRGenSILFunction &IGF,
32333233
assert(!IGF.IndirectReturn.isValid() &&
32343234
"Formally direct results should stay direct results for async "
32353235
"functions");
3236-
llvm::Value *context = IGF.getAsyncContext();
3237-
auto layout = getAsyncContextLayout(IGF);
3238-
3239-
Address dataAddr = layout.emitCastTo(IGF, context);
3240-
for (unsigned index = 0, count = layout.getDirectReturnCount();
3241-
index < count; ++index) {
3242-
auto fieldLayout = layout.getDirectReturnLayout(index);
3243-
Address fieldAddr =
3244-
fieldLayout.project(IGF, dataAddr, /*offsets*/ llvm::None);
3245-
cast<LoadableTypeInfo>(fieldLayout.getType())
3246-
.initialize(IGF, result, fieldAddr, /*isOutlined*/ false);
3247-
}
3248-
emitAsyncReturn(IGF, layout, fnType);
3236+
3237+
auto asyncLayout = getAsyncContextLayout(IGF);
3238+
emitAsyncReturn(IGF, asyncLayout, fnType, result);
32493239
IGF.emitCoroutineOrAsyncExit();
32503240
} else {
32513241
auto funcLang = IGF.CurSILFn->getLoweredFunctionType()->getLanguage();

test/Concurrency/Runtime/Inputs/resilient_class.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,15 @@ open class BaseClass<T> {
1010
}
1111

1212
open func waitForNothing() async {}
13+
1314
open func wait() async -> T {
1415
return value
1516
}
17+
18+
open func waitForInt() async -> Int {
19+
return 123
20+
}
21+
1622
open func wait(orThrow: Bool) async throws {
1723
if orThrow {
1824
throw MyError.bad
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
public protocol Awaitable {
22
associatedtype Result
33
func waitForNothing() async
4+
func waitForInt() async -> Int
45
func wait() async -> Result
56
func wait(orThrow: Bool) async throws
67
}

test/Concurrency/Runtime/class_resilience.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ class MyDerived : BaseClass<Int> {
2626
return await super.wait() * 2
2727
}
2828

29+
override func waitForInt() async -> Int {
30+
return await super.waitForInt() * 2
31+
}
32+
2933
override func wait(orThrow: Bool) async throws {
3034
return try await super.wait(orThrow: orThrow)
3135
}
@@ -39,6 +43,10 @@ func virtualWait<T>(_ c: BaseClass<T>) async -> T {
3943
return await c.wait()
4044
}
4145

46+
func virtualWaitForInt<T>(_ c: BaseClass<T>) async -> Int {
47+
return await c.waitForInt()
48+
}
49+
4250
func virtualWait<T>(orThrow: Bool, _ c: BaseClass<T>) async throws {
4351
return try await c.wait(orThrow: orThrow)
4452
}
@@ -52,6 +60,7 @@ AsyncVTableMethodSuite.test("AsyncVTableMethod") {
5260
await virtualWaitForNothing(x)
5361

5462
expectEqual(642, await virtualWait(x))
63+
expectEqual(246, await virtualWaitForInt(x))
5564

5665
expectNil(try? await virtualWait(orThrow: true, x))
5766
try! await virtualWait(orThrow: false, x)

test/Concurrency/Runtime/protocol_resilience.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ struct IntAwaitable : Awaitable {
2828
return 123
2929
}
3030

31+
func waitForInt() async -> Int {
32+
return 321
33+
}
34+
3135
func wait(orThrow: Bool) async throws {
3236
if (orThrow) {
3337
throw MyError.bad
@@ -43,6 +47,10 @@ func genericWait<T : Awaitable>(_ t: T) async -> T.Result {
4347
return await t.wait()
4448
}
4549

50+
func genericWaitForInt<T : Awaitable>(_ t: T) async -> Int {
51+
return await t.waitForInt()
52+
}
53+
4654
func genericWait<T : Awaitable>(orThrow: Bool, _ t: T) async throws {
4755
return try await t.wait(orThrow: orThrow)
4856
}
@@ -56,6 +64,7 @@ AsyncProtocolRequirementSuite.test("AsyncProtocolRequirement") {
5664
await genericWaitForNothing(x)
5765

5866
expectEqual(123, await genericWait(x))
67+
expectEqual(321, await genericWaitForInt(x))
5968

6069
expectNil(try? await genericWait(orThrow: true, x))
6170
try! await genericWait(orThrow: false, x)

test/IRGen/async/class_resilience.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,18 @@ import resilient_class
88
open class MyBaseClass<T> {
99
var value: T
1010

11+
open func wait() async -> Int {
12+
return 0
13+
}
14+
1115
open func wait() async -> T {
1216
return value
1317
}
1418

19+
open func waitThrows() async throws -> Int {
20+
return 0
21+
}
22+
1523
open func waitThrows() async throws -> T {
1624
return value
1725
}

test/IRGen/async/protocol_resilience.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,13 @@ import resilient_protocol
77

88
public protocol MyAwaitable {
99
associatedtype Result
10+
11+
func wait() async -> Int
12+
1013
func wait() async -> Result
1114

15+
func waitThrows() async throws -> Int
16+
1217
func waitThrows() async throws -> Result
1318

1419
// FIXME

0 commit comments

Comments
 (0)