Skip to content

Commit aab5f7a

Browse files
authored
Revert "SIL: Remove special meaning for @_semantics("stdlib_binary_only")" (#12270)
It still affects StdlibUnittest, which is still using -sil-serialize-all.
1 parent b9384f5 commit aab5f7a

19 files changed

+135
-39
lines changed

docs/HighLevelSILOptimizations.rst

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,15 @@ Cloning code from the standard library
117117
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
118118

119119
The Swift compiler can copy code from the standard library into the
120-
application for functions marked @_inlineable. This allows the optimizer to
121-
inline calls from the stdlib and improve the performance of code that uses
122-
common operators such as '+=' or basic containers such as Array. However,
123-
importing code from the standard library can increase the binary size.
124-
125-
To prevent copying of functions from the standard library into the user
126-
program, make sure the function in question is not marked @_inlineable.
120+
application. This allows the optimizer to inline calls from stdlib and improve
121+
the performance of code that uses common operators such as '++' or basic
122+
containers such as Array. However, importing code from the standard library can
123+
increase the binary size. Marking functions with @_semantics("stdlib_binary_only")
124+
will prevent the copying of the marked function from the standard library into the
125+
user program.
126+
127+
Notice that this annotation is similar to the resilient annotation that will
128+
disallow the cloning of code into the user application.
127129

128130
Array
129131
~~~~~

lib/SIL/Linker.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,26 @@ using namespace Lowering;
2626

2727
STATISTIC(NumFuncLinked, "Number of SIL functions linked");
2828

29+
//===----------------------------------------------------------------------===//
30+
// Utility
31+
//===----------------------------------------------------------------------===//
32+
33+
/// \return True if the function \p F should be imported into the current
34+
/// module.
35+
static bool shouldImportFunction(SILFunction *F) {
36+
// Skip functions that are marked with the 'no import' tag. These
37+
// are functions that we don't want to copy from the module.
38+
if (F->hasSemanticsAttr("stdlib_binary_only")) {
39+
// If we are importing a function declaration mark it as external since we
40+
// are not importing the body.
41+
if (F->isExternalDeclaration())
42+
F->setLinkage(SILLinkage::PublicExternal);
43+
return false;
44+
}
45+
46+
return true;
47+
}
48+
2949
//===----------------------------------------------------------------------===//
3050
// Linker Helpers
3151
//===----------------------------------------------------------------------===//
@@ -35,6 +55,9 @@ bool SILLinkerVisitor::processFunction(SILFunction *F) {
3555
if (Mode == LinkingMode::LinkNone)
3656
return false;
3757

58+
if (!shouldImportFunction(F))
59+
return false;
60+
3861
// If F is a declaration, first deserialize it.
3962
if (F->isExternalDeclaration()) {
4063
auto *NewFn = Loader->lookupSILFunction(F);
@@ -311,6 +334,9 @@ bool SILLinkerVisitor::process() {
311334
while (!Worklist.empty()) {
312335
auto *Fn = Worklist.pop_back_val();
313336

337+
if (!shouldImportFunction(Fn))
338+
continue;
339+
314340
DEBUG(llvm::dbgs() << "Process imports in function: "
315341
<< Fn->getName() << "\n");
316342

@@ -320,6 +346,9 @@ bool SILLinkerVisitor::process() {
320346
if (visit(&I)) {
321347
for (auto *F : FunctionDeserializationWorklist) {
322348

349+
if (!shouldImportFunction(F))
350+
continue;
351+
323352
DEBUG(llvm::dbgs() << "Imported function: "
324353
<< F->getName() << "\n");
325354
F->setBare(IsBare);

lib/SILOptimizer/IPO/GlobalOpt.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,9 +1353,11 @@ void SILGlobalOpt::replaceFindStringCall(ApplyInst *FindStringCall) {
13531353
if (!FD)
13541354
return;
13551355

1356-
SILDeclRef declRef(FD, SILDeclRef::Kind::Func);
1357-
SILFunction *replacementFunc = Module->getOrCreateFunction(
1358-
FindStringCall->getLoc(), declRef, NotForDefinition);
1356+
std::string Mangled = SILDeclRef(FD, SILDeclRef::Kind::Func).mangle();
1357+
SILFunction *replacementFunc = Module->findFunction(Mangled,
1358+
SILLinkage::PublicExternal);
1359+
if (!replacementFunc)
1360+
return;
13591361

13601362
SILFunctionType *FTy = replacementFunc->getLoweredFunctionType();
13611363
if (FTy->getNumParameters() != 3)
@@ -1365,7 +1367,6 @@ void SILGlobalOpt::replaceFindStringCall(ApplyInst *FindStringCall) {
13651367
NominalTypeDecl *cacheDecl = cacheType.getNominalOrBoundGenericNominal();
13661368
if (!cacheDecl)
13671369
return;
1368-
13691370
SILType wordTy = cacheType.getFieldType(
13701371
cacheDecl->getStoredProperties().front(), *Module);
13711372

lib/SILOptimizer/Utils/Local.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,11 @@ SILLinkage swift::getSpecializedLinkage(SILFunction *F, SILLinkage L) {
423423
return SILLinkage::Private;
424424
}
425425

426-
return SILLinkage::Shared;
426+
// Treat stdlib_binary_only specially. We don't serialize the body of
427+
// stdlib_binary_only functions so we can't mark them as Shared (making
428+
// their visibility in the dylib hidden).
429+
return F->hasSemanticsAttr("stdlib_binary_only") ? SILLinkage::Public
430+
: SILLinkage::Shared;
427431
}
428432

429433
/// Remove all instructions in the body of \p BB in safe manner by using

stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,7 @@ func _stdlib_installTrapInterceptor()
627627
#endif
628628

629629
// Avoid serializing references to objc_setUncaughtExceptionHandler in SIL.
630-
@inline(never)
630+
@inline(never) @_semantics("stdlib_binary_only")
631631
func _childProcess() {
632632
_stdlib_installTrapInterceptor()
633633

stdlib/public/core/AssertCommon.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,10 @@ func _fatalErrorFlags() -> UInt32 {
8282
///
8383
/// This function should not be inlined because it is cold and inlining just
8484
/// bloats code.
85-
@_versioned // FIXME(sil-serialize-all)
85+
@_inlineable // FIXME(sil-serialize-all)
86+
@_versioned
8687
@inline(never)
88+
@_semantics("stdlib_binary_only")
8789
internal func _assertionFailure(
8890
_ prefix: StaticString, _ message: StaticString,
8991
file: StaticString, line: UInt,
@@ -112,8 +114,10 @@ internal func _assertionFailure(
112114
///
113115
/// This function should not be inlined because it is cold and inlining just
114116
/// bloats code.
115-
@_versioned // FIXME(sil-serialize-all)
117+
@_inlineable // FIXME(sil-serialize-all)
118+
@_versioned
116119
@inline(never)
120+
@_semantics("stdlib_binary_only")
117121
internal func _assertionFailure(
118122
_ prefix: StaticString, _ message: String,
119123
file: StaticString, line: UInt,
@@ -142,8 +146,10 @@ internal func _assertionFailure(
142146
///
143147
/// This function should not be inlined because it is cold and it inlining just
144148
/// bloats code.
145-
@_versioned // FIXME(sil-serialize-all)
149+
@_inlineable // FIXME(sil-serialize-all)
150+
@_versioned
146151
@inline(never)
152+
@_semantics("stdlib_binary_only")
147153
@_semantics("arc.programtermination_point")
148154
internal func _fatalErrorMessage(
149155
_ prefix: StaticString, _ message: StaticString,

stdlib/public/core/DebuggerSupport.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,10 @@ public enum _DebuggerSupport {
305305
}
306306

307307
// LLDB uses this function in expressions, and if it is inlined the resulting
308-
// LLVM IR is enormous. As a result, to improve LLDB performance we are not
309-
// making it @_inlineable.
308+
// LLVM IR is enormous. As a result, to improve LLDB performance we have made
309+
// this stdlib_binary_only, which prevents inlining.
310+
@_inlineable // FIXME(sil-serialize-all)
311+
@_semantics("stdlib_binary_only")
310312
public static func stringForPrintObject(_ value: Any) -> String {
311313
var maxItemCounter = Int.max
312314
var refs = Set<ObjectIdentifier>()

stdlib/public/core/HashedCollections.swift.gyb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2862,7 +2862,9 @@ public func _dictionaryUpCast<DerivedKey, DerivedValue, BaseKey, BaseValue>(
28622862
///
28632863
/// - Precondition: `SwiftKey` and `SwiftValue` are bridged to Objective-C,
28642864
/// and at least one of them requires non-trivial bridging.
2865+
@_inlineable // FIXME(sil-serialize-all)
28652866
@inline(never)
2867+
@_semantics("stdlib_binary_only")
28662868
public func _dictionaryBridgeToObjectiveC<
28672869
SwiftKey, SwiftValue, ObjCKey, ObjCValue
28682870
>(

stdlib/public/core/OutputStream.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,9 +343,11 @@ internal func _adHocPrint_unlocked<T, TargetStream : TextOutputStream>(
343343
}
344344
}
345345

346+
@_inlineable // FIXME(sil-serialize-all)
346347
@_versioned
347348
@inline(never)
348349
@_semantics("optimize.sil.specialize.generic.never")
350+
@_semantics("stdlib_binary_only")
349351
internal func _print_unlocked<T, TargetStream : TextOutputStream>(
350352
_ value: T, _ target: inout TargetStream
351353
) {

stdlib/public/core/Print.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@
4949
/// space (`" "`).
5050
/// - terminator: The string to print after all items have been printed. The
5151
/// default is a newline (`"\n"`).
52+
@_inlineable // FIXME(sil-serialize-all)
5253
@inline(never)
54+
@_semantics("stdlib_binary_only")
5355
public func print(
5456
_ items: Any...,
5557
separator: String = " ",
@@ -108,7 +110,9 @@ public func print(
108110
/// space (`" "`).
109111
/// - terminator: The string to print after all items have been printed. The
110112
/// default is a newline (`"\n"`).
113+
@_inlineable // FIXME(sil-serialize-all)
111114
@inline(never)
115+
@_semantics("stdlib_binary_only")
112116
public func debugPrint(
113117
_ items: Any...,
114118
separator: String = " ",
@@ -224,8 +228,10 @@ public func debugPrint<Target : TextOutputStream>(
224228
items, separator: separator, terminator: terminator, to: &output)
225229
}
226230

231+
@_inlineable // FIXME(sil-serialize-all)
227232
@_versioned
228233
@inline(never)
234+
@_semantics("stdlib_binary_only")
229235
internal func _print<Target : TextOutputStream>(
230236
_ items: [Any],
231237
separator: String = " ",
@@ -243,8 +249,10 @@ internal func _print<Target : TextOutputStream>(
243249
output.write(terminator)
244250
}
245251

252+
@_inlineable // FIXME(sil-serialize-all)
246253
@_versioned
247254
@inline(never)
255+
@_semantics("stdlib_binary_only")
248256
internal func _debugPrint<Target : TextOutputStream>(
249257
_ items: [Any],
250258
separator: String = " ",

stdlib/public/core/REPL.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ func _replPrintLiteralString(_ text: String) {
1818
}
1919

2020
/// Print the debug representation of `value`, followed by a newline.
21+
@_inlineable // FIXME(sil-serialize-all)
2122
@inline(never)
23+
@_semantics("stdlib_binary_only")
2224
public // COMPILER_INTRINSIC
2325
func _replDebugPrintln<T>(_ value: T) {
2426
debugPrint(value)

stdlib/public/core/StringBridge.swift

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,9 @@ func _stdlib_binary_CFStringGetCharactersPtr(
4747

4848
/// Bridges `source` to `Swift.String`, assuming that `source` has non-ASCII
4949
/// characters (does not apply ASCII optimizations).
50+
@_inlineable // FIXME(sil-serialize-all)
5051
@_versioned // FIXME(sil-serialize-all)
51-
@inline(never) // Hide the CF dependency
52+
@inline(never) @_semantics("stdlib_binary_only") // Hide the CF dependency
5253
func _cocoaStringToSwiftString_NonASCII(
5354
_ source: _CocoaString
5455
) -> String {
@@ -69,8 +70,9 @@ func _cocoaStringToSwiftString_NonASCII(
6970

7071
/// Produces a `_StringBuffer` from a given subrange of a source
7172
/// `_CocoaString`, having the given minimum capacity.
73+
@_inlineable // FIXME(sil-serialize-all)
7274
@_versioned // FIXME(sil-serialize-all)
73-
@inline(never) // Hide the CF dependency
75+
@inline(never) @_semantics("stdlib_binary_only") // Hide the CF dependency
7476
internal func _cocoaStringToContiguous(
7577
source: _CocoaString, range: Range<Int>, minimumCapacity: Int
7678
) -> _StringBuffer {
@@ -92,8 +94,9 @@ internal func _cocoaStringToContiguous(
9294

9395
/// Reads the entire contents of a _CocoaString into contiguous
9496
/// storage of sufficient capacity.
97+
@_inlineable // FIXME(sil-serialize-all)
9598
@_versioned // FIXME(sil-serialize-all)
96-
@inline(never) // Hide the CF dependency
99+
@inline(never) @_semantics("stdlib_binary_only") // Hide the CF dependency
97100
internal func _cocoaStringReadAll(
98101
_ source: _CocoaString, _ destination: UnsafeMutablePointer<UTF16.CodeUnit>
99102
) {
@@ -102,8 +105,9 @@ internal func _cocoaStringReadAll(
102105
location: 0, length: _swift_stdlib_CFStringGetLength(source)), destination)
103106
}
104107

108+
@_inlineable // FIXME(sil-serialize-all)
105109
@_versioned // FIXME(sil-serialize-all)
106-
@inline(never) // Hide the CF dependency
110+
@inline(never) @_semantics("stdlib_binary_only") // Hide the CF dependency
107111
internal func _cocoaStringSlice(
108112
_ target: _StringCore, _ bounds: Range<Int>
109113
) -> _StringCore {
@@ -122,8 +126,9 @@ internal func _cocoaStringSlice(
122126
return String(_cocoaString: cfResult)._core
123127
}
124128

125-
@_versioned // FIXME(sil-serialize-all)
126-
@inline(never) // Hide the CF dependency
129+
@_inlineable // FIXME(sil-serialize-all)
130+
@_versioned
131+
@inline(never) @_semantics("stdlib_binary_only") // Hide the CF dependency
127132
internal func _cocoaStringSubscript(
128133
_ target: _StringCore, _ position: Int
129134
) -> UTF16.CodeUnit {
@@ -146,7 +151,8 @@ internal var kCFStringEncodingASCII : _swift_shims_CFStringEncoding {
146151
}
147152

148153
extension String {
149-
@inline(never) // Hide the CF dependency
154+
@_inlineable // FIXME(sil-serialize-all)
155+
@inline(never) @_semantics("stdlib_binary_only") // Hide the CF dependency
150156
public // SPI(Foundation)
151157
init(_cocoaString: AnyObject) {
152158
if let wrapped = _cocoaString as? _NSContiguousString {
@@ -368,7 +374,8 @@ extension String {
368374
return _NSContiguousString(_core)
369375
}
370376

371-
@inline(never) // Hide the CF dependency
377+
@_inlineable // FIXME(sil-serialize-all)
378+
@inline(never) @_semantics("stdlib_binary_only") // Hide the CF dependency
372379
public func _bridgeToObjectiveCImpl() -> AnyObject {
373380
return _stdlib_binary_bridgeToObjectiveCImpl()
374381
}

stdlib/public/core/StringComparable.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ extension String {
7777
#endif
7878

7979
/// Compares two strings with the Unicode Collation Algorithm.
80-
@inline(never) // Hide the CF/ICU dependency
80+
@_inlineable // FIXME(sil-serialize-all)
81+
@inline(never)
82+
@_semantics("stdlib_binary_only") // Hide the CF/ICU dependency
8183
public // @testable
8284
func _compareDeterministicUnicodeCollation(_ rhs: String) -> Int {
8385
// Note: this operation should be consistent with equality comparison of

stdlib/public/core/StringHashable.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,10 @@ extension Unicode {
8282
}
8383
}
8484

85+
// FIXME: cannot be marked @_inlineable. See <rdar://problem/34438258>
86+
// @_inlineable // FIXME(sil-serialize-all)
8587
@_versioned // FIXME(sil-serialize-all)
86-
@inline(never) // Hide the CF dependency
88+
@inline(never) @_semantics("stdlib_binary_only") // Hide the CF dependency
8789
internal func _hashString(_ string: String) -> Int {
8890
let core = string._core
8991
#if _runtime(_ObjC)

stdlib/public/core/StringSwitch.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
/// The compiler intrinsic which is called to lookup a string in a table
1818
/// of static string case values.
19+
@_inlineable // FIXME(sil-serialize-all)
20+
@_semantics("stdlib_binary_only")
1921
@_semantics("findStringSwitchCase")
2022
public // COMPILER_INTRINSIC
2123
func _findStringSwitchCase(
@@ -66,6 +68,8 @@ internal struct _StringSwitchContext {
6668
/// in \p cache. Consecutive calls use the cache for faster lookup.
6769
/// The \p cases array must not change between subsequent calls with the
6870
/// same \p cache.
71+
@_inlineable // FIXME(sil-serialize-all)
72+
@_semantics("stdlib_binary_only")
6973
@_semantics("findStringSwitchCaseWithCache")
7074
public // COMPILER_INTRINSIC
7175
func _findStringSwitchCaseWithCache(

test/SILOptimizer/Inputs/linker_pass_input.swift

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,23 @@
22
@_silgen_name("unknown")
33
public func unknown() -> ()
44

5-
@_inlineable
65
public func doSomething() {
76
unknown()
87
}
98

9+
@_semantics("stdlib_binary_only")
1010
public func doSomething2() {
1111
unknown()
1212
}
1313

1414
@inline(never)
15+
@_semantics("stdlib_binary_only")
1516
public func doSomething3<T>(_ a:T) {
1617
unknown()
1718
}
1819

19-
@_versioned struct A {
20-
@_versioned init() {}
21-
}
22-
20+
struct A {}
2321
@inline(never)
24-
@_inlineable
2522
public func callDoSomething3() {
2623
doSomething3(A())
2724
}

0 commit comments

Comments
 (0)