Skip to content

Commit 4b33f26

Browse files
committed
Reserve a mangling for predefined completion handler impls in the runtime.
To manage code size in user binaries, we want to be able to implement common completion handler signatures in the Swift runtime once. Using a different mangling for these lets us add new ones without clobbering symbols in existing binaries.
1 parent e7ec8c3 commit 4b33f26

File tree

10 files changed

+44
-18
lines changed

10 files changed

+44
-18
lines changed

docs/ABI/Mangling.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ types where the metadata itself has unknown layout.)
220220
global ::= from-type to-type generic-signature? 'TR' // reabstraction thunk
221221
global ::= from-type to-type generic-signature? 'TR' // reabstraction thunk
222222
global ::= impl-function-type type 'Tz' // objc-to-swift-async completion handler block implementation
223+
global ::= impl-function-type type 'TZ' // objc-to-swift-async completion handler block implementation (predefined by runtime)
223224
global ::= from-type to-type self-type generic-signature? 'Ty' // reabstraction thunk with dynamic 'Self' capture
224225
global ::= from-type to-type generic-signature? 'Tr' // obsolete mangling for reabstraction thunk
225226
global ::= entity generic-signature? type type* 'TK' // key path getter

include/swift/AST/ASTMangler.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,14 @@ class ASTMangler : public Mangler {
155155
Type SelfType,
156156
ModuleDecl *Module);
157157

158+
/// Mangle a completion handler block implementation function, used for importing ObjC
159+
/// APIs as async.
160+
///
161+
/// - If `predefined` is true, this mangles the symbol name of the completion handler
162+
/// predefined in the Swift runtime for the given type signature.
158163
std::string mangleObjCAsyncCompletionHandlerImpl(CanSILFunctionType BlockType,
159-
CanType ResultType);
164+
CanType ResultType,
165+
bool predefined);
160166

161167
/// Mangle the derivative function (JVP/VJP) for the given:
162168
/// - Mangled original function name.

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ NODE(NominalTypeDescriptor)
160160
NODE(NonObjCAttribute)
161161
NODE(Number)
162162
NODE(ObjCAsyncCompletionHandlerImpl)
163+
NODE(PredefinedObjCAsyncCompletionHandlerImpl)
163164
NODE(ObjCAttribute)
164165
NODE(ObjCBlock)
165166
NODE(EscapingObjCBlock)

