Skip to content

Commit 6a0851e

Browse files
authored
Merge pull request #64810 from tshortli/unavailable-decl-optimization-5.9
[5.9] Introduce `-unavailable-decl-optimization`
2 parents a7258c8 + 5e1fcbc commit 6a0851e

22 files changed

+616
-4
lines changed

include/swift/Basic/LangOptions.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,22 @@ namespace swift {
105105
TaskToThread,
106106
};
107107

108+
/// Describes the code size optimization behavior for code associated with
109+
/// declarations that are marked unavailable.
110+
enum class UnavailableDeclOptimization : uint8_t {
111+
/// No optimization. Unavailable declarations will contribute to the
112+
/// resulting binary by default in this mode.
113+
None,
114+
115+
/// Avoid generating any code for unavailable declarations.
116+
///
117+
/// NOTE: This optimization can be ABI breaking for a library evolution
118+
/// enabled module because existing client binaries built with a
119+
/// pre-Swift 5.9 compiler may depend on linkable symbols associated with
120+
/// unavailable declarations.
121+
Complete,
122+
};
123+
108124
/// A collection of options that affect the language dialect and
109125
/// provide compiler debugging facilities.
110126
class LangOptions final {
@@ -174,6 +190,10 @@ namespace swift {
174190
/// Only check the availability of the API, ignore function bodies.
175191
bool CheckAPIAvailabilityOnly = false;
176192

193+
/// Optimization mode for unavailable declarations.
194+
UnavailableDeclOptimization UnavailableDeclOptimizationMode =
195+
UnavailableDeclOptimization::None;
196+
177197
/// Causes the compiler to use weak linkage for symbols belonging to
178198
/// declarations introduced at the deployment target.
179199
bool WeakLinkAtTarget = false;

include/swift/Option/Options.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,13 @@ def check_api_availability_only : Flag<["-"], "check-api-availability-only">,
490490
Flags<[HelpHidden, FrontendOption, NoInteractiveOption]>,
491491
HelpText<"Only check the availability of the APIs, ignore function bodies">;
492492

493+
def unavailable_decl_optimization_EQ : Joined<["-"], "unavailable-decl-optimization=">,
494+
MetaVarName<"<complete,none>">,
495+
Flags<[FrontendOption, NoInteractiveOption]>,
496+
HelpText<"Specify the optimization mode for unavailable declarations. The "
497+
"value may be 'none' (no optimization) or 'complete' (code is not "
498+
"generated at all unavailable declarations)">;
499+
493500
def library_level : Separate<["-"], "library-level">,
494501
MetaVarName<"<level>">,
495502
Flags<[HelpHidden, FrontendOption, ModuleInterfaceOption]>,

include/swift/SIL/SILModule.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,8 +1078,22 @@ namespace Lowering {
10781078
/// Determine whether the given class will be allocated/deallocated using the
10791079
/// Objective-C runtime, i.e., +alloc and -dealloc.
10801080
LLVM_LIBRARY_VISIBILITY bool usesObjCAllocator(ClassDecl *theClass);
1081+
1082+
/// Returns true if SIL/IR lowering for the given declaration should be skipped.
1083+
/// A declaration may not require lowering if, for example, it is annotated as
1084+
/// unavailable and optimization settings allow it to be omitted.
1085+
LLVM_LIBRARY_VISIBILITY bool shouldSkipLowering(Decl *D);
10811086
} // namespace Lowering
10821087

1088+
/// Apply the given function to each ABI member of \c D skipping the members
1089+
/// that should be skipped according to \c shouldSkipLowering()
1090+
template <typename F>
1091+
void forEachMemberToLower(IterableDeclContext *D, F &&f) {
1092+
for (auto *member : D->getABIMembers()) {
1093+
if (!Lowering::shouldSkipLowering(member))
1094+
f(member);
1095+
}
1096+
}
10831097
} // namespace swift
10841098

10851099
#endif

include/swift/SIL/SILVTableVisitor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,9 @@ template <class T> class SILVTableVisitor {
141141
if (!theClass->hasKnownSwiftImplementation())
142142
return;
143143

144-
for (auto member : theClass->getABIMembers())
144+
forEachMemberToLower(theClass, [&](Decl *member) {
145145
maybeAddMember(member);
146+
});
146147
}
147148
};
148149

