Skip to content

[SIL]/[SILOpt] Thunks and specializations are never public. #16959

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 26, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 43 additions & 3 deletions include/swift/SIL/SILFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@ class SILProfiler;
enum IsBare_t { IsNotBare, IsBare };
enum IsTransparent_t { IsNotTransparent, IsTransparent };
enum Inline_t { InlineDefault, NoInline, AlwaysInline };
enum IsThunk_t { IsNotThunk, IsThunk, IsReabstractionThunk };
enum IsThunk_t {
IsNotThunk,
IsThunk,
IsReabstractionThunk,
IsSignatureOptimizedThunk
};

class SILSpecializeAttr final {
friend SILFunction;
Expand Down Expand Up @@ -224,6 +229,33 @@ class SILFunction
/// serialization.
bool WasDeserializedCanonical = false;

static void
validateSubclassScope(SubclassScope scope, IsThunk_t isThunk,
const GenericSpecializationInformation *genericInfo) {
#ifndef NDEBUG
// The _original_ function for a method can turn into a thunk through
// signature optimization, meaning it needs to retain its subclassScope, but
// other thunks and specializations are implementation details and so
// shouldn't be connected to their parent class.
bool thunkCanHaveSubclassScope;
switch (isThunk) {
case IsNotThunk:
case IsSignatureOptimizedThunk:
thunkCanHaveSubclassScope = true;
break;
case IsThunk:
case IsReabstractionThunk:
thunkCanHaveSubclassScope = false;
break;
}
auto allowsInterestingScopes = thunkCanHaveSubclassScope && !genericInfo;
assert(
allowsInterestingScopes ||
scope == SubclassScope::NotApplicable &&
"SubclassScope on specialization or non-signature-optimized thunk");
#endif
}

SILFunction(SILModule &module, SILLinkage linkage, StringRef mangledName,
CanSILFunctionType loweredType, GenericEnvironment *genericEnv,
Optional<SILLocation> loc, IsBare_t isBareSILFunction,
Expand Down Expand Up @@ -573,13 +605,20 @@ class SILFunction

/// Get this function's thunk attribute.
IsThunk_t isThunk() const { return IsThunk_t(Thunk); }
void setThunk(IsThunk_t isThunk) { Thunk = isThunk; }
void setThunk(IsThunk_t isThunk) {
validateSubclassScope(getClassSubclassScope(), isThunk, SpecializationInfo);
Thunk = isThunk;
}

/// Get the class visibility (relevant for class methods).
SubclassScope getClassSubclassScope() const {
return SubclassScope(ClassSubclassScope);
}

void setClassSubclassScope(SubclassScope scope) {
validateSubclassScope(scope, isThunk(), SpecializationInfo);
ClassSubclassScope = static_cast<unsigned>(scope);
}

/// Get this function's noinline attribute.
Inline_t getInlineStrategy() const { return Inline_t(InlineStrategy); }
void setInlineStrategy(Inline_t inStr) { InlineStrategy = inStr; }
Expand Down Expand Up @@ -655,6 +694,7 @@ class SILFunction

void setSpecializationInfo(const GenericSpecializationInformation *Info) {
assert(!isSpecialization());
validateSubclassScope(getClassSubclassScope(), isThunk(), Info);
SpecializationInfo = Info;
}

Expand Down
2 changes: 2 additions & 0 deletions lib/ParseSIL/ParseSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -912,6 +912,8 @@ static bool parseDeclSILOptional(bool *isTransparent,
*isCanonical = true;
else if (isThunk && SP.P.Tok.getText() == "thunk")
*isThunk = IsThunk;
else if (isThunk && SP.P.Tok.getText() == "signature_optimized_thunk")
*isThunk = IsSignatureOptimizedThunk;
else if (isThunk && SP.P.Tok.getText() == "reabstraction_thunk")
*isThunk = IsReabstractionThunk;
else if (isGlobalInit && SP.P.Tok.getText() == "global_init")
Expand Down
4 changes: 4 additions & 0 deletions lib/SIL/SILDeclRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,10 @@ SubclassScope SILDeclRef::getSubclassScope() const {
if (context->isExtensionContext())
return SubclassScope::NotApplicable;

// Various forms of thunks don't either.
if (isThunk() || isForeign)
return SubclassScope::NotApplicable;

auto *classType = context->getAsClassOrClassExtensionContext();
if (!classType || classType->isFinal())
return SubclassScope::NotApplicable;
Expand Down
2 changes: 2 additions & 0 deletions lib/SIL/SILFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ SILFunction::SILFunction(SILModule &Module, SILLinkage Linkage, StringRef Name,
HasCReferences(false), IsWeakLinked(false),
OptMode(OptimizationMode::NotSet), EffectsKindAttr(E),
EntryCount(entryCount) {
validateSubclassScope(classSubclassScope, isThunk, nullptr);

if (InsertBefore)
Module.functions.insert(SILModule::iterator(InsertBefore), this);
else
Expand Down
3 changes: 3 additions & 0 deletions lib/SIL/SILPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2326,6 +2326,9 @@ void SILFunction::print(SILPrintContext &PrintCtx) const {
switch (isThunk()) {
case IsNotThunk: break;
case IsThunk: OS << "[thunk] "; break;
case IsSignatureOptimizedThunk:
OS << "[signature_optimized_thunk] ";
break;
case IsReabstractionThunk: OS << "[reabstraction_thunk] "; break;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,10 @@ void FunctionSignatureTransform::createFunctionSignatureOptimizedFunction() {
NewF->setUnqualifiedOwnership();
}

if (F->isSpecialization()) {
NewF->setSpecializationInfo(F->getSpecializationInfo());
}

// Then we transfer the body of F to NewF.
NewF->spliceBody(F);

Expand All @@ -529,7 +533,7 @@ void FunctionSignatureTransform::createFunctionSignatureOptimizedFunction() {
}

// Create the thunk body !
F->setThunk(IsThunk);
F->setThunk(IsSignatureOptimizedThunk);
// The thunk now carries the information on how the signature is
// optimized. If we inline the thunk, we will get the benefit of calling
// the signature optimized function without additional setup on the
Expand Down
6 changes: 5 additions & 1 deletion lib/SILOptimizer/IPO/ClosureSpecializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -635,11 +635,15 @@ ClosureSpecCloner::initCloned(const CallSiteDescriptor &CallSiteDesc,
// and not the original linkage.
// Otherwise the new function could have an external linkage (in case the
// original function was de-serialized) and would not be code-gen'd.
// It's also important to disconnect this specialized function from any
// classes (the classSubclassScope), because that may incorrectly
// influence the linkage.
getSpecializedLinkage(ClosureUser, ClosureUser->getLinkage()), ClonedName,
ClonedTy, ClosureUser->getGenericEnvironment(),
ClosureUser->getLocation(), IsBare, ClosureUser->isTransparent(),
CallSiteDesc.isSerialized(), ClosureUser->getEntryCount(),
ClosureUser->isThunk(), ClosureUser->getClassSubclassScope(),
ClosureUser->isThunk(),
/*classSubclassScope=*/SubclassScope::NotApplicable,
ClosureUser->getInlineStrategy(), ClosureUser->getEffectsKind(),
ClosureUser, ClosureUser->getDebugScope());
if (!ClosureUser->hasQualifiedOwnership()) {
Expand Down
1 change: 1 addition & 0 deletions lib/SILOptimizer/Utils/Generics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1840,6 +1840,7 @@ SILFunction *GenericFuncSpecializer::tryCreateSpecialization() {
auto *Caller = ReInfo.getApply() ? ReInfo.getApply().getFunction() : nullptr;
SubstitutionMap Subs = Caller ? ReInfo.getApply().getSubstitutionMap()
: ReInfo.getClonerParamSubstitutionMap();
SpecializedF->setClassSubclassScope(SubclassScope::NotApplicable);
SpecializedF->setSpecializationInfo(
GenericSpecializationInformation::create(Caller, GenericFunc, Subs));
return SpecializedF;
Expand Down
2 changes: 1 addition & 1 deletion lib/Serialization/SILFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ namespace sil_block {
BCRecordLayout<SIL_FUNCTION, SILLinkageField,
BCFixed<1>, // transparent
BCFixed<2>, // serialized
BCFixed<2>, // thunk/reabstraction_thunk
BCFixed<2>, // thunks: signature optimized/reabstraction
BCFixed<1>, // global_init
BCFixed<2>, // inlineStrategy
BCFixed<2>, // optimizationMode
Expand Down
2 changes: 1 addition & 1 deletion test/SILOptimizer/dead_partial_apply_arg.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ extension Int32 {

// This function has an unused metatype argument.

// CHECK-LABEL: sil [thunk] [always_inline] @$Ss5Int32V4testE8lessthan3lhs3rhsSbAB_ABtFZ : $@convention(method) (Int32, Int32, @thin Int32.Type) -> Bool
// CHECK-LABEL: sil [signature_optimized_thunk] [always_inline] @$Ss5Int32V4testE8lessthan3lhs3rhsSbAB_ABtFZ : $@convention(method) (Int32, Int32, @thin Int32.Type) -> Bool
public static func lessthan (lhs: Int32, rhs: Int32) -> Bool {
return lhs < rhs
}
Expand Down
6 changes: 3 additions & 3 deletions test/SILOptimizer/deadargsignatureopt.sil
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Swift

// Specialize to a function with removed dead argument.

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

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

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

// CHECK-LABEL: sil [thunk] [always_inline] @two_args_dead
// CHECK-LABEL: sil [signature_optimized_thunk] [always_inline] @two_args_dead
// CHECK: [[F:%[0-9]+]] = function_ref @$S13two_args_deadTf4nnd_n
// CHECK: [[A:%[0-9]+]] = apply [[F]](%0, %1)
// CHECK: return [[A]]
Expand Down
2 changes: 1 addition & 1 deletion test/SILOptimizer/funcsig_opaque.sil
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ sil @testAggregateArgHelper : $@convention(thin) (@owned R<S>) -> ()

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