Skip to content

Commit 1b3d29a

Browse files
authored
Merge pull request #6092 from swiftix/wip-generics-inlining-flag-4
Enable inlining of generics
2 parents b324249 + 199e76d commit 1b3d29a

24 files changed

+343
-75
lines changed

include/swift/SIL/SILModule.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -430,12 +430,19 @@ class SILModule {
430430
bool linkFunction(StringRef Name,
431431
LinkingMode LinkAll = LinkingMode::LinkNormal);
432432

433-
/// Check if a given function exists in the module,
434-
/// i.e. it can be linked by linkFunction.
433+
/// Check if a given function exists in any of the modules with a
434+
/// required linkage, i.e. it can be linked by linkFunction.
435+
///
436+
/// If linkage parameter is none, then the linkage of the function
437+
/// with a given name does not matter.
435438
///
436439
/// \return null if this module has no such function. Otherwise
437440
/// the declaration of a function.
438-
SILFunction *hasFunction(StringRef Name, SILLinkage Linkage);
441+
SILFunction *findFunction(StringRef Name, Optional<SILLinkage> Linkage);
442+
443+
/// Check if a given function exists in the module,
444+
/// i.e. it can be linked by linkFunction.
445+
bool hasFunction(StringRef Name);
439446

440447
/// Link in all Witness Tables in the module.
441448
void linkAllWitnessTables();

include/swift/SILOptimizer/Utils/Devirtualize.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ typedef std::pair<ValueBase *, ApplySite> DevirtualizationResult;
4646
DevirtualizationResult tryDevirtualizeApply(FullApplySite AI);
4747
DevirtualizationResult tryDevirtualizeApply(FullApplySite AI,
4848
ClassHierarchyAnalysis *CHA);
49+
bool canDevirtualizeApply(FullApplySite AI, ClassHierarchyAnalysis *CHA);
4950
bool isNominalTypeWithUnboundGenericParameters(SILType Ty, SILModule &M);
5051
bool canDevirtualizeClassMethod(FullApplySite AI, SILType ClassInstanceType);
5152
SILFunction *getTargetClassMethod(SILModule &M, SILType ClassOrMetatypeType,

include/swift/Serialization/SerializedSILLoader.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ class SerializedSILLoader {
9292
SILFunction *lookupSILFunction(SILFunction *Callee);
9393
SILFunction *
9494
lookupSILFunction(StringRef Name, bool declarationOnly = false,
95-
SILLinkage linkage = SILLinkage::Private);
96-
bool hasSILFunction(StringRef Name, SILLinkage linkage = SILLinkage::Private);
95+
Optional<SILLinkage> linkage = None);
96+
bool hasSILFunction(StringRef Name, Optional<SILLinkage> linkage = None);
9797
SILVTable *lookupVTable(Identifier Name);
9898
SILVTable *lookupVTable(const ClassDecl *C) {
9999
return lookupVTable(C->getName());

lib/AST/Substitution.cpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,26 @@ Substitution Substitution::subst(ModuleDecl *module,
9595
// conformances from thin air. FIXME: gross.
9696
if (!conformance &&
9797
proto->isSpecificProtocol(KnownProtocolKind::AnyObject)) {
98-
auto classDecl
99-
= substReplacement->getClassOrBoundGenericClass();
100-
assert(classDecl);
101-
SmallVector<ProtocolConformance *, 1> lookupResults;
102-
classDecl->lookupConformance(classDecl->getParentModule(),
103-
proto, lookupResults);
104-
conformance = ProtocolConformanceRef(lookupResults.front());
98+
auto archetype =
99+
dyn_cast<ArchetypeType>(substReplacement->getCanonicalType());
100+
// If classDecl is not nullptr, it is a concrete class.
101+
auto classDecl = substReplacement->getClassOrBoundGenericClass();
102+
if (!classDecl && archetype->getSuperclass()) {
103+
// Replacement type is an archetype with a superclass constraint.
104+
classDecl = archetype->getSuperclass()->getClassOrBoundGenericClass();
105+
assert(classDecl);
106+
}
107+
if (classDecl) {
108+
// Create a concrete conformance based on the conforming class.
109+
SmallVector<ProtocolConformance *, 1> lookupResults;
110+
classDecl->lookupConformance(classDecl->getParentModule(), proto,
111+
lookupResults);
112+
conformance = ProtocolConformanceRef(lookupResults.front());
113+
} else if (archetype && archetype->requiresClass()) {
114+
// Replacement type is an archetype with a class constraint.
115+
// Create an abstract conformance.
116+
conformance = ProtocolConformanceRef(proto);
117+
}
105118
}
106119

107120
assert(conformance);

lib/IRGen/IRGenSIL.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -731,19 +731,34 @@ class IRGenSILFunction :
731731
copy.push_back(alloca.getAddress());
732732
}
733733

734+
/// Determine whether a generic variable has been inlined.
735+
static bool isInlinedGeneric(VarDecl *VarDecl, const SILDebugScope *DS) {
736+
if (!DS->InlinedCallSite)
737+
return false;
738+
if (VarDecl->hasType())
739+
return VarDecl->getType()->hasArchetype();
740+
return VarDecl->getInterfaceType()->hasTypeParameter();
741+
}
742+
734743
/// Emit debug info for a function argument or a local variable.
735744
template <typename StorageType>
736745
void emitDebugVariableDeclaration(StorageType Storage,
737746
DebugTypeInfo Ty,
738747
SILType SILTy,
739748
const SILDebugScope *DS,
740-
ValueDecl *VarDecl,
749+
VarDecl *VarDecl,
741750
StringRef Name,
742751
unsigned ArgNo = 0,
743752
IndirectionKind Indirection = DirectValue) {
744753
// Force all archetypes referenced by the type to be bound by this point.
745754
// TODO: just make sure that we have a path to them that the debug info
746755
// can follow.
756+
757+
// FIXME: The debug info type of all inlined instances of a variable must be
758+
// the same as the type of the abstract variable.
759+
if (isInlinedGeneric(VarDecl, DS))
760+
return;
761+
747762
auto runtimeTy = getRuntimeReifiedType(IGM,
748763
Ty.getType()->getCanonicalType());
749764
if (!IGM.IRGen.Opts.Optimize && runtimeTy->hasArchetype())
@@ -3754,6 +3769,10 @@ void IRGenSILFunction::visitAllocBoxInst(swift::AllocBoxInst *i) {
37543769
CurSILFn->getDeclContext(), Decl,
37553770
i->getBoxType()->getFieldType(IGM.getSILModule(), 0).getSwiftType(),
37563771
type, /*Unwrap=*/false);
3772+
3773+
if (isInlinedGeneric(Decl, i->getDebugScope()))
3774+
return;
3775+
37573776
IGM.DebugInfo->emitVariableDeclaration(
37583777
Builder,
37593778
emitShadowCopy(boxWithAddr.getAddress(), i->getDebugScope(), Name, 0),

lib/SIL/Linker.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ SILFunction *SILLinkerVisitor::lookupFunction(StringRef Name,
117117
}
118118

119119
/// Process Decl, recursively deserializing any thing Decl may reference.
120-
bool SILLinkerVisitor::hasFunction(StringRef Name, SILLinkage Linkage) {
120+
bool SILLinkerVisitor::hasFunction(StringRef Name,
121+
Optional<SILLinkage> Linkage) {
121122
return Loader->hasSILFunction(Name, Linkage);
122123
}
123124

lib/SIL/Linker.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class SILLinkerVisitor : public SILInstructionVisitor<SILLinkerVisitor, bool> {
6060

6161
/// Process Name, try to check if there is a declaration of a function
6262
/// with this Name.
63-
bool hasFunction(StringRef Name, SILLinkage Linkage);
63+
bool hasFunction(StringRef Name, Optional<SILLinkage> Linkage = None);
6464

6565
/// Deserialize the VTable mapped to C if it exists and all SIL the VTable
6666
/// transitively references.

lib/SIL/SILModule.cpp

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -499,23 +499,39 @@ bool SILModule::linkFunction(StringRef Name, SILModule::LinkingMode Mode) {
499499
return SILLinkerVisitor(*this, getSILLoader(), Mode).processFunction(Name);
500500
}
501501

502-
SILFunction *SILModule::hasFunction(StringRef Name, SILLinkage Linkage) {
503-
assert((Linkage == SILLinkage::Public ||
504-
Linkage == SILLinkage::PublicExternal) &&
505-
"Only a lookup of public functions is supported currently");
502+
/// Check if a given SIL linkage matches the required linkage.
503+
/// If the required linkage is Private, then anything matches it.
504+
static bool isMatchingLinkage(SILLinkage ActualLinkage,
505+
Optional<SILLinkage> Linkage) {
506+
if (!Linkage)
507+
return true;
508+
return ActualLinkage == Linkage;
509+
}
510+
511+
bool SILModule::hasFunction(StringRef Name) {
512+
if (lookUpFunction(Name))
513+
return true;
514+
SILLinkerVisitor Visitor(*this, getSILLoader(),
515+
SILModule::LinkingMode::LinkNormal);
516+
return Visitor.hasFunction(Name);
517+
}
518+
519+
SILFunction *SILModule::findFunction(StringRef Name,
520+
Optional<SILLinkage> Linkage) {
506521

507522
SILFunction *F = nullptr;
523+
SILLinkage RequiredLinkage = Linkage ? *Linkage : SILLinkage::Private;
508524

509525
// First, check if there is a function with a required name in the
510526
// current module.
511527
SILFunction *CurF = lookUpFunction(Name);
512528

513529
// Nothing to do if the current module has a required function
514530
// with a proper linkage already.
515-
if (CurF && CurF->getLinkage() == Linkage) {
531+
if (CurF && isMatchingLinkage(CurF->getLinkage(), Linkage)) {
516532
F = CurF;
517533
} else {
518-
assert((!CurF || CurF->getLinkage() != Linkage) &&
534+
assert((!CurF || CurF->getLinkage() != RequiredLinkage) &&
519535
"hasFunction should be only called for functions that are not "
520536
"contained in the SILModule yet or do not have a required linkage");
521537
}
@@ -528,7 +544,7 @@ SILFunction *SILModule::hasFunction(StringRef Name, SILLinkage Linkage) {
528544
// name is present in the current module.
529545
// This is done to reduce the amount of IO from the
530546
// swift module file.
531-
if (!Visitor.hasFunction(Name, Linkage))
547+
if (!Visitor.hasFunction(Name, RequiredLinkage))
532548
return nullptr;
533549
// The function in the current module will be changed.
534550
F = CurF;
@@ -538,13 +554,14 @@ SILFunction *SILModule::hasFunction(StringRef Name, SILLinkage Linkage) {
538554
// or if it is known to exist, perform a lookup.
539555
if (!F) {
540556
// Try to load the function from other modules.
541-
F = Visitor.lookupFunction(Name, Linkage);
557+
F = Visitor.lookupFunction(Name, RequiredLinkage);
542558
// Bail if nothing was found and we are not sure if
543559
// this function exists elsewhere.
544560
if (!F)
545561
return nullptr;
546562
assert(F && "SILFunction should be present in one of the modules");
547-
assert(F->getLinkage() == Linkage && "SILFunction has a wrong linkage");
563+
assert(isMatchingLinkage(F->getLinkage(), Linkage) &&
564+
"SILFunction has a wrong linkage");
548565
}
549566
}
550567

@@ -556,9 +573,19 @@ SILFunction *SILModule::hasFunction(StringRef Name, SILLinkage Linkage) {
556573
SILOptions::SILOptMode::Optimize) {
557574
F->convertToDeclaration();
558575
}
559-
if (F->isExternalDeclaration())
576+
if (F->isExternalDeclaration()) {
560577
F->setFragile(IsFragile_t::IsNotFragile);
561-
F->setLinkage(Linkage);
578+
if (isAvailableExternally(F->getLinkage()) &&
579+
!hasPublicVisibility(F->getLinkage()) && !Linkage) {
580+
// We were just asked if a given function exists anywhere.
581+
// It is not going to be used by the current module.
582+
// Since external non-public function declarations should not
583+
// exist, strip the "external" part from the linkage.
584+
F->setLinkage(stripExternalFromLinkage(F->getLinkage()));
585+
}
586+
}
587+
if (Linkage)
588+
F->setLinkage(RequiredLinkage);
562589
return F;
563590
}
564591

lib/SILOptimizer/IPO/EagerSpecializer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ class EagerDispatch {
287287
substConv(ReInfo.getSubstitutedType(), GenericFunc->getModule()),
288288
Builder(*GenericFunc), Loc(GenericFunc->getLocation()) {
289289
Builder.setCurrentDebugScope(GenericFunc->getDebugScope());
290-
IsClassF = Builder.getModule().hasFunction(
290+
IsClassF = Builder.getModule().findFunction(
291291
"_swift_isClassOrObjCExistentialType", SILLinkage::PublicExternal);
292292
assert(IsClassF);
293293
}

lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ static SILInstruction *findOnlyApply(SILFunction *F) {
9393
///
9494
/// TODO: we should teach the demangler to understand this suffix.
9595
static std::string getUniqueName(std::string Name, SILModule &M) {
96-
if (!M.lookUpFunction(Name))
96+
if (!M.hasFunction(Name))
9797
return Name;
9898
return getUniqueName(Name + "_unique_suffix", M);
9999
}
@@ -372,7 +372,7 @@ std::string FunctionSignatureTransform::createOptimizedSILFunctionName() {
372372
do {
373373
New = NewFM.mangle(UniqueID);
374374
++UniqueID;
375-
} while (M.lookUpFunction(New));
375+
} while (M.hasFunction(New));
376376

377377
return NewMangling::selectMangling(Old, New);
378378
}

0 commit comments

Comments
 (0)