Skip to content

Commit b508527

Browse files
authored
Merge pull request swiftlang#36006 from jckarter/foreign-async-pseudogeneric
SILGen: Handle pseudogeneric completion-handler-based async APIs.
2 parents 536cabb + eea3a6c commit b508527

File tree

10 files changed

+61
-9
lines changed

10 files changed

+61
-9
lines changed

docs/ABI/Mangling.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,9 @@ types where the metadata itself has unknown layout.)
222222
global ::= from-type to-type generic-signature? 'TR' // reabstraction thunk
223223
global ::= impl-function-type type 'Tz' // objc-to-swift-async completion handler block implementation
224224
global ::= impl-function-type type 'TZ' // objc-to-swift-async completion handler block implementation (predefined by runtime)
225+
global ::= from-type to-type generic-signature? 'TR' // reabstraction thunk
226+
global ::= impl-function-type type generic-signature? 'Tz' // objc-to-swift-async completion handler block implementation
227+
global ::= impl-function-type type generic-signature? 'TZ' // objc-to-swift-async completion handler block implementation (predefined by runtime)
225228
global ::= from-type to-type self-type generic-signature? 'Ty' // reabstraction thunk with dynamic 'Self' capture
226229
global ::= from-type to-type generic-signature? 'Tr' // obsolete mangling for reabstraction thunk
227230
global ::= entity generic-signature? type type* 'TK' // key path getter

