Skip to content

Commit 871b815

Browse files
authored
Merge pull request swiftlang#23104 from gottesmm/pr-3e4bebe2b149d856f564ac2442e6dd635570d098
2 parents 0d951bf + 5da4638 commit 871b815

File tree

1 file changed

+88
-78
lines changed

1 file changed

+88
-78
lines changed

lib/SILOptimizer/Utils/CastOptimizer.cpp

Lines changed: 88 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,82 @@ static bool canOptimizeCast(const swift::Type &BridgedTargetTy,
319319
return false;
320320
}
321321

322+
static Optional<std::pair<SILFunction *, SubstitutionMap>>
323+
findBridgeToObjCFunc(SILOptFunctionBuilder &functionBuilder,
324+
SILDynamicCastInst dynamicCast) {
325+
CanType sourceType = dynamicCast.getSourceType();
326+
auto loc = dynamicCast.getLocation();
327+
auto &mod = dynamicCast.getModule();
328+
auto bridgedProto =
329+
mod.getASTContext().getProtocol(KnownProtocolKind::ObjectiveCBridgeable);
330+
331+
auto conf = mod.getSwiftModule()->lookupConformance(sourceType, bridgedProto);
332+
assert(conf && "_ObjectiveCBridgeable conformance should exist");
333+
(void)conf;
334+
335+
// Generate code to invoke _bridgeToObjectiveC
336+
337+
auto *ntd = sourceType.getNominalOrBoundGenericNominal();
338+
assert(ntd);
339+
auto members = ntd->lookupDirect(mod.getASTContext().Id_bridgeToObjectiveC);
340+
if (members.empty()) {
341+
SmallVector<ValueDecl *, 4> foundMembers;
342+
if (ntd->getDeclContext()->lookupQualified(
343+
ntd, mod.getASTContext().Id_bridgeToObjectiveC,
344+
NLOptions::NL_ProtocolMembers, foundMembers)) {
345+
// Returned members are starting with the most specialized ones.
346+
// Thus, the first element is what we are looking for.
347+
members.push_back(foundMembers.front());
348+
}
349+
}
350+
351+
// There should be exactly one implementation of _bridgeToObjectiveC.
352+
if (members.size() != 1)
353+
return None;
354+
355+
auto bridgeFuncDecl = members.front();
356+
ModuleDecl *modDecl =
357+
mod.getASTContext().getLoadedModule(mod.getASTContext().Id_Foundation);
358+
if (!modDecl)
359+
return None;
360+
SmallVector<ValueDecl *, 2> results;
361+
modDecl->lookupMember(results, sourceType.getNominalOrBoundGenericNominal(),
362+
mod.getASTContext().Id_bridgeToObjectiveC,
363+
Identifier());
364+
ArrayRef<ValueDecl *> resultsRef(results);
365+
if (resultsRef.empty()) {
366+
mod.getSwiftModule()->lookupMember(
367+
results, sourceType.getNominalOrBoundGenericNominal(),
368+
mod.getASTContext().Id_bridgeToObjectiveC, Identifier());
369+
resultsRef = results;
370+
}
371+
if (resultsRef.size() != 1)
372+
return None;
373+
374+
auto *resultDecl = results.front();
375+
auto memberDeclRef = SILDeclRef(resultDecl);
376+
auto *bridgedFunc = functionBuilder.getOrCreateFunction(
377+
loc, memberDeclRef, ForDefinition_t::NotForDefinition);
378+
379+
// Get substitutions, if source is a bound generic type.
380+
auto subMap = sourceType->getContextSubstitutionMap(
381+
mod.getSwiftModule(), bridgeFuncDecl->getDeclContext());
382+
383+
// Implementation of _bridgeToObjectiveC could not be found.
384+
if (!bridgedFunc)
385+
return None;
386+
387+
if (dynamicCast.getFunction()->isSerialized() &&
388+
!bridgedFunc->hasValidLinkageForFragileRef())
389+
return None;
390+
391+
if (bridgedFunc->getLoweredFunctionType()
392+
->getSingleResult()
393+
.isFormalIndirect())
394+
return None;
395+
return std::make_pair(bridgedFunc, subMap);
396+
}
397+
322398
/// Create a call of _bridgeToObjectiveC which converts an _ObjectiveCBridgeable
323399
/// instance into a bridged ObjC type.
324400
SILInstruction *
@@ -328,7 +404,6 @@ CastOptimizer::optimizeBridgedSwiftToObjCCast(SILDynamicCastInst dynamicCast) {
328404
bool isConditional = dynamicCast.isConditional();
329405
SILValue Src = dynamicCast.getSource();
330406
SILValue Dest = dynamicCast.getDest();
331-
CanType Source = dynamicCast.getSourceType();
332407
CanType BridgedTargetTy = dynamicCast.getBridgedTargetType();
333408
SILBasicBlock *SuccessBB = dynamicCast.getSuccessBlock();
334409
SILBasicBlock *FailureBB = dynamicCast.getFailureBlock();
@@ -341,91 +416,26 @@ CastOptimizer::optimizeBridgedSwiftToObjCCast(SILDynamicCastInst dynamicCast) {
341416
}
342417

343418
// Find the _BridgedToObjectiveC protocol.
344-
auto BridgedProto =
345-
M.getASTContext().getProtocol(KnownProtocolKind::ObjectiveCBridgeable);
346-
347-
auto Conf = M.getSwiftModule()->lookupConformance(Source, BridgedProto);
348-
349-
assert(Conf && "_ObjectiveCBridgeable conformance should exist");
350-
(void)Conf;
351-
352-
// Generate code to invoke _bridgeToObjectiveC
353-
SILBuilderWithScope Builder(Inst, BuilderContext);
354-
355-
auto *NTD = Source.getNominalOrBoundGenericNominal();
356-
assert(NTD);
357-
auto Members = NTD->lookupDirect(M.getASTContext().Id_bridgeToObjectiveC);
358-
if (Members.empty()) {
359-
SmallVector<ValueDecl *, 4> FoundMembers;
360-
if (NTD->getDeclContext()->lookupQualified(
361-
NTD, M.getASTContext().Id_bridgeToObjectiveC,
362-
NLOptions::NL_ProtocolMembers, FoundMembers)) {
363-
// Returned members are starting with the most specialized ones.
364-
// Thus, the first element is what we are looking for.
365-
Members.push_back(FoundMembers.front());
366-
}
367-
}
368-
369-
// There should be exactly one implementation of _bridgeToObjectiveC.
370-
if (Members.size() != 1)
371-
return nullptr;
372-
373-
auto BridgeFuncDecl = Members.front();
374-
auto BridgeFuncDeclRef = SILDeclRef(BridgeFuncDecl);
375-
ModuleDecl *Mod =
376-
M.getASTContext().getLoadedModule(M.getASTContext().Id_Foundation);
377-
if (!Mod)
378-
return nullptr;
379-
SmallVector<ValueDecl *, 2> Results;
380-
Mod->lookupMember(Results, Source.getNominalOrBoundGenericNominal(),
381-
M.getASTContext().Id_bridgeToObjectiveC, Identifier());
382-
ArrayRef<ValueDecl *> ResultsRef(Results);
383-
if (ResultsRef.empty()) {
384-
M.getSwiftModule()->lookupMember(
385-
Results, Source.getNominalOrBoundGenericNominal(),
386-
M.getASTContext().Id_bridgeToObjectiveC, Identifier());
387-
ResultsRef = Results;
419+
SILFunction *bridgedFunc = nullptr;
420+
SubstitutionMap subMap;
421+
{
422+
auto result = findBridgeToObjCFunc(FunctionBuilder, dynamicCast);
423+
if (!result)
424+
return nullptr;
425+
std::tie(bridgedFunc, subMap) = result.getValue();
388426
}
389-
if (ResultsRef.size() != 1)
390-
return nullptr;
391-
392-
auto *resultDecl = Results.front();
393-
auto MemberDeclRef = SILDeclRef(resultDecl);
394-
auto *BridgedFunc = FunctionBuilder.getOrCreateFunction(
395-
Loc, MemberDeclRef, ForDefinition_t::NotForDefinition);
396-
397-
// Implementation of _bridgeToObjectiveC could not be found.
398-
if (!BridgedFunc)
399-
return nullptr;
400-
401-
if (Inst->getFunction()->isSerialized() &&
402-
!BridgedFunc->hasValidLinkageForFragileRef())
403-
return nullptr;
404-
405-
auto ParamTypes = BridgedFunc->getLoweredFunctionType()->getParameters();
406-
407-
auto SILFnTy = SILType::getPrimitiveObjectType(
408-
M.Types.getConstantFunctionType(BridgeFuncDeclRef));
409-
410-
// TODO: Handle return from witness function.
411-
if (BridgedFunc->getLoweredFunctionType()
412-
->getSingleResult()
413-
.isFormalIndirect())
414-
return nullptr;
415427

416-
// Get substitutions, if source is a bound generic type.
417-
auto SubMap = Source->getContextSubstitutionMap(
418-
M.getSwiftModule(), BridgeFuncDecl->getDeclContext());
419-
420-
SILType SubstFnTy = SILFnTy.substGenericArgs(M, SubMap);
428+
SILType SubstFnTy = bridgedFunc->getLoweredType().substGenericArgs(M, subMap);
421429
SILFunctionConventions substConv(SubstFnTy.castTo<SILFunctionType>(), M);
422430

423431
// check that we can go through with the optimization
424432
if (!canOptimizeCast(BridgedTargetTy, M, substConv)) {
425433
return nullptr;
426434
}
427435

428-
auto FnRef = Builder.createFunctionRef(Loc, BridgedFunc);
436+
SILBuilderWithScope Builder(Inst, BuilderContext);
437+
auto FnRef = Builder.createFunctionRef(Loc, bridgedFunc);
438+
auto ParamTypes = SubstFnTy.castTo<SILFunctionType>()->getParameters();
429439
if (Src->getType().isAddress() && !substConv.isSILIndirect(ParamTypes[0])) {
430440
// Create load
431441
Src = Builder.createLoad(Loc, Src, LoadOwnershipQualifier::Unqualified);
@@ -512,7 +522,7 @@ CastOptimizer::optimizeBridgedSwiftToObjCCast(SILDynamicCastInst dynamicCast) {
512522
}
513523

514524
// Generate a code to invoke the bridging function.
515-
auto *NewAI = Builder.createApply(Loc, FnRef, SubMap, Src, false);
525+
auto *NewAI = Builder.createApply(Loc, FnRef, subMap, Src, false);
516526

517527
auto releaseSrc = [&](SILBuilder &Builder) {
518528
if (AddressOnlyType) {

0 commit comments

Comments
 (0)