Skip to content

Commit 4cb8453

Browse files
committed
[SILGen] Used formal type when bridging continuation arguments.
Address a FIXME where lowered types rather than formal types were used when converting from objc to native types which resulted in a failure to convert block types.
1 parent 3040136 commit 4cb8453

File tree

10 files changed

+105
-60
lines changed

10 files changed

+105
-60
lines changed

include/swift/SIL/AbstractionPattern.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,6 +1379,13 @@ class AbstractionPattern {
13791379
/// Swift type.
13801380
AbstractionPattern getObjCMethodAsyncCompletionHandlerType(
13811381
CanType swiftCompletionHandlerType) const;
1382+
1383+
/// If this pattern refers to a foreign ObjC method that was imported as
1384+
/// async, return the bridged-back-to-ObjC completion handler type.
1385+
CanType getObjCMethodAsyncCompletionHandlerForeignType(
1386+
ForeignAsyncConvention convention,
1387+
Lowering::TypeConverter &TC
1388+
) const;
13821389

13831390
void dump() const LLVM_ATTRIBUTE_USED;
13841391
void print(raw_ostream &OS) const;

lib/SIL/IR/AbstractionPattern.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,30 @@ AbstractionPattern::getObjCMethodAsyncCompletionHandlerType(
664664
llvm_unreachable("covered switch");
665665
}
666666

667+
668+
CanType AbstractionPattern::getObjCMethodAsyncCompletionHandlerForeignType(
669+
ForeignAsyncConvention convention,
670+
Lowering::TypeConverter &TC
671+
) const {
672+
auto nativeCHTy = convention.completionHandlerType();
673+
674+
// Use the abstraction pattern we're lowering against in order to lower
675+
// the completion handler type, so we can preserve C/ObjC distinctions that
676+
// normally get abstracted away by the importer.
677+
auto completionHandlerNativeOrigTy = getObjCMethodAsyncCompletionHandlerType(nativeCHTy);
678+
679+
// Bridge the Swift completion handler type back to its
680+
// foreign representation.
681+
auto foreignCHTy = TC.getLoweredBridgedType(completionHandlerNativeOrigTy,
682+
nativeCHTy,
683+
Bridgeability::Full,
684+
SILFunctionTypeRepresentation::ObjCMethod,
685+
TypeConverter::ForArgument)
686+
->getCanonicalType();
687+
688+
return foreignCHTy;
689+
}
690+
667691
AbstractionPattern
668692
AbstractionPattern::getFunctionParamType(unsigned index) const {
669693
switch (getKind()) {

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1675,25 +1675,9 @@ class DestructureInputs {
16751675
|| NextOrigParamIndex != Foreign.Async->completionHandlerParamIndex())
16761676
return false;
16771677

1678-
auto nativeCHTy = Foreign.Async->completionHandlerType();
1679-
1680-
// Use the abstraction pattern we're lowering against in order to lower
1681-
// the completion handler type, so we can preserve C/ObjC distinctions that
1682-
// normally get abstracted away by the importer.
1683-
auto completionHandlerNativeOrigTy = TopLevelOrigType
1684-
.getObjCMethodAsyncCompletionHandlerType(nativeCHTy);
1685-
1686-
// Bridge the Swift completion handler type back to its
1687-
// foreign representation.
1688-
auto foreignCHTy = TC.getLoweredBridgedType(completionHandlerNativeOrigTy,
1689-
nativeCHTy,
1690-
Bridgeability::Full,
1691-
SILFunctionTypeRepresentation::ObjCMethod,
1692-
TypeConverter::ForArgument)
1693-
->getCanonicalType();
1694-
1695-
auto completionHandlerOrigTy = TopLevelOrigType
1696-
.getObjCMethodAsyncCompletionHandlerType(foreignCHTy);
1678+
CanType foreignCHTy = TopLevelOrigType
1679+
.getObjCMethodAsyncCompletionHandlerForeignType(Foreign.Async.getValue(), TC);
1680+
auto completionHandlerOrigTy = TopLevelOrigType.getObjCMethodAsyncCompletionHandlerType(foreignCHTy);
16971681
auto completionHandlerTy = TC.getLoweredType(completionHandlerOrigTy,
16981682
foreignCHTy, expansion)
16991683
.getASTType();

lib/SILGen/Callee.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ namespace Lowering {
2323

2424
class CalleeTypeInfo {
2525
public:
26+
Optional<AbstractionPattern> origFormalType;
2627
CanSILFunctionType substFnType;
2728
Optional<AbstractionPattern> origResultType;
2829
CanType substResultType;
@@ -45,17 +46,18 @@ class CalleeTypeInfo {
4546
const Optional<ForeignAsyncConvention> &foreignAsync,
4647
ImportAsMemberStatus foreignSelf,
4748
Optional<SILFunctionTypeRepresentation> overrideRep = None)
48-
: substFnType(substFnType), origResultType(origResultType),
49-
substResultType(substResultType),
50-
foreign{foreignError, foreignAsync, foreignSelf},
49+
: origFormalType(llvm::None), substFnType(substFnType),
50+
origResultType(origResultType),
51+
substResultType(substResultType), foreign{foreignError, foreignAsync,
52+
foreignSelf},
5153
overrideRep(overrideRep) {}
5254

5355
CalleeTypeInfo(CanSILFunctionType substFnType,
5456
AbstractionPattern origResultType, CanType substResultType,
5557
Optional<SILFunctionTypeRepresentation> overrideRep = None)
56-
: substFnType(substFnType), origResultType(origResultType),
57-
substResultType(substResultType), foreign(),
58-
overrideRep(overrideRep) {}
58+
: origFormalType(llvm::None), substFnType(substFnType),
59+
origResultType(origResultType), substResultType(substResultType),
60+
foreign(), overrideRep(overrideRep) {}
5961

6062
SILFunctionTypeRepresentation getOverrideRep() const {
6163
return overrideRep.getValueOr(substFnType->getRepresentation());

lib/SILGen/ResultPlan.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -475,10 +475,11 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
475475
SmallVectorImpl<SILValue> &outList) const override {
476476
// A foreign async function shouldn't have any indirect results.
477477
}
478-
478+
479479
ManagedValue
480-
emitForeignAsyncCompletionHandler(SILGenFunction &SGF, SILLocation loc)
481-
override {
480+
emitForeignAsyncCompletionHandler(SILGenFunction &SGF,
481+
AbstractionPattern origFormalType,
482+
SILLocation loc) override {
482483
// Get the current continuation for the task.
483484
bool throws = calleeTypeInfo.foreign.async
484485
->completionHandlerErrorParamIndex().hasValue();
@@ -527,13 +528,12 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
527528
auto env = SGF.F.getGenericEnvironment();
528529
auto sig = env ? env->getGenericSignature()->getCanonicalSignature()
529530
: CanGenericSignature();
530-
SILFunction *impl = SGF.SGM
531-
.getOrCreateForeignAsyncCompletionHandlerImplFunction(
532-
cast<SILFunctionType>(impFnTy->mapTypeOutOfContext()
533-
->getCanonicalType(sig)),
534-
continuationTy->mapTypeOutOfContext()->getCanonicalType(sig),
535-
sig,
536-
*calleeTypeInfo.foreign.async);
531+
SILFunction *impl =
532+
SGF.SGM.getOrCreateForeignAsyncCompletionHandlerImplFunction(
533+
cast<SILFunctionType>(
534+
impFnTy->mapTypeOutOfContext()->getCanonicalType(sig)),
535+
continuationTy->mapTypeOutOfContext()->getCanonicalType(sig),
536+
origFormalType, sig, *calleeTypeInfo.foreign.async);
537537
auto impRef = SGF.B.createFunctionRef(loc, impl);
538538

539539
// Initialize the block object for the completion handler.
@@ -551,7 +551,7 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
551551
// _Block_copy-ing it.
552552
return ManagedValue::forUnmanaged(block);
553553
}
554-
554+
555555
RValue finish(SILGenFunction &SGF, SILLocation loc, CanType substType,
556556
ArrayRef<ManagedValue> &directResults) override {
557557
// There should be no direct results from the call.

lib/SILGen/ResultPlan.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ class ResultPlan {
4949
emitForeignErrorArgument(SILGenFunction &SGF, SILLocation loc) {
5050
return None;
5151
}
52-
53-
virtual ManagedValue
54-
emitForeignAsyncCompletionHandler(SILGenFunction &SGF, SILLocation loc) {
52+
53+
virtual ManagedValue emitForeignAsyncCompletionHandler(
54+
SILGenFunction &SGF, AbstractionPattern origFormalType, SILLocation loc) {
5555
return {};
5656
}
5757
};

lib/SILGen/SILGen.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,9 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
182182
/// implementation function for an ObjC API that was imported
183183
/// as `async` in Swift.
184184
SILFunction *getOrCreateForeignAsyncCompletionHandlerImplFunction(
185-
CanSILFunctionType blockType,
186-
CanType continuationTy,
187-
CanGenericSignature sig,
188-
ForeignAsyncConvention convention);
185+
CanSILFunctionType blockType, CanType continuationTy,
186+
AbstractionPattern origFormalType, CanGenericSignature sig,
187+
ForeignAsyncConvention convention);
189188

190189
/// Determine whether the given class has any instance variables that
191190
/// need to be destroyed.

lib/SILGen/SILGenApply.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3893,6 +3893,8 @@ RValue CallEmission::applyNormalCall(SGFContext C) {
38933893
// Get the callee type information.
38943894
auto calleeTypeInfo = callee.getTypeInfo(SGF);
38953895

3896+
calleeTypeInfo.origFormalType = origFormalType;
3897+
38963898
// In C language modes, substitute the type of the AbstractionPattern
38973899
// so that we won't see type parameters down when we try to form bridging
38983900
// conversions.
@@ -3910,6 +3912,8 @@ RValue CallEmission::applyNormalCall(SGFContext C) {
39103912
calleeTypeInfo.substResultType = formalType.getResult();
39113913

39123914
if (selfArg.hasValue() && callSite.hasValue()) {
3915+
calleeTypeInfo.origFormalType =
3916+
calleeTypeInfo.origFormalType->getFunctionResultType();
39133917
calleeTypeInfo.origResultType =
39143918
calleeTypeInfo.origResultType->getFunctionResultType();
39153919
calleeTypeInfo.substResultType =
@@ -4395,7 +4399,9 @@ RValue SILGenFunction::emitApply(ResultPlanPtr &&resultPlan,
43954399
// we left during the first pass.
43964400
auto &completionArgSlot = const_cast<ManagedValue &>(args[completionIndex]);
43974401

4398-
completionArgSlot = resultPlan->emitForeignAsyncCompletionHandler(*this, loc);
4402+
auto origFormalType = *calleeTypeInfo.origFormalType;
4403+
completionArgSlot = resultPlan->emitForeignAsyncCompletionHandler(
4404+
*this, origFormalType, loc);
43994405

44004406
} else if (auto foreignError = calleeTypeInfo.foreign.error) {
44014407
unsigned errorParamIndex =

lib/SILGen/SILGenBridging.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2387,6 +2387,8 @@ void SILGenFunction::emitForeignToNativeThunk(SILDeclRef thunk) {
23872387
foreignError,
23882388
foreignAsync,
23892389
ImportAsMemberStatus());
2390+
calleeTypeInfo.origFormalType =
2391+
foreignCI.FormalPattern.getFunctionResultType();
23902392

23912393
auto init = indirectResult
23922394
? useBufferAsTemporary(indirectResult,

lib/SILGen/SILGenThunk.cpp

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -188,15 +188,28 @@ static const clang::Type *prependParameterType(
188188
return clangCtx.getPointerType(newFnTy).getTypePtr();
189189
}
190190

191-
SILFunction *
192-
SILGenModule::getOrCreateForeignAsyncCompletionHandlerImplFunction(
193-
CanSILFunctionType blockType,
194-
CanType continuationTy,
195-
CanGenericSignature sig,
196-
ForeignAsyncConvention convention) {
191+
SILFunction *SILGenModule::getOrCreateForeignAsyncCompletionHandlerImplFunction(
192+
CanSILFunctionType blockType, CanType continuationTy,
193+
AbstractionPattern origFormalType, CanGenericSignature sig,
194+
ForeignAsyncConvention convention) {
197195
// Extract the result and error types from the continuation type.
198196
auto resumeType = cast<BoundGenericType>(continuationTy).getGenericArgs()[0];
199197

198+
CanAnyFunctionType completionHandlerOrigTy = [&]() {
199+
auto completionHandlerOrigTy =
200+
origFormalType.getObjCMethodAsyncCompletionHandlerForeignType(convention, Types);
201+
Optional<CanAnyFunctionType> maybeCompletionHandlerOrigTy;
202+
if (auto fnTy =
203+
dyn_cast<AnyFunctionType>(completionHandlerOrigTy)) {
204+
maybeCompletionHandlerOrigTy = fnTy;
205+
} else {
206+
maybeCompletionHandlerOrigTy = cast<AnyFunctionType>(
207+
completionHandlerOrigTy.getOptionalObjectType());
208+
}
209+
return maybeCompletionHandlerOrigTy.getValue();
210+
}();
211+
auto blockParams = completionHandlerOrigTy.getParams();
212+
200213
// Build up the implementation function type, which matches the
201214
// block signature with an added block storage argument that points at the
202215
// block buffer. The block storage holds the continuation we feed the
@@ -214,7 +227,7 @@ SILGenModule::getOrCreateForeignAsyncCompletionHandlerImplFunction(
214227
getASTContext(),
215228
blockType->getClangTypeInfo().getType(),
216229
getASTContext().getClangTypeForIRGen(blockStorageTy));
217-
230+
218231
auto implTy = SILFunctionType::get(sig,
219232
blockType->getExtInfo().intoBuilder()
220233
.withRepresentation(SILFunctionTypeRepresentation::CFunctionPointer)
@@ -362,15 +375,13 @@ SILGenModule::getOrCreateForeignAsyncCompletionHandlerImplFunction(
362375
auto resumeArgBuf = SGF.emitTemporaryAllocation(loc,
363376
loweredResumeTy.getAddressType());
364377

365-
auto prepareArgument = [&](SILValue destBuf, ManagedValue arg) {
378+
auto prepareArgument = [&](SILValue destBuf, CanType destFormalType,
379+
ManagedValue arg, CanType argFormalType) {
366380
// Convert the ObjC argument to the bridged Swift representation we
367381
// want.
368-
ManagedValue bridgedArg = SGF.emitBridgedToNativeValue(loc,
369-
arg.copy(SGF, loc),
370-
arg.getType().getASTType(),
371-
// FIXME: pass down formal type
372-
destBuf->getType().getASTType(),
373-
destBuf->getType().getObjectType());
382+
ManagedValue bridgedArg = SGF.emitBridgedToNativeValue(
383+
loc, arg.copy(SGF, loc), argFormalType, destFormalType,
384+
destBuf->getType().getObjectType());
374385
// Force-unwrap an argument that comes to us as Optional if it's
375386
// formally non-optional in the return.
376387
if (bridgedArg.getType().getOptionalObjectType()
@@ -401,12 +412,22 @@ SILGenModule::getOrCreateForeignAsyncCompletionHandlerImplFunction(
401412
for (unsigned i : indices(resumeTuple.getElementTypes())) {
402413
auto resumeEltBuf = SGF.B.createTupleElementAddr(loc,
403414
resumeArgBuf, i);
404-
prepareArgument(resumeEltBuf, params[paramIndices[i]]);
415+
prepareArgument(
416+
/*destBuf*/ resumeEltBuf,
417+
/*destFormalType*/
418+
F->mapTypeIntoContext(resumeTuple.getElementTypes()[i])
419+
->getCanonicalType(),
420+
/*arg*/ params[paramIndices[i]],
421+
/*argFormalType*/ blockParams[i].getParameterType());
405422
}
406423
} else {
407424
assert(paramIndices.size() == 1);
408425
assert(params.size() == 2 + (bool)errorIndex + (bool)flagIndex);
409-
prepareArgument(resumeArgBuf, params[paramIndices[0]]);
426+
prepareArgument(/*destBuf*/ resumeArgBuf,
427+
/*destFormalType*/
428+
F->mapTypeIntoContext(resumeType)->getCanonicalType(),
429+
/*arg*/ params[paramIndices[0]],
430+
/*argFormalType*/ blockParams[0].getParameterType());
410431
}
411432

412433
// Resume the continuation with the composed bridged result.

0 commit comments

Comments
 (0)