@@ -41,6 +41,9 @@ ReabstractionInfo::ReabstractionInfo(SILFunction *OrigF,
41
41
if (hasUnboundGenericTypes (InterfaceSubs)) {
42
42
DEBUG (llvm::dbgs () <<
43
43
" Cannot specialize with unbound interface substitutions.\n " );
44
+ DEBUG (for (auto Sub : ParamSubs) {
45
+ Sub.dump ();
46
+ });
44
47
return ;
45
48
}
46
49
if (hasDynamicSelfTypes (InterfaceSubs)) {
@@ -167,8 +170,12 @@ SILFunction *GenericFuncSpecializer::lookupSpecialization() {
167
170
assert (ReInfo.getSpecializedType ()
168
171
== SpecializedF->getLoweredFunctionType () &&
169
172
" Previously specialized function does not match expected type." );
173
+ DEBUG (llvm::dbgs () << " Found an existing specialization for: " << ClonedName
174
+ << " \n " );
170
175
return SpecializedF;
171
176
}
177
+ DEBUG (llvm::dbgs () << " Could not find an existing specialization for: "
178
+ << ClonedName << " \n " );
172
179
return nullptr ;
173
180
}
174
181
@@ -400,7 +407,8 @@ void swift::trySpecializeApplyOfGeneric(
400
407
auto *F = Apply.getInstruction ()->getFunction ();
401
408
auto *RefF = cast<FunctionRefInst>(Apply.getCallee ())->getReferencedFunction ();
402
409
403
- DEBUG (llvm::dbgs () << " ApplyInst: " << *Apply.getInstruction ());
410
+ DEBUG (llvm::dbgs () << " ApplyInst:\n " ;
411
+ Apply.getInstruction ()->dumpInContext ());
404
412
405
413
// If the caller is fragile but the callee is not, bail out.
406
414
// Specializations have shared linkage, which means they do
@@ -470,6 +478,9 @@ void swift::trySpecializeApplyOfGeneric(
470
478
== SpecializedF->isFragile () &&
471
479
" Previously specialized function does not match expected "
472
480
" resilience level." );
481
+ // Even if the pre-specialization exists already, try to preserve it
482
+ // if it is whitelisted.
483
+ linkSpecialization (M, SpecializedF);
473
484
} else {
474
485
SpecializedF = FuncSpecializer.tryCreateSpecialization ();
475
486
if (!SpecializedF)
@@ -534,8 +545,29 @@ void swift::trySpecializeApplyOfGeneric(
534
545
// This uses the SIL linker to checks for the does not load the body of the pres
535
546
// =============================================================================
536
547
548
+ static void keepSpecializationAsPublic (SILFunction *F) {
549
+ DEBUG (auto DemangledNameString =
550
+ swift::Demangle::demangleSymbolAsString (F->getName ());
551
+ StringRef DemangledName = DemangledNameString;
552
+ llvm::dbgs () << " Keep specialization public: " << DemangledName << " : "
553
+ << F->getName () << " \n " );
554
+ // Make it public, so that others can refer to it.
555
+ //
556
+ // NOTE: This function may refer to non-public symbols, which may lead to
557
+ // problems, if you ever try to inline this function. Therefore, these
558
+ // specializations should only be used to refer to them, but should never
559
+ // be inlined! The general rule could be: Never inline specializations
560
+ // from stdlib!
561
+ //
562
+ // NOTE: Making these specializations public at this point breaks
563
+ // some optimizations. Therefore, just mark the function.
564
+ // DeadFunctionElimination pass will check if the function is marked
565
+ // and preserve it if required.
566
+ F->setKeepAsPublic (true );
567
+ }
568
+
537
569
// / Link a specialization for generating prespecialized code.
538
- // /
570
+ // /
539
571
// / For now, it is performed only for specializations in the
540
572
// / standard library. But in the future, one could think of
541
573
// / maintaining a cache of optimized specializations.
@@ -545,34 +577,14 @@ void swift::trySpecializeApplyOfGeneric(
545
577
// / the library, but only used only by client code compiled at -Onone. They
546
578
// / should be never inlined.
547
579
static bool linkSpecialization (SILModule &M, SILFunction *F) {
580
+ if (F->isKeepAsPublic ())
581
+ return true ;
548
582
// Do not remove functions from the white-list. Keep them around.
549
583
// Change their linkage to public, so that other applications can refer to it.
550
-
551
584
if (M.getOptions ().Optimization >= SILOptions::SILOptMode::Optimize &&
552
- F->getLinkage () != SILLinkage::Public &&
553
585
F->getModule ().getSwiftModule ()->getName ().str () == SWIFT_ONONE_SUPPORT) {
554
- if (F->getLinkage () != SILLinkage::Public &&
555
- isWhitelistedSpecialization (F->getName ())) {
556
-
557
- DEBUG (
558
- auto DemangledNameString =
559
- swift::Demangle::demangleSymbolAsString (F->getName ());
560
- StringRef DemangledName = DemangledNameString;
561
- llvm::dbgs () << " Keep specialization: " << DemangledName << " : "
562
- << F->getName () << " \n " );
563
- // Make it public, so that others can refer to it.
564
- //
565
- // NOTE: This function may refer to non-public symbols, which may lead to
566
- // problems, if you ever try to inline this function. Therefore, these
567
- // specializations should only be used to refer to them, but should never
568
- // be inlined! The general rule could be: Never inline specializations
569
- // from stdlib!
570
- //
571
- // NOTE: Making these specializations public at this point breaks
572
- // some optimizations. Therefore, just mark the function.
573
- // DeadFunctionElimination pass will check if the function is marked
574
- // and preserve it if required.
575
- F->setKeepAsPublic (true );
586
+ if (isWhitelistedSpecialization (F->getName ())) {
587
+ keepSpecializationAsPublic (F);
576
588
return true ;
577
589
}
578
590
}
@@ -607,7 +619,10 @@ bool swift::isWhitelistedSpecialization(StringRef SpecName) {
607
619
608
620
StringRef DemangledName = DemangledNameString;
609
621
622
+ DEBUG (llvm::dbgs () << " Check if whitelisted: " << DemangledName << " \n " );
623
+
610
624
auto pos = DemangledName.find (" generic " , 0 );
625
+ auto oldpos = pos;
611
626
if (pos == StringRef::npos)
612
627
return false ;
613
628
@@ -618,11 +633,22 @@ bool swift::isWhitelistedSpecialization(StringRef SpecName) {
618
633
buffer << STDLIB_NAME <<' .' ;
619
634
620
635
StringRef OfStr = buffer.str ();
621
-
622
- pos = DemangledName.find (OfStr, pos);
623
-
624
- if (pos == StringRef::npos)
625
- return false ;
636
+ DEBUG (llvm::dbgs () << " Check substring: " << OfStr << " \n " );
637
+
638
+ pos = DemangledName.find (OfStr, oldpos);
639
+
640
+ if (pos == StringRef::npos) {
641
+ // Create "of (extension in Swift).Swift"
642
+ llvm::SmallString<64 > OfString;
643
+ llvm::raw_svector_ostream buffer (OfString);
644
+ buffer << " of (extension in " << STDLIB_NAME << " ):" ;
645
+ buffer << STDLIB_NAME << ' .' ;
646
+ OfStr = buffer.str ();
647
+ pos = DemangledName.find (OfStr, oldpos);
648
+ DEBUG (llvm::dbgs () << " Check substring: " << OfStr << " \n " );
649
+ if (pos == StringRef::npos)
650
+ return false ;
651
+ }
626
652
627
653
pos += OfStr.size ();
628
654
@@ -659,8 +685,10 @@ SILFunction *swift::lookupPrespecializedSymbol(SILModule &M,
659
685
StringRef FunctionName) {
660
686
// First check if the module contains a required specialization already.
661
687
auto *Specialization = M.lookUpFunction (FunctionName);
662
- if (Specialization)
663
- return Specialization;
688
+ if (Specialization) {
689
+ if (Specialization->getLinkage () == SILLinkage::PublicExternal)
690
+ return Specialization;
691
+ }
664
692
665
693
// Then check if the required specialization can be found elsewhere.
666
694
Specialization = lookupExistingSpecialization (M, FunctionName);
0 commit comments