Skip to content

Commit 390dd28

Browse files
authored
Merge pull request #34740 from nate-chandler/concurrency/irgen/rdar71260862
[Async CC] Resolve metadata from class instances.
2 parents 60b052c + e276472 commit 390dd28

File tree

4 files changed

+98
-9
lines changed

4 files changed

+98
-9
lines changed

lib/IRGen/GenThunk.cpp

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "ClassMetadataVisitor.h"
2121
#include "ConstantBuilder.h"
2222
#include "Explosion.h"
23+
#include "GenCall.h"
2324
#include "GenClass.h"
2425
#include "GenDecl.h"
2526
#include "GenHeap.h"
@@ -31,6 +32,7 @@
3132
#include "MetadataLayout.h"
3233
#include "ProtocolInfo.h"
3334
#include "Signature.h"
35+
#include "swift/AST/GenericEnvironment.h"
3436
#include "swift/IRGen/Linking.h"
3537
#include "swift/SIL/SILDeclRef.h"
3638
#include "llvm/IR/Function.h"
@@ -79,14 +81,32 @@ static FunctionPointer lookupMethod(IRGenFunction &IGF, SILDeclRef declRef) {
7981
// Load the metadata, or use the 'self' value if we have a static method.
8082
llvm::Value *self;
8183

82-
// Non-throwing class methods always have the 'self' parameter at the end.
83-
// Throwing class methods have 'self' right before the error parameter.
84-
//
85-
// FIXME: Should find a better way of expressing this.
86-
if (funcTy->hasErrorResult())
87-
self = (IGF.CurFn->arg_end() - 2);
88-
else
89-
self = (IGF.CurFn->arg_end() - 1);
84+
if (funcTy->isAsync()) {
85+
auto originalType = funcTy;
86+
auto forwardingSubstitutionMap =
87+
decl->getGenericEnvironment()
88+
? decl->getGenericEnvironment()->getForwardingSubstitutionMap()
89+
: SubstitutionMap();
90+
auto substitutedType = originalType->substGenericArgs(
91+
IGF.IGM.getSILModule(), forwardingSubstitutionMap,
92+
IGF.IGM.getMaximalTypeExpansionContext());
93+
auto layout = getAsyncContextLayout(IGF.IGM, originalType, substitutedType,
94+
forwardingSubstitutionMap);
95+
assert(layout.hasLocalContext());
96+
auto context = layout.emitCastTo(IGF, IGF.getAsyncContext());
97+
auto localContextAddr =
98+
layout.getLocalContextLayout().project(IGF, context, llvm::None);
99+
self = IGF.Builder.CreateLoad(localContextAddr);
100+
} else {
101+
// Non-throwing class methods always have the 'self' parameter at the end.
102+
// Throwing class methods have 'self' right before the error parameter.
103+
//
104+
// FIXME: Should find a better way of expressing this.
105+
if (funcTy->hasErrorResult())
106+
self = (IGF.CurFn->arg_end() - 2);
107+
else
108+
self = (IGF.CurFn->arg_end() - 1);
109+
}
90110

91111
auto selfTy = funcTy->getSelfParameter().getSILStorageType(
92112
IGF.IGM.getSILModule(), funcTy, IGF.IGM.getMaximalTypeExpansionContext());
@@ -109,13 +129,15 @@ void IRGenModule::emitDispatchThunk(SILDeclRef declRef) {
109129
}
110130

111131
IRGenFunction IGF(*this, f);
132+
IGF.setAsync(declRef.getAbstractFunctionDecl()->hasAsync());
112133

113134
// Look up the method.
114135
auto fn = lookupMethod(IGF, declRef);
115136

116137
// Call the witness, forwarding all of the parameters.
117138
auto params = IGF.collectParameters();
118-
auto result = IGF.Builder.CreateCall(fn, params.claimAll());
139+
auto result =
140+
IGF.Builder.CreateCall(fn.getAsFunction(IGF), params.claimAll());
119141

120142
// Return the result, if we have one.
121143
if (result->getType()->isVoidTy())
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import _Concurrency
2+
3+
public class Clazz {
4+
public init() {}
5+
public func classinstanceVoidToVoid() async {
6+
print(self)
7+
}
8+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift-dylib(%t/%target-library-name(PrintShims)) %S/../../Inputs/print-shims.swift -module-name PrintShims -emit-module -emit-module-path %t/PrintShims.swiftmodule
3+
// RUN: %target-codesign %t/%target-library-name(PrintShims)
4+
// RUN: %target-build-swift-dylib(%t/%target-library-name(ResilientClass)) %S/Inputs/class-1instance-void_to_void.swift -Xfrontend -enable-experimental-concurrency -module-name ResilientClass -emit-module -emit-module-path %t/ResilientClass.swiftmodule
5+
// RUN: %target-codesign %t/%target-library-name(ResilientClass)
6+
// RUN: %target-build-swift -Xfrontend -enable-experimental-concurrency -parse-sil %s -emit-ir -I %t -L %t -lPrintShim -lResilientClass | %FileCheck %s --check-prefix=CHECK-LL
7+
// RUN: %target-build-swift -Xfrontend -enable-experimental-concurrency -parse-sil %s -module-name main -o %t/main -I %t -L %t -lPrintShims -lResilientClass %target-rpath(%t)
8+
// RUN: %target-codesign %t/main
9+
// RUN: %target-run %t/main %t/%target-library-name(PrintShims) %t/%target-library-name(ResilientClass) | %FileCheck %s
10+
11+
// REQUIRES: executable_test
12+
// REQUIRES: swift_test_mode_optimize_none
13+
// REQUIRES: concurrency
14+
// UNSUPPORTED: use_os_stdlib
15+
// UNSUPPORTED: CPU=arm64e
16+
17+
18+
import Builtin
19+
import Swift
20+
import PrintShims
21+
import _Concurrency
22+
import ResilientClass
23+
24+
sil public_external [exact_self_class] @$s14ResilientClass5ClazzCACycfC : $@convention(method) (@thick Clazz.Type) -> @owned Clazz
25+
26+
// Defined in _Concurrency
27+
sil public_external @$s12_Concurrency8runAsyncyyyyYcF : $@convention(thin) (@guaranteed @async @callee_guaranteed () -> ()) -> ()
28+
29+
// CHECK-LL: define{{( dllexport)?}}{{( protected)?}} swiftcc void @test_case(%swift.task* {{%[0-9]+}}, %swift.executor* {{%[0-9]+}}, %swift.context* {{%[0-9]+}}) {{#[0-9]*}} {
30+
sil @test_case : $@convention(thin) @async () -> () {
31+
%s_type = metatype $@thick Clazz.Type
32+
%allocating_init = function_ref @$s14ResilientClass5ClazzCACycfC : $@convention(method) (@thick Clazz.Type) -> @owned Clazz
33+
%instance = apply %allocating_init(%s_type) : $@convention(method) (@thick Clazz.Type) -> @owned Clazz
34+
%classinstanceVoidToVoid = class_method %instance : $Clazz, #Clazz.classinstanceVoidToVoid : (Clazz) -> () async -> (), $@convention(method) @async (@guaranteed Clazz) -> ()
35+
strong_retain %instance : $Clazz
36+
%result = apply %classinstanceVoidToVoid(%instance) : $@convention(method) @async (@guaranteed Clazz) -> () // CHECK: ResilientClass.Clazz
37+
strong_release %instance : $Clazz
38+
39+
%out = tuple ()
40+
return %out : $()
41+
}
42+
43+
sil @main : $@async @convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
44+
bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
45+
46+
%2 = function_ref @test_case : $@convention(thin) @async () -> ()
47+
%3 = thin_to_thick_function %2 : $@convention(thin) @async () -> () to $@async @callee_guaranteed () -> ()
48+
%4 = function_ref @$s12_Concurrency8runAsyncyyyyYcF : $@convention(thin) (@guaranteed @async @callee_guaranteed () -> ()) -> ()
49+
%5 = apply %4(%3) : $@convention(thin) (@guaranteed @async @callee_guaranteed () -> ()) -> ()
50+
51+
%6 = integer_literal $Builtin.Int32, 0
52+
%7 = struct $Int32 (%6 : $Builtin.Int32)
53+
return %7 : $Int32
54+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// RUN: %target-swift-frontend %s -emit-ir -enable-library-evolution -enable-experimental-concurrency
2+
3+
public class X {
4+
public func f() async { }
5+
}

0 commit comments

Comments
 (0)