lib/AST/Availability.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,12 @@ AvailabilityInference::parentDeclForInferredAvailability(const Decl *D) {
181181
return NTD;
182182
}
183183

184+
if (auto *PBD = dyn_cast<PatternBindingDecl>(D))
185+
return PBD->getAnchoringVarDecl(0);
186+
187+
if (auto *OTD = dyn_cast<OpaqueTypeDecl>(D))
188+
return OTD->getNamingDecl();
189+
184190
// Clang decls may be inaccurately parented rdar://53956555
185191
if (D->hasClangNode())
186192
return nullptr;

lib/AST/Decl.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,8 @@ AvailabilityContext Decl::getAvailabilityForLinkage() const {
11001100
return *containingContext;
11011101
}
11021102

1103+
// FIXME: Adopt AvailabilityInference::parentDeclForInferredAvailability()
1104+
// here instead of duplicating the logic.
11031105
if (auto *accessor = dyn_cast<AccessorDecl>(this))
11041106
return accessor->getStorage()->getAvailabilityForLinkage();
11051107

lib/Frontend/CompilerInvocation.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,21 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
550550
Args.hasArg(OPT_disable_availability_checking);
551551
Opts.CheckAPIAvailabilityOnly |=
552552
Args.hasArg(OPT_check_api_availability_only);
553+
554+
if (const Arg *A = Args.getLastArg(OPT_unavailable_decl_optimization_EQ)) {
555+
auto value =
556+
llvm::StringSwitch<Optional<UnavailableDeclOptimization>>(A->getValue())
557+
.Case("none", UnavailableDeclOptimization::None)
558+
.Case("complete", UnavailableDeclOptimization::Complete)
559+
.Default(None);
560+
561+
if (value)
562+
Opts.UnavailableDeclOptimizationMode = *value;
563+
else
564+
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
565+
A->getAsString(Args), A->getValue());
566+
}
567+
553568
Opts.WeakLinkAtTarget |= Args.hasArg(OPT_weak_link_at_target);
554569

555570
if (auto A = Args.getLastArg(OPT_enable_conformance_availability_errors,

lib/IRGen/GenDecl.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2456,9 +2456,13 @@ void swift::irgen::disableAddressSanitizer(IRGenModule &IGM, llvm::GlobalVariabl
24562456

24572457
/// Emit a global declaration.
24582458
void IRGenModule::emitGlobalDecl(Decl *D) {
2459+
if (Lowering::shouldSkipLowering(D))
2460+
return;
2461+
24592462
D->visitAuxiliaryDecls([&](Decl *decl) {
24602463
emitGlobalDecl(decl);
24612464
});
2465+
24622466
switch (D->getKind()) {
24632467
case DeclKind::Extension:
24642468
return emitExtension(cast<ExtensionDecl>(D));
@@ -5485,6 +5489,9 @@ Address IRGenModule::getAddrOfEnumCase(EnumElementDecl *Case,
54855489

54865490
void IRGenModule::emitNestedTypeDecls(DeclRange members) {
54875491
for (Decl *member : members) {
5492+
if (Lowering::shouldSkipLowering(member))
5493+
continue;
5494+
54885495
member->visitAuxiliaryDecls([&](Decl *decl) {
54895496
emitNestedTypeDecls({decl, nullptr});
54905497
});

lib/IRGen/GenStruct.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1572,6 +1572,9 @@ void IRGenModule::emitStructDecl(StructDecl *st) {
15721572
}
15731573

15741574
void IRGenModule::maybeEmitOpaqueTypeDecl(OpaqueTypeDecl *opaque) {
1575+
if (Lowering::shouldSkipLowering(opaque))
1576+
return;
1577+
15751578
if (IRGen.Opts.EnableAnonymousContextMangledNames) {
15761579
// If we're emitting anonymous context mangled names for debuggability,
15771580
// then emit all opaque type descriptors and make them runtime-discoverable

lib/IRGen/TBDGen.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,9 @@ void TBDGenVisitor::addSymbol(StringRef name, SymbolSource source,
414414
}
415415

416416
bool TBDGenVisitor::willVisitDecl(Decl *D) {
417+
if (Lowering::shouldSkipLowering(D))
418+
return false;
419+
417420
// A @_silgen_name("...") function without a body only exists to
418421
// forward-declare a symbol from another library.
419422
if (auto AFD = dyn_cast<AbstractFunctionDecl>(D))

0 commit comments

Comments
 (0)