lib/AST/ASTMangler.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -396,11 +396,12 @@ std::string ASTMangler::mangleReabstractionThunkHelper(
396396

397397
std::string ASTMangler::mangleObjCAsyncCompletionHandlerImpl(
398398
CanSILFunctionType BlockType,
399-
CanType ResultType) {
399+
CanType ResultType,
400+
bool predefined) {
400401
beginMangling();
401402
appendType(BlockType);
402403
appendType(ResultType);
403-
appendOperator("Tz");
404+
appendOperator(predefined ? "TZ" : "Tz");
404405
return finalize();
405406
}
406407

lib/Demangling/Demangler.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2263,10 +2263,13 @@ NodePointer Demangler::popProtocolConformance() {
22632263
NodePointer type = popNode(Node::Kind::Type);
22642264
return createWithChild(Node::Kind::CoroutineContinuationPrototype, type);
22652265
}
2266-
case 'z': {
2266+
case 'z':
2267+
case 'Z': {
22672268
NodePointer resultType = popNode(Node::Kind::Type);
22682269
NodePointer implType = popNode(Node::Kind::Type);
2269-
return createWithChildren(Node::Kind::ObjCAsyncCompletionHandlerImpl,
2270+
return createWithChildren(c == 'z'
2271+
? Node::Kind::ObjCAsyncCompletionHandlerImpl
2272+
: Node::Kind::PredefinedObjCAsyncCompletionHandlerImpl,
22702273
implType, resultType);
22712274
}
22722275
case 'V': {

lib/Demangling/NodePrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,7 @@ class NodePrinter {
455455
case Node::Kind::PartialApplyForwarder:
456456
case Node::Kind::PartialApplyObjCForwarder:
457457
case Node::Kind::PostfixOperator:
458+
case Node::Kind::PredefinedObjCAsyncCompletionHandlerImpl:
458459
case Node::Kind::PrefixOperator:
459460
case Node::Kind::PrivateDeclName:
460461
case Node::Kind::PropertyDescriptor:
@@ -2533,6 +2534,9 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
25332534
Printer << ')';
25342535
}
25352536
return nullptr;
2537+
case Node::Kind::PredefinedObjCAsyncCompletionHandlerImpl:
2538+
Printer << "predefined ";
2539+
LLVM_FALLTHROUGH;
25362540
case Node::Kind::ObjCAsyncCompletionHandlerImpl:
25372541
Printer << "@objc completion handler block implementation for ";
25382542
print(Node->getChild(0));

lib/Demangling/OldRemangler.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2166,6 +2166,9 @@ void Remangler::mangleGlobalVariableOnceFunction(Node *node) {
21662166
void Remangler::mangleGlobalVariableOnceDeclList(Node *node) {
21672167
unreachable("unsupported");
21682168
}
2169+
void Remangler::manglePredefinedObjCAsyncCompletionHandlerImpl(Node *node) {
2170+
unreachable("unsupported");
2171+
}
21692172
void Remangler::mangleObjCAsyncCompletionHandlerImpl(Node *node) {
21702173
unreachable("unsupported");
21712174
}

lib/Demangling/Remangler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,11 @@ void Remangler::mangleCoroutineContinuationPrototype(Node *node) {
805805
Buffer << "TC";
806806
}
807807

808+
void Remangler::manglePredefinedObjCAsyncCompletionHandlerImpl(Node *node) {
809+
mangleChildNodes(node);
810+
Buffer << "TZ";
811+
}
812+
808813
void Remangler::mangleObjCAsyncCompletionHandlerImpl(Node *node) {
809814
mangleChildNodes(node);
810815
Buffer << "Tz";

lib/SILGen/SILGenThunk.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ SILGenModule::getOrCreateForeignAsyncCompletionHandlerImplFunction(
171171

172172
Mangle::ASTMangler Mangler;
173173
auto name = Mangler.mangleObjCAsyncCompletionHandlerImpl(blockType,
174-
resumeType);
174+
resumeType,
175+
/*predefined*/ false);
175176

176177
SILGenFunctionBuilder builder(*this);
177178
auto F = builder.getOrCreateSharedFunction(loc, name, implTy,

test/SILGen/objc_async.swift

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ func testSlowServer(slowServer: SlowServer) async throws {
1111
// CHECK: [[CONT:%.*]] = get_async_continuation_addr $Int, [[RESUME_BUF]]
1212
// CHECK: [[BLOCK_STORAGE:%.*]] = alloc_stack $@block_storage UnsafeContinuation<Int>
1313
// CHECK: [[CONT_SLOT:%.*]] = project_block_storage [[BLOCK_STORAGE]]
14-
// CHECK: store [[CONT]] to [[CONT_SLOT]]
15-
// CHECK: [[BLOCK_IMPL:%.*]] = %20 = function_ref @{{.*}} : $@convention(c) (@inout_aliasable @block_storage UnsafeContinuation<Int>, Int) -> ()
14+
// CHECK: store [[CONT]] to [trivial] [[CONT_SLOT]]
15+
// CHECK: [[BLOCK_IMPL:%.*]] = function_ref @{{.*}} : $@convention(c) (@inout_aliasable @block_storage UnsafeContinuation<Int>, Int) -> ()
1616
// CHECK: [[BLOCK:%.*]] = init_block_storage_header [[BLOCK_STORAGE]] {{.*}}, invoke [[BLOCK_IMPL]]
1717
// CHECK: apply [[METHOD]]({{.*}}, [[BLOCK]], %0)
1818
// CHECK: await_async_continuation [[CONT]] {{.*}}, resume [[RESUME:bb[0-9]+]]
@@ -21,26 +21,27 @@ func testSlowServer(slowServer: SlowServer) async throws {
2121
// CHECK: dealloc_stack [[RESUME_BUF]]
2222
let _: Int = await slowServer.doSomethingSlow("mail")
2323

24-
// CHECK: [[RESUME_BUF:%.*]] = alloc_stack $Optional<String>
24+
// CHECK: [[RESUME_BUF:%.*]] = alloc_stack $String
2525
// CHECK: [[METHOD:%.*]] = objc_method {{.*}} $@convention(objc_method) (@convention(block) (Optional<NSString>, Optional<NSError>) -> (), SlowServer) -> ()
26-
// CHECK: [[CONT:%.*]] = get_async_continuation_addr $Optional<String>, [[RESUME_BUF]]
27-
// CHECK: [[BLOCK_STORAGE:%.*]] = alloc_stack $@block_storage UnsafeContinuation<Optional<String>>
26+
// CHECK: [[CONT:%.*]] = get_async_continuation_addr [throws] $String, [[RESUME_BUF]]
27+
// CHECK: [[BLOCK_STORAGE:%.*]] = alloc_stack $@block_storage UnsafeThrowingContinuation<String>
2828
// CHECK: [[CONT_SLOT:%.*]] = project_block_storage [[BLOCK_STORAGE]]
29-
// CHECK: store [[CONT]] to [[CONT_SLOT]]
30-
// CHECK: [[BLOCK_IMPL:%.*]] = %20 = function_ref @{{.*}} : $@convention(c) (@inout_aliasable @block_storage UnsafeContinuation<Optional<String>>, Optional<NSString>, Optional<NSError>) -> ()
29+
// CHECK: store [[CONT]] to [trivial] [[CONT_SLOT]]
30+
// CHECK: [[BLOCK_IMPL:%.*]] = function_ref @{{.*}} : $@convention(c) (@inout_aliasable @block_storage UnsafeThrowingContinuation<String>, Optional<NSString>, Optional<NSError>) -> ()
3131
// CHECK: [[BLOCK:%.*]] = init_block_storage_header [[BLOCK_STORAGE]] {{.*}}, invoke [[BLOCK_IMPL]]
32-
// CHECK: apply [[METHOD]]({{.*}}, [[BLOCK]], %0)
32+
// CHECK: apply [[METHOD]]([[BLOCK]], %0)
3333
// CHECK: await_async_continuation [[CONT]] {{.*}}, resume [[RESUME:bb[0-9]+]], error [[ERROR:bb[0-9]+]]
3434
// CHECK: [[RESUME]]:
3535
// CHECK: [[RESULT:%.*]] = load [take] [[RESUME_BUF]]
3636
// CHECK: destroy_value [[RESULT]]
3737
// CHECK: dealloc_stack [[RESUME_BUF]]
38+
let _: String = try await slowServer.findAnswer()
39+
40+
// CHECK: objc_method {{.*}} $@convention(objc_method) (NSString, @convention(block) () -> (), SlowServer) -> ()
41+
await slowServer.serverRestart("somewhere")
42+
3843
// CHECK: [[ERROR]]([[ERROR_VALUE:%.*]] : @owned $Error):
3944
// CHECK: dealloc_stack [[RESUME_BUF]]
4045
// CHECK: throw [[ERROR_VALUE]]
4146

42-
let _: String? = try await slowServer.findAnswer()
43-
44-
// CHECK: objc_method {{.*}} $@convention(objc_method) (NSString, @convention(block) () -> (), SlowServer) -> ()
45-
await slowServer.serverRestart("somewhere")
4647
}

0 commit comments

Comments
 (0)