Skip to content

Commit 1c86abb

Browse files
authored
Merge pull request #16959 from huonw/tbd-thunk-specialization
[SIL]/[SILOpt] Thunks and specializations are never public.
2 parents d987ca8 + ed64fad commit 1c86abb

File tree

16 files changed

+184
-62
lines changed

16 files changed

+184
-62
lines changed

include/swift/SIL/SILFunction.h

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,12 @@ class SILProfiler;
4040
enum IsBare_t { IsNotBare, IsBare };
4141
enum IsTransparent_t { IsNotTransparent, IsTransparent };
4242
enum Inline_t { InlineDefault, NoInline, AlwaysInline };
43-
enum IsThunk_t { IsNotThunk, IsThunk, IsReabstractionThunk };
43+
enum IsThunk_t {
44+
IsNotThunk,
45+
IsThunk,
46+
IsReabstractionThunk,
47+
IsSignatureOptimizedThunk
48+
};
4449

4550
class SILSpecializeAttr final {
4651
friend SILFunction;
@@ -224,6 +229,33 @@ class SILFunction
224229
/// serialization.
225230
bool WasDeserializedCanonical = false;
226231

232+
static void
233+
validateSubclassScope(SubclassScope scope, IsThunk_t isThunk,
234+
const GenericSpecializationInformation *genericInfo) {
235+
#ifndef NDEBUG
236+
// The _original_ function for a method can turn into a thunk through
237+
// signature optimization, meaning it needs to retain its subclassScope, but
238+
// other thunks and specializations are implementation details and so
239+
// shouldn't be connected to their parent class.
240+
bool thunkCanHaveSubclassScope;
241+
switch (isThunk) {
242+
case IsNotThunk:
243+
case IsSignatureOptimizedThunk:
244+
thunkCanHaveSubclassScope = true;
245+
break;
246+
case IsThunk:
247+
case IsReabstractionThunk:
248+
thunkCanHaveSubclassScope = false;
249+
break;
250+
}
251+
auto allowsInterestingScopes = thunkCanHaveSubclassScope && !genericInfo;
252+
assert(
253+
allowsInterestingScopes ||
254+
scope == SubclassScope::NotApplicable &&
255+
"SubclassScope on specialization or non-signature-optimized thunk");
256+
#endif
257+
}
258+
227259
SILFunction(SILModule &module, SILLinkage linkage, StringRef mangledName,
228260
CanSILFunctionType loweredType, GenericEnvironment *genericEnv,
229261
Optional<SILLocation> loc, IsBare_t isBareSILFunction,
@@ -573,13 +605,20 @@ class SILFunction
573605

574606
/// Get this function's thunk attribute.
575607
IsThunk_t isThunk() const { return IsThunk_t(Thunk); }
576-
void setThunk(IsThunk_t isThunk) { Thunk = isThunk; }
608+
void setThunk(IsThunk_t isThunk) {
609+
validateSubclassScope(getClassSubclassScope(), isThunk, SpecializationInfo);
610+
Thunk = isThunk;
611+
}
577612

578613
/// Get the class visibility (relevant for class methods).
579614
SubclassScope getClassSubclassScope() const {
580615
return SubclassScope(ClassSubclassScope);
581616
}
582-
617+
void setClassSubclassScope(SubclassScope scope) {
618+
validateSubclassScope(scope, isThunk(), SpecializationInfo);
619+
ClassSubclassScope = static_cast<unsigned>(scope);
620+
}
621+
583622
/// Get this function's noinline attribute.
584623
Inline_t getInlineStrategy() const { return Inline_t(InlineStrategy); }
585624
void setInlineStrategy(Inline_t inStr) { InlineStrategy = inStr; }
@@ -655,6 +694,7 @@ class SILFunction
655694

656695
void setSpecializationInfo(const GenericSpecializationInformation *Info) {
657696
assert(!isSpecialization());
697+
validateSubclassScope(getClassSubclassScope(), isThunk(), Info);
658698
SpecializationInfo = Info;
659699
}
660700

lib/ParseSIL/ParseSIL.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,8 @@ static bool parseDeclSILOptional(bool *isTransparent,
912912
*isCanonical = true;
913913
else if (isThunk && SP.P.Tok.getText() == "thunk")
914914
*isThunk = IsThunk;
915+
else if (isThunk && SP.P.Tok.getText() == "signature_optimized_thunk")
916+
*isThunk = IsSignatureOptimizedThunk;
915917
else if (isThunk && SP.P.Tok.getText() == "reabstraction_thunk")
916918
*isThunk = IsReabstractionThunk;
917919
else if (isGlobalInit && SP.P.Tok.getText() == "global_init")

lib/SIL/SILDeclRef.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,10 @@ SubclassScope SILDeclRef::getSubclassScope() const {
771771
if (context->isExtensionContext())
772772
return SubclassScope::NotApplicable;
773773

774+
// Various forms of thunks don't either.
775+
if (isThunk() || isForeign)
776+
return SubclassScope::NotApplicable;
777+
774778
auto *classType = context->getAsClassOrClassExtensionContext();
775779
if (!classType || classType->isFinal())
776780
return SubclassScope::NotApplicable;

lib/SIL/SILFunction.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ SILFunction::SILFunction(SILModule &Module, SILLinkage Linkage, StringRef Name,
102102
HasCReferences(false), IsWeakLinked(false),
103103
OptMode(OptimizationMode::NotSet), EffectsKindAttr(E),
104104
EntryCount(entryCount) {
105+
validateSubclassScope(classSubclassScope, isThunk, nullptr);
106+
105107
if (InsertBefore)
106108
Module.functions.insert(SILModule::iterator(InsertBefore), this);
107109
else

lib/SIL/SILPrinter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2326,6 +2326,9 @@ void SILFunction::print(SILPrintContext &PrintCtx) const {
23262326
switch (isThunk()) {
23272327
case IsNotThunk: break;
23282328
case IsThunk: OS << "[thunk] "; break;
2329+
case IsSignatureOptimizedThunk:
2330+
OS << "[signature_optimized_thunk] ";
2331+
break;
23292332
case IsReabstractionThunk: OS << "[reabstraction_thunk] "; break;
23302333
}
23312334

lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,10 @@ void FunctionSignatureTransform::createFunctionSignatureOptimizedFunction() {
506506
NewF->setUnqualifiedOwnership();
507507
}
508508

509+
if (F->isSpecialization()) {
510+
NewF->setSpecializationInfo(F->getSpecializationInfo());
511+
}
512+
509513
// Then we transfer the body of F to NewF.
510514
NewF->spliceBody(F);
511515

@@ -529,7 +533,7 @@ void FunctionSignatureTransform::createFunctionSignatureOptimizedFunction() {
529533
}
530534

531535
// Create the thunk body !
532-
F->setThunk(IsThunk);
536+
F->setThunk(IsSignatureOptimizedThunk);
533537
// The thunk now carries the information on how the signature is
534538
// optimized. If we inline the thunk, we will get the benefit of calling
535539
// the signature optimized function without additional setup on the

lib/SILOptimizer/IPO/ClosureSpecializer.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -635,11 +635,15 @@ ClosureSpecCloner::initCloned(const CallSiteDescriptor &CallSiteDesc,
635635
// and not the original linkage.
636636
// Otherwise the new function could have an external linkage (in case the
637637
// original function was de-serialized) and would not be code-gen'd.
638+
// It's also important to disconnect this specialized function from any
639+
// classes (the classSubclassScope), because that may incorrectly
640+
// influence the linkage.
638641
getSpecializedLinkage(ClosureUser, ClosureUser->getLinkage()), ClonedName,
639642
ClonedTy, ClosureUser->getGenericEnvironment(),
640643
ClosureUser->getLocation(), IsBare, ClosureUser->isTransparent(),
641644
CallSiteDesc.isSerialized(), ClosureUser->getEntryCount(),
642-
ClosureUser->isThunk(), ClosureUser->getClassSubclassScope(),
645+
ClosureUser->isThunk(),
646+
/*classSubclassScope=*/SubclassScope::NotApplicable,
643647
ClosureUser->getInlineStrategy(), ClosureUser->getEffectsKind(),
644648
ClosureUser, ClosureUser->getDebugScope());
645649
if (!ClosureUser->hasQualifiedOwnership()) {

lib/SILOptimizer/Utils/Generics.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1840,6 +1840,7 @@ SILFunction *GenericFuncSpecializer::tryCreateSpecialization() {
18401840
auto *Caller = ReInfo.getApply() ? ReInfo.getApply().getFunction() : nullptr;
18411841
SubstitutionMap Subs = Caller ? ReInfo.getApply().getSubstitutionMap()
18421842
: ReInfo.getClonerParamSubstitutionMap();
1843+
SpecializedF->setClassSubclassScope(SubclassScope::NotApplicable);
18431844
SpecializedF->setSpecializationInfo(
18441845
GenericSpecializationInformation::create(Caller, GenericFunc, Subs));
18451846
return SpecializedF;

lib/Serialization/SILFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ namespace sil_block {
286286
BCRecordLayout<SIL_FUNCTION, SILLinkageField,
287287
BCFixed<1>, // transparent
288288
BCFixed<2>, // serialized
289-
BCFixed<2>, // thunk/reabstraction_thunk
289+
BCFixed<2>, // thunks: signature optimized/reabstraction
290290
BCFixed<1>, // global_init
291291
BCFixed<2>, // inlineStrategy
292292
BCFixed<2>, // optimizationMode

test/SILOptimizer/dead_partial_apply_arg.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ extension Int32 {
88

99
// This function has an unused metatype argument.
1010

11-
// CHECK-LABEL: sil [thunk] [always_inline] @$Ss5Int32V4testE8lessthan3lhs3rhsSbAB_ABtFZ : $@convention(method) (Int32, Int32, @thin Int32.Type) -> Bool
11+
// CHECK-LABEL: sil [signature_optimized_thunk] [always_inline] @$Ss5Int32V4testE8lessthan3lhs3rhsSbAB_ABtFZ : $@convention(method) (Int32, Int32, @thin Int32.Type) -> Bool
1212
public static func lessthan (lhs: Int32, rhs: Int32) -> Bool {
1313
return lhs < rhs
1414
}

test/SILOptimizer/deadargsignatureopt.sil

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import Swift
55

66
// Specialize to a function with removed dead argument.
77

8-
// CHECK-LABEL: sil [thunk] [always_inline] @one_arg_dead
8+
// CHECK-LABEL: sil [signature_optimized_thunk] [always_inline] @one_arg_dead
99
// CHECK: [[F:%[0-9]+]] = function_ref @$S12one_arg_deadTf4nnd_n
1010
// CHECK: [[A:%[0-9]+]] = apply [[F]](%0, %1)
1111
// CHECK: return [[A]]
@@ -18,7 +18,7 @@ bb0(%0 : $Int32, %1 : $Int32, %2 : $@thin Int32.Type):
1818
return %8 : $Bool
1919
}
2020

21-
// CHECK-LABEL: sil [thunk] [always_inline] @always_inline_one_arg_dead
21+
// CHECK-LABEL: sil [signature_optimized_thunk] [always_inline] @always_inline_one_arg_dead
2222
// CHECK: [[F:%[0-9]+]] = function_ref @$S26always_inline_one_arg_deadTf4nnd_n
2323
// CHECK: [[A:%[0-9]+]] = apply [[F]](%0, %1)
2424
// CHECK: return [[A]]
@@ -33,7 +33,7 @@ bb0(%0 : $Int32, %1 : $Int32, %2 : $@thin Int32.Type):
3333

3434
// Still delete only one dead arg as only one arg is partially applied.
3535

36-
// CHECK-LABEL: sil [thunk] [always_inline] @two_args_dead
36+
// CHECK-LABEL: sil [signature_optimized_thunk] [always_inline] @two_args_dead
3737
// CHECK: [[F:%[0-9]+]] = function_ref @$S13two_args_deadTf4nnd_n
3838
// CHECK: [[A:%[0-9]+]] = apply [[F]](%0, %1)
3939
// CHECK: return [[A]]

test/SILOptimizer/funcsig_opaque.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ sil @testAggregateArgHelper : $@convention(thin) (@owned R<S>) -> ()
1414

1515
// Test owned-to-guaranteed transformation of opaque arguments.
1616
//
17-
// CHECK-LABEL: sil [thunk] [always_inline] @testAggregateArg : $@convention(thin) (@in R<S>) -> @out () {
17+
// CHECK-LABEL: sil [signature_optimized_thunk] [always_inline] @testAggregateArg : $@convention(thin) (@in R<S>) -> @out () {
1818
// CHECK: bb0(%0 : $R<S>):
1919
// CHECK: [[F:%.*]] = function_ref @$S16testAggregateArgTf4g_n : $@convention(thin) (@in_guaranteed R<S>) -> @out ()
2020
// CHECK: [[CALL:%.*]] = apply [[F]](%0) : $@convention(thin) (@in_guaranteed R<S>) -> @out ()

0 commit comments

Comments
 (0)