include/swift/AST/ASTMangler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ class ASTMangler : public Mangler {
171171
/// predefined in the Swift runtime for the given type signature.
172172
std::string mangleObjCAsyncCompletionHandlerImpl(CanSILFunctionType BlockType,
173173
CanType ResultType,
174+
CanGenericSignature Sig,
174175
bool predefined);
175176

176177
/// Mangle the derivative function (JVP/VJP), or optionally its vtable entry

lib/AST/ASTMangler.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,10 +398,13 @@ std::string ASTMangler::mangleReabstractionThunkHelper(
398398
std::string ASTMangler::mangleObjCAsyncCompletionHandlerImpl(
399399
CanSILFunctionType BlockType,
400400
CanType ResultType,
401+
CanGenericSignature Sig,
401402
bool predefined) {
402403
beginMangling();
403404
appendType(BlockType);
404405
appendType(ResultType);
406+
if (Sig)
407+
appendGenericSignature(Sig);
405408
appendOperator(predefined ? "TZ" : "Tz");
406409
return finalize();
407410
}

lib/Demangling/Demangler.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2301,12 +2301,16 @@ NodePointer Demangler::demangleThunkOrSpecialization() {
23012301
}
23022302
case 'z':
23032303
case 'Z': {
2304+
NodePointer sig = popNode(Node::Kind::DependentGenericSignature);
23042305
NodePointer resultType = popNode(Node::Kind::Type);
23052306
NodePointer implType = popNode(Node::Kind::Type);
2306-
return createWithChildren(c == 'z'
2307+
auto node = createWithChildren(c == 'z'
23072308
? Node::Kind::ObjCAsyncCompletionHandlerImpl
23082309
: Node::Kind::PredefinedObjCAsyncCompletionHandlerImpl,
23092310
implType, resultType);
2311+
if (sig)
2312+
addChild(node, sig);
2313+
return node;
23102314
}
23112315
case 'V': {
23122316
NodePointer Base = popNode(isEntity);

lib/SIL/IR/AbstractionPattern.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,15 @@ AbstractionPattern::getObjCMethodAsyncCompletionHandlerType(
608608
auto callbackParamTy = getObjCMethod()->parameters()[paramIndex]
609609
->getType().getTypePtr();
610610

611-
return AbstractionPattern(swiftCompletionHandlerType, callbackParamTy);
611+
CanGenericSignature patternSig;
612+
if (auto origSig = getGenericSignature()) {
613+
patternSig = origSig;
614+
} else if (auto genFnTy = dyn_cast<GenericFunctionType>(getType())) {
615+
patternSig = genFnTy->getGenericSignature()->getCanonicalSignature();
616+
}
617+
618+
return AbstractionPattern(patternSig,
619+
swiftCompletionHandlerType, callbackParamTy);
612620
}
613621
case Kind::Opaque:
614622
case Kind::OpaqueFunction:

lib/SILGen/ResultPlan.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -524,17 +524,24 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
524524
handlerIsOptional = false;
525525
impFnTy = cast<SILFunctionType>(impTy.getASTType());
526526
}
527+
auto env = SGF.F.getGenericEnvironment();
528+
auto sig = env ? env->getGenericSignature()->getCanonicalSignature()
529+
: CanGenericSignature();
527530
SILFunction *impl = SGF.SGM
528-
.getOrCreateForeignAsyncCompletionHandlerImplFunction(impFnTy,
529-
continuationTy,
530-
*calleeTypeInfo.foreign.async);
531+
.getOrCreateForeignAsyncCompletionHandlerImplFunction(
532+
cast<SILFunctionType>(impFnTy->mapTypeOutOfContext()
533+
->getCanonicalType(sig)),
534+
continuationTy->mapTypeOutOfContext()->getCanonicalType(sig),
535+
sig,
536+
*calleeTypeInfo.foreign.async);
531537
auto impRef = SGF.B.createFunctionRef(loc, impl);
532538

533539
// Initialize the block object for the completion handler.
534540
SILValue block = SGF.B.createInitBlockStorageHeader(loc, blockStorage,
535-
impRef, SILType::getPrimitiveObjectType(impFnTy), {});
541+
impRef, SILType::getPrimitiveObjectType(impFnTy),
542+
SGF.getForwardingSubstitutionMap());
536543

537-
// Wrap it in optional if the callee expects if.
544+
// Wrap it in optional if the callee expects it.
538545
if (handlerIsOptional) {
539546
block = SGF.B.createOptionalSome(loc, block, impTy);
540547
}

lib/SILGen/SILGen.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
181181
SILFunction *getOrCreateForeignAsyncCompletionHandlerImplFunction(
182182
CanSILFunctionType blockType,
183183
CanType continuationTy,
184+
CanGenericSignature sig,
184185
ForeignAsyncConvention convention);
185186

186187
/// Determine whether the given class has any instance variables that

lib/SILGen/SILGenThunk.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ SILFunction *
185185
SILGenModule::getOrCreateForeignAsyncCompletionHandlerImplFunction(
186186
CanSILFunctionType blockType,
187187
CanType continuationTy,
188+
CanGenericSignature sig,
188189
ForeignAsyncConvention convention) {
189190
// Extract the result and error types from the continuation type.
190191
auto resumeType = cast<BoundGenericType>(continuationTy).getGenericArgs()[0];
@@ -207,10 +208,11 @@ SILGenModule::getOrCreateForeignAsyncCompletionHandlerImplFunction(
207208
blockType->getClangTypeInfo().getType(),
208209
getASTContext().getClangTypeForIRGen(blockStorageTy));
209210

210-
auto implTy = SILFunctionType::get(GenericSignature(),
211+
auto implTy = SILFunctionType::get(sig,
211212
blockType->getExtInfo().intoBuilder()
212213
.withRepresentation(SILFunctionTypeRepresentation::CFunctionPointer)
213214
.withClangFunctionType(newClangTy)
215+
.withIsPseudogeneric((bool)sig)
214216
.build(),
215217
SILCoroutineKind::None,
216218
ParameterConvention::Direct_Unowned,
@@ -223,6 +225,7 @@ SILGenModule::getOrCreateForeignAsyncCompletionHandlerImplFunction(
223225
Mangle::ASTMangler Mangler;
224226
auto name = Mangler.mangleObjCAsyncCompletionHandlerImpl(blockType,
225227
resumeType,
228+
sig,
226229
/*predefined*/ false);
227230

228231
SILGenFunctionBuilder builder(*this);
@@ -234,6 +237,9 @@ SILGenModule::getOrCreateForeignAsyncCompletionHandlerImplFunction(
234237

235238
if (F->empty()) {
236239
// Emit the implementation.
240+
if (sig)
241+
F->setGenericEnvironment(sig->getGenericEnvironment());
242+
237243
SILGenFunction SGF(*this, *F, SwiftModule);
238244
{
239245
Scope scope(SGF, loc);
@@ -282,6 +288,8 @@ SILGenModule::getOrCreateForeignAsyncCompletionHandlerImplFunction(
282288
// Resume the continuation as throwing the given error, bridged to a
283289
// native Swift error.
284290
auto nativeError = SGF.emitBridgedToNativeError(loc, matchedError);
291+
Type replacementTypes[]
292+
= {F->mapTypeIntoContext(resumeType)->getCanonicalType()};
285293
auto subs = SubstitutionMap::get(errorIntrinsic->getGenericSignature(),
286294
replacementTypes,
287295
ArrayRef<ProtocolConformanceRef>{});
@@ -296,7 +304,7 @@ SILGenModule::getOrCreateForeignAsyncCompletionHandlerImplFunction(
296304
}
297305

298306
auto loweredResumeTy = SGF.getLoweredType(AbstractionPattern::getOpaque(),
299-
resumeType);
307+
F->mapTypeIntoContext(resumeType));
300308

301309
// Prepare the argument for the resume intrinsic, using the non-error
302310
// arguments to the callback.
@@ -343,6 +351,8 @@ SILGenModule::getOrCreateForeignAsyncCompletionHandlerImplFunction(
343351

344352
// Resume the continuation with the composed bridged result.
345353
ManagedValue resumeArg = SGF.emitManagedBufferWithCleanup(resumeArgBuf);
354+
Type replacementTypes[]
355+
= {F->mapTypeIntoContext(resumeType)->getCanonicalType()};
346356
auto subs = SubstitutionMap::get(resumeIntrinsic->getGenericSignature(),
347357
replacementTypes,
348358
ArrayRef<ProtocolConformanceRef>{});

test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ typedef void ( ^ObjCErrorHandler )( NSError * _Nullable inError );
117117
- (void) myMethod:(NSInteger)value1 foo:(NSInteger)value2;
118118
@end
119119

120+
@interface GenericObject<T> : NSObject
121+
- (void)doSomethingWithCompletionHandler:(void (^)(T _Nullable_result, NSError * _Nullable))completionHandler;
122+
- (void)doAnotherThingWithCompletionHandler:(void (^)(GenericObject<T> *_Nullable))completionHandler;
123+
@end
124+
120125
#define MAGIC_NUMBER 42
121126

122127
#pragma clang assume_nonnull end

test/SILGen/objc_async.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,16 @@ func testSlowServer(slowServer: SlowServer) async throws {
6464
let _: NSObject = try await slowServer.someObject()
6565
}
6666

67+
func testGeneric<T: AnyObject>(x: GenericObject<T>) async throws {
68+
let _: T? = try await x.doSomething()
69+
let _: GenericObject<T>? = await x.doAnotherThing()
70+
}
71+
72+
func testGeneric2<T: AnyObject, U>(x: GenericObject<T>, y: U) async throws {
73+
let _: T? = try await x.doSomething()
74+
let _: GenericObject<T>? = await x.doAnotherThing()
75+
}
76+
6777
// CHECK: sil{{.*}}@[[INT_COMPLETION_BLOCK]]
6878
// CHECK: [[CONT_ADDR:%.*]] = project_block_storage %0
6979
// CHECK: [[CONT:%.*]] = load [trivial] [[CONT_ADDR]]

0 commit comments

Comments
 (0)