Skip to content

Commit 4ff65cc

Browse files
authored
Merge pull request #83784 from DougGregor/never-emit-into-client
Add @_neverEmitIntoClient to prohibit SIL serialization for a function
2 parents d8edd86 + 2f60d72 commit 4ff65cc

File tree

10 files changed

+118
-1
lines changed

10 files changed

+118
-1
lines changed

include/swift/AST/Decl.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,6 +1068,14 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl>, public Swi
10681068
/// behaviors for it and, if it's an extension, its members.
10691069
bool isObjCImplementation() const;
10701070

1071+
/// True if this declaration should never have its implementation made
1072+
/// available to any client. This overrides cross-module optimization and
1073+
/// optimizations that might use the implementation, such that the only
1074+
/// implementation of this function is the one compiled into its owning
1075+
/// module. Practically speaking, this prohibits serialization of the SIL
1076+
/// for this definition.
1077+
bool isNeverEmittedIntoClient() const;
1078+
10711079
using AuxiliaryDeclCallback = llvm::function_ref<void(Decl *)>;
10721080

10731081
/// Iterate over the auxiliary declarations for this declaration,

include/swift/AST/DeclAttr.def

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,11 @@ SIMPLE_DECL_ATTR(requires_stored_property_inits, RequiresStoredPropertyInits,
201201
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnreachableInABIAttr,
202202
27)
203203

204-
// Unused '28'
204+
SIMPLE_DECL_ATTR(_neverEmitIntoClient, NeverEmitIntoClient,
205+
OnVar | OnSubscript | OnAbstractFunction,
206+
UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr,
207+
28)
208+
205209
// Unused '29'
206210

