Skip to content

Commit 8fa74fa

Browse files
authored
Merge pull request swiftlang#22664 from slavapestov/always-emit-into-client
SIL: Introduce '@_alwaysEmitIntoClient' attribute for use by standard library
2 parents 6b0dee5 + bd6490b commit 8fa74fa

13 files changed

+79
-11
lines changed

include/swift/AST/Attr.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,9 @@ DECL_ATTR(_private, PrivateImport,
387387
OnImport |
388388
UserInaccessible |
389389
NotSerialized, 82)
390+
SIMPLE_DECL_ATTR(_alwaysEmitIntoClient, AlwaysEmitIntoClient,
391+
OnVar | OnSubscript | OnAbstractFunction | UserInaccessible,
392+
83)
390393

391394
#undef TYPE_ATTR
392395
#undef DECL_ATTR_ALIAS

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4079,6 +4079,7 @@ ERROR(usable_from_inline_attr_in_protocol,none,
40794079
#define FRAGILE_FUNC_KIND \
40804080
"%select{a '@_transparent' function|" \
40814081
"an '@inlinable' function|" \
4082+
"an '@_alwaysEmitIntoClient' function|" \
40824083
"a default argument value|" \
40834084
"a property initializer in a '@_fixed_layout' type}"
40844085

@@ -4112,7 +4113,7 @@ NOTE(resilience_decl_declared_here,
41124113

41134114
ERROR(class_designated_init_inlinable_resilient,none,
41144115
"initializer for class %0 is "
4115-
"'%select{@_transparent|@inlinable|%error}1' and must "
4116+
"'%select{@_transparent|@inlinable|@_alwaysEmitIntoClient|%error}1' and must "
41164117
"delegate to another initializer", (Type, unsigned))
41174118

41184119
ERROR(attribute_invalid_on_stored_property,

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5252
/// describe what change you made. The content of this comment isn't important;
5353
/// it just ensures a conflict if two people change the module format.
5454
/// Don't worry about adhering to the 80-column limit for this line.
55-
const uint16_t SWIFTMODULE_VERSION_MINOR = 473; // Last change: assign ownership qualifier
55+
const uint16_t SWIFTMODULE_VERSION_MINOR = 474; // Last change: @_alwaysEmitIntoClient
5656

5757
using DeclIDField = BCFixed<31>;
5858

lib/AST/Decl.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2518,12 +2518,14 @@ bool ValueDecl::isUsableFromInline() const {
25182518
assert(getFormalAccess() == AccessLevel::Internal);
25192519

25202520
if (getAttrs().hasAttribute<UsableFromInlineAttr>() ||
2521+
getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>() ||
25212522
getAttrs().hasAttribute<InlinableAttr>())
25222523
return true;
25232524

25242525
if (auto *accessor = dyn_cast<AccessorDecl>(this)) {
25252526
auto *storage = accessor->getStorage();
25262527
if (storage->getAttrs().hasAttribute<UsableFromInlineAttr>() ||
2528+
storage->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>() ||
25272529
storage->getAttrs().hasAttribute<InlinableAttr>())
25282530
return true;
25292531
}

lib/AST/DeclContext.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -360,11 +360,18 @@ ResilienceExpansion DeclContext::getResilienceExpansion() const {
360360
if (AFD->getAttrs().hasAttribute<InlinableAttr>())
361361
return ResilienceExpansion::Minimal;
362362

363-
// If a property or subscript is @inlinable, the accessors are
364-
// @inlinable also.
365-
if (auto accessor = dyn_cast<AccessorDecl>(AFD))
366-
if (accessor->getStorage()->getAttrs().getAttribute<InlinableAttr>())
363+
if (AFD->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>())
364+
return ResilienceExpansion::Minimal;
365+
366+
// If a property or subscript is @inlinable or @_alwaysEmitIntoClient,
367+
// the accessors are @inlinable or @_alwaysEmitIntoClient also.
368+
if (auto accessor = dyn_cast<AccessorDecl>(AFD)) {
369+
auto *storage = accessor->getStorage();
370+
if (storage->getAttrs().getAttribute<InlinableAttr>())
367371
return ResilienceExpansion::Minimal;
372+
if (storage->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>())
373+
return ResilienceExpansion::Minimal;
374+
}
368375
}
369376
}
370377

lib/SIL/SILDeclRef.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -290,10 +290,18 @@ SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const {
290290
/// or shared linkage.
291291
OnDemand,
292292
/// The declaration should never be made public.
293-
NeverPublic
293+
NeverPublic,
294+
/// The declaration should always be emitted into the client,
295+
AlwaysEmitIntoClient,
294296
};
295297
auto limit = Limit::None;
296298

299+
// @_alwaysEmitIntoClient declarations are like the default arguments of
300+
// public functions; they are roots for dead code elimination and have
301+
// serialized bodies, but no public symbol in the generated binary.
302+
if (d->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>())
303+
limit = Limit::AlwaysEmitIntoClient;
304+
297305
// ivar initializers and destroyers are completely contained within the class
298306
// from which they come, and never get seen externally.
299307
if (isIVarInitializerOrDestroyer()) {
@@ -369,6 +377,8 @@ SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const {
369377
return SILLinkage::Shared;
370378
if (limit == Limit::NeverPublic)
371379
return maybeAddExternal(SILLinkage::Hidden);
380+
if (limit == Limit::AlwaysEmitIntoClient)
381+
return maybeAddExternal(SILLinkage::PublicNonABI);
372382
return maybeAddExternal(SILLinkage::Public);
373383
}
374384
llvm_unreachable("unhandled access");
@@ -464,8 +474,8 @@ IsSerialized_t SILDeclRef::isSerialized() const {
464474

465475
auto *d = getDecl();
466476

467-
// Default argument generators are serialized if the function was
468-
// type-checked in Swift 4 mode.
477+
// Default argument generators are serialized if the containing
478+
// declaration is public.
469479
if (isDefaultArgGenerator()) {
470480
ResilienceExpansion expansion;
471481
if (auto *EED = dyn_cast<EnumElementDecl>(d)) {

lib/Sema/ResilienceDiagnostics.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,21 @@ TypeChecker::getFragileFunctionKind(const DeclContext *DC) {
5858
return std::make_pair(FragileFunctionKind::Inlinable,
5959
/*treatUsableFromInlineAsPublic=*/true);
6060

61+
if (AFD->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>())
62+
return std::make_pair(FragileFunctionKind::AlwaysEmitIntoClient,
63+
/*treatUsableFromInlineAsPublic=*/true);
64+
6165
// If a property or subscript is @inlinable, the accessors are
6266
// @inlinable also.
63-
if (auto accessor = dyn_cast<AccessorDecl>(AFD))
64-
if (accessor->getStorage()->getAttrs().getAttribute<InlinableAttr>())
67+
if (auto accessor = dyn_cast<AccessorDecl>(AFD)) {
68+
auto *storage = accessor->getStorage();
69+
if (storage->getAttrs().getAttribute<InlinableAttr>())
6570
return std::make_pair(FragileFunctionKind::Inlinable,
6671
/*treatUsableFromInlineAsPublic=*/true);
72+
if (storage->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>())
73+
return std::make_pair(FragileFunctionKind::AlwaysEmitIntoClient,
74+
/*treatUsableFromInlineAsPublic=*/true);
75+
}
6776
}
6877
}
6978

lib/Sema/TypeCheckAttr.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class AttributeEarlyChecker : public AttributeVisitor<AttributeEarlyChecker> {
7272
bool visitDeclAttribute(DeclAttribute *A) = delete;
7373

7474
#define IGNORED_ATTR(X) void visit##X##Attr(X##Attr *) {}
75+
IGNORED_ATTR(AlwaysEmitIntoClient)
7576
IGNORED_ATTR(Available)
7677
IGNORED_ATTR(HasInitialValue)
7778
IGNORED_ATTR(CDecl)
@@ -739,6 +740,7 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
739740
void visit##CLASS##Attr(CLASS##Attr *) {}
740741

741742
IGNORED_ATTR(Alignment)
743+
IGNORED_ATTR(AlwaysEmitIntoClient)
742744
IGNORED_ATTR(Borrowed)
743745
IGNORED_ATTR(HasInitialValue)
744746
IGNORED_ATTR(ClangImporterSynthesizedType)

lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,6 +1246,7 @@ namespace {
12461246

12471247
UNINTERESTING_ATTR(AccessControl)
12481248
UNINTERESTING_ATTR(Alignment)
1249+
UNINTERESTING_ATTR(AlwaysEmitIntoClient)
12491250
UNINTERESTING_ATTR(Borrowed)
12501251
UNINTERESTING_ATTR(CDecl)
12511252
UNINTERESTING_ATTR(Consuming)

lib/Sema/TypeChecker.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1925,6 +1925,7 @@ class TypeChecker final : public LazyResolver {
19251925
enum class FragileFunctionKind : unsigned {
19261926
Transparent,
19271927
Inlinable,
1928+
AlwaysEmitIntoClient,
19281929
DefaultArgument,
19291930
PropertyInitializer
19301931
};

0 commit comments

Comments
 (0)