Skip to content

Commit d1961e1

Browse files
authored
Merge pull request #71808 from eeckstein/global_async_function_pointers
Support statically initialized global async function pointers
2 parents 97a8148 + 9aff04a commit d1961e1

File tree

3 files changed

+54
-6
lines changed

3 files changed

+54
-6
lines changed

SwiftCompilerSources/Sources/SIL/GlobalVariable.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,6 @@ extension Instruction {
137137
// initializers.
138138
return false
139139
}
140-
case let fri as FunctionRefInst:
141-
// TODO: support async function pointers in static globals.
142-
return !fri.referencedFunction.isAsync
143140
case is StructInst,
144141
is TupleInst,
145142
is EnumInst,
@@ -152,7 +149,8 @@ extension Instruction {
152149
is ConvertFunctionInst,
153150
is ThinToThickFunctionInst,
154151
is AddressToPointerInst,
155-
is GlobalAddrInst:
152+
is GlobalAddrInst,
153+
is FunctionRefInst:
156154
return true
157155
default:
158156
return false

lib/IRGen/GenConstant.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,9 +378,13 @@ Explosion irgen::emitConstantValue(IRGenModule &IGM, SILValue operand,
378378
SILFunction *fn = FRI->getReferencedFunction();
379379

380380
llvm::Constant *fnPtr = IGM.getAddrOfSILFunction(fn, NotForDefinition);
381-
assert(!fn->isAsync() && "TODO: support async functions");
382-
383381
CanSILFunctionType fnType = FRI->getType().getAs<SILFunctionType>();
382+
383+
if (irgen::classifyFunctionPointerKind(fn).isAsyncFunctionPointer()) {
384+
llvm::Constant *asyncFnPtr = IGM.getAddrOfAsyncFunctionPointer(fn);
385+
fnPtr = llvm::ConstantExpr::getBitCast(asyncFnPtr, fnPtr->getType());
386+
}
387+
384388
auto authInfo = PointerAuthInfo::forFunctionPointer(IGM, fnType);
385389
if (authInfo.isSigned()) {
386390
auto constantDiscriminator =
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// RUN: %target-swift-frontend -enable-experimental-feature SymbolLinkageMarkers -emit-sil -disable-availability-checking -parse-as-library %s | %FileCheck %s --check-prefix=CHECK-SIL
2+
// RUN: %target-build-swift -enable-experimental-feature SymbolLinkageMarkers -Xfrontend -disable-availability-checking -Xfrontend -parse-as-library %s -o %t_binary
3+
// RUN: %target-codesign %t_binary
4+
// RUN: %target-run %t_binary | %FileCheck %s --check-prefix=CHECK-EXEC
5+
6+
// REQUIRES: concurrency
7+
// REQUIRES: executable_test
8+
// REQUIRES: OS=macosx || OS=ios
9+
// REQUIRES: swift_in_compiler
10+
11+
// rdar://76038845
12+
// REQUIRES: concurrency_runtime
13+
// UNSUPPORTED: back_deployment_runtime
14+
15+
@MainActor
16+
var foo: Int = 42
17+
18+
func asyncFunc() async {
19+
print("Hello World!")
20+
}
21+
22+
public func callAsync() async {
23+
await asyncFunc()
24+
}
25+
26+
// CHECK-SIL-LABEL: sil_global @$s23global_function_pointer5gfptryyYacvp : $@async @callee_guaranteed () -> () = {
27+
// CHECK-SIL: %0 = function_ref @$s23global_function_pointer9callAsyncyyYaF : $@convention(thin) @async () -> ()
28+
// CHECK-SIL-NEXT: %initval = thin_to_thick_function %0 : $@convention(thin) @async () -> () to $@async @callee_guaranteed () -> ()
29+
// CHECK-SIL-NEXT: }
30+
31+
@_section("__DATA,__mysection")
32+
public var gfptr = callAsync
33+
34+
@main struct MyProgram {
35+
static func main() async throws {
36+
print("\(foo)")
37+
foo += 1
38+
await gfptr()
39+
print("\(foo)")
40+
}
41+
}
42+
43+
// CHECK-EXEC: 42
44+
// CHECK-EXEC-NEXT: Hello World!
45+
// CHECK-EXEC-NEXT: 43
46+

0 commit comments

Comments
 (0)