207211
SIMPLE_DECL_ATTR(nonobjc, NonObjC,

lib/AST/ASTDumper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5011,6 +5011,7 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, Label>,
50115011
TRIVIAL_ATTR_PRINTER(NSApplicationMain, ns_application_main)
50125012
TRIVIAL_ATTR_PRINTER(NSCopying, ns_copying)
50135013
TRIVIAL_ATTR_PRINTER(NSManaged, ns_managed)
5014+
TRIVIAL_ATTR_PRINTER(NeverEmitIntoClient, never_emit_into_client)
50145015
TRIVIAL_ATTR_PRINTER(NoAllocation, no_allocation)
50155016
TRIVIAL_ATTR_PRINTER(NoDerivative, no_derivative)
50165017
TRIVIAL_ATTR_PRINTER(NoEagerMove, no_eager_move)

lib/AST/Decl.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2281,6 +2281,10 @@ bool Decl::isObjCImplementation() const {
22812281
return getAttrs().hasAttribute<ObjCImplementationAttr>(/*AllowInvalid=*/true);
22822282
}
22832283

2284+
bool Decl::isNeverEmittedIntoClient() const {
2285+
return getAttrs().hasAttribute<NeverEmitIntoClientAttr>();
2286+
}
2287+
22842288
PatternBindingDecl::PatternBindingDecl(SourceLoc StaticLoc,
22852289
StaticSpellingKind StaticSpelling,
22862290
SourceLoc VarLoc,

lib/ASTGen/Sources/ASTGen/DeclAttrs.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ extension ASTGenVisitor {
267267
.MainType,
268268
.Marker,
269269
.MoveOnly,
270+
.NeverEmitIntoClient,
270271
.NoAllocation,
271272
.NoDerivative,
272273
.NoEagerMove,

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -887,6 +887,11 @@ SerializedKind_t SILDeclRef::getSerializedKind() const {
887887
ASSERT(ABIRoleInfo(d).providesAPI()
888888
&& "should not get serialization info from ABI-only decl");
889889

890+
// A declaration marked as "never emitted into client" will not have its SIL
891+
// serialized, ever.
892+
if (d->isNeverEmittedIntoClient())
893+
return IsNotSerialized;
894+
890895
// Default and property wrapper argument generators are serialized if the
891896
// containing declaration is public.
892897
if (isDefaultArgGenerator() || (isPropertyWrapperBackingInitializer() &&
@@ -1102,6 +1107,11 @@ bool SILDeclRef::declHasNonUniqueDefinition(const ValueDecl *decl) {
11021107
if (!decl->getASTContext().LangOpts.hasFeature(Feature::Embedded))
11031108
return false;
11041109

1110+
// If the declaration is marked as @_neverEmitIntoClient, it has a unique
1111+
// definition.
1112+
if (decl->isNeverEmittedIntoClient())
1113+
return false;
1114+
11051115
// If the declaration is not from the main module, treat its definition as
11061116
// non-unique.
11071117
auto module = decl->getModuleContext();

lib/Sema/TypeCheckAttr.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
153153

154154
#define IGNORED_ATTR(X) void visit##X##Attr(X##Attr *) {}
155155
IGNORED_ATTR(AlwaysEmitIntoClient)
156+
IGNORED_ATTR(NeverEmitIntoClient)
156157
IGNORED_ATTR(HasInitialValue)
157158
IGNORED_ATTR(ClangImporterSynthesizedType)
158159
IGNORED_ATTR(Convenience)

lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,6 +1589,7 @@ namespace {
15891589
UNINTERESTING_ATTR(AccessControl)
15901590
UNINTERESTING_ATTR(Alignment)
15911591
UNINTERESTING_ATTR(AlwaysEmitIntoClient)
1592+
UNINTERESTING_ATTR(NeverEmitIntoClient)
15921593
UNINTERESTING_ATTR(Borrowed)
15931594
UNINTERESTING_ATTR(Borrowing)
15941595
UNINTERESTING_ATTR(CDecl)

lib/Serialization/SerializeSIL.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3575,6 +3575,12 @@ bool SILSerializer::shouldEmitFunctionBody(const SILFunction *F,
35753575
if (F->isAvailableExternally())
35763576
return false;
35773577

3578+
if (F->getDeclRef().hasDecl()) {
3579+
if (auto decl = F->getDeclRef().getDecl())
3580+
if (decl->isNeverEmittedIntoClient())
3581+
return false;
3582+
}
3583+
35783584
// If we are asked to serialize everything, go ahead and do it.
35793585
if (ShouldSerializeAll)
35803586
return true;
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
4+
// Library module
5+
6+
// SIL checking
7+
// RUN: %target-swift-frontend %t/Library.swift -parse-as-library -entry-point-function-name Library_main -enable-experimental-feature Embedded -emit-sil -emit-module-path %t/Modules/Library.swiftmodule -o - | %FileCheck -check-prefix LIBRARY-SIL %s
8+
9+
// IR checking to ensure we get the right weak symbols.
10+
// RUN: %target-swift-frontend %t/Library.swift -parse-as-library -entry-point-function-name Library_main -enable-experimental-feature Embedded -emit-ir -o - | %FileCheck -check-prefix LIBRARY-IR --dump-input-filter all %s
11+
12+
// Application module
13+
14+
// RUN: %target-swift-frontend %t/Application.swift -I %t/Modules -parse-as-library -entry-point-function-name Application_main -enable-experimental-feature Embedded -emit-sil -o - | %FileCheck -check-prefix APPLICATION-SIL %s
15+
16+
// RUN: %target-swift-frontend %t/Application.swift -I %t/Modules -parse-as-library -entry-point-function-name Application_main -enable-experimental-feature Embedded -emit-ir -o - | %FileCheck -check-prefix APPLICATION-IR %s
17+
18+
// REQUIRES: swift_in_compiler
19+
// REQUIRES: swift_feature_Embedded
20+
21+
//--- Library.swift
22+
23+
// LIBRARY-IR: define {{(protected |dllexport )?}}swiftcc ptr @"$e7Library5helloSaySiGyF"()
24+
@_neverEmitIntoClient
25+
public func hello() -> [Int] {
26+
getArray()
27+
}
28+
29+
// LIBRARY-IR: define {{(protected |dllexport )?}}swiftcc ptr @"$e7Library8getArraySaySiGyF"()
30+
public func getArray() -> [Int] {
31+
throughInternal()
32+
}
33+
34+
// LIBRARY-IR: define {{(protected |dllexport )?}}swiftcc ptr @"$e7Library15throughInternalSaySiGyF"()
35+
func throughInternal() -> [Int] {
36+
throughPrivate()
37+
}
38+
39+
// LIBRARY-IR: define {{(protected |dllexport )?}}swiftcc ptr @"$e7Library14throughPrivate
40+
private func throughPrivate() -> [Int] {
41+
[5, 6, 7]
42+
}
43+
44+
// LIBRARY-IR-NOT: unnecessary
45+
public func unnecessary() -> Int { 5 }
46+
47+
// LIBRARY-IR: define linkonce_odr hidden swiftcc { ptr, ptr } @"$es27_allocateUninitializedArrayySayxG_BptBwlFSi_Tg5"
48+
49+
// LIBRARY-SIL: sil @$e7Library5helloSaySiGyF
50+
// LIBRARY-SIL: sil @$e7Library8getArraySaySiGyF : $@convention(thin) () -> @owned Array<Int> {
51+
52+
//--- Application.swift
53+
import Library
54+
55+
@_neverEmitIntoClient
56+
public func testMe() {
57+
_ = hello()
58+
_ = getArray()
59+
}
60+
61+
// Note: "hello" is emitted only into the object file, so there is no definition
62+
// here.
63+
64+
// APPLICATION-SIL: sil @$e7Library5helloSaySiGyF : $@convention(thin) () -> @owned Array<Int>{{$}}
65+
// APPLICATION-IR: declare swiftcc ptr @"$e7Library5helloSaySiGyF"()
66+
67+
// Note: "getArray" is not @_neverEmitIntoClient, so it's definition is
68+
// available.
69+
70+
// APPLICATION-SIL: sil public_external @$e7Library8getArraySaySiGyF : $@convention(thin) () -> @owned Array<Int> {
71+
// APPLICATION-IR: define linkonce_odr hidden swiftcc ptr @"$e7Library8getArraySaySiGyF"()
72+
73+
// APPLICATION-IR: define{{.*}}@Application_main
74+
@main
75+
struct Main {
76+
static func main() {
77+
}
78+
}
79+
80+
// APPLICATION-IR: define linkonce_odr hidden swiftcc { ptr, ptr } @"$es27_allocateUninitializedArrayySayxG_BptBwlFSi_Tg5"
81+

0 commit comments

Comments
 (0)