Skip to content

Commit 44a9753

Browse files
authored
Merge pull request #41703 from eeckstein/simplify-linkage
Stabilize and simplify SIL linkage and serialization
2 parents d1b60c8 + 6a020f8 commit 44a9753

File tree

159 files changed

+789
-946
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

159 files changed

+789
-946
lines changed

include/swift/SIL/SILFunction.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ class SILFunction
262262
unsigned Transparent : 1;
263263

264264
/// The function's serialized attribute.
265-
unsigned Serialized : 2;
265+
bool Serialized : 1;
266266

267267
/// Specifies if this function is a thunk or a reabstraction thunk.
268268
///
@@ -689,10 +689,7 @@ class SILFunction
689689

690690
/// Returns true if this function can be inlined into a fragile function
691691
/// body.
692-
bool hasValidLinkageForFragileInline() const {
693-
return (isSerialized() == IsSerialized ||
694-
isSerialized() == IsSerializable);
695-
}
692+
bool hasValidLinkageForFragileInline() const { return isSerialized(); }
696693

697694
/// Returns true if this function can be referenced from a fragile function
698695
/// body.
@@ -914,7 +911,11 @@ class SILFunction
914911

915912
/// Get this function's serialized attribute.
916913
IsSerialized_t isSerialized() const { return IsSerialized_t(Serialized); }
917-
void setSerialized(IsSerialized_t isSerialized) { Serialized = isSerialized; }
914+
void setSerialized(IsSerialized_t isSerialized) {
915+
Serialized = isSerialized;
916+
assert(this->isSerialized() == isSerialized &&
917+
"too few bits for Serialized storage");
918+
}
918919

919920
/// Get this function's thunk attribute.
920921
IsThunk_t isThunk() const { return IsThunk_t(Thunk); }

include/swift/SIL/SILLinkage.h

Lines changed: 55 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -38,33 +38,51 @@ enum class SILLinkage : uint8_t {
3838
/// This object definition is visible to multiple Swift modules (and
3939
/// thus potentially across linkage-unit boundaries). There are no
4040
/// other object definitions with this name in the program.
41+
///
42+
/// Public functions must be definitions, i.e. must have a body, except the
43+
/// body is emitted by clang.
4144
Public,
4245

4346
/// This is a special linkage used for symbols which are treated
4447
/// as public for the purposes of SIL serialization and optimization,
4548
/// but do not have public entry points in the generated binary.
4649
///
50+
/// This linkage is used for @_alwaysEmitIntoClient functions.
51+
///
4752
/// There is no external variant of this linkage, because from other
4853
/// translation units in the same module, this behaves identically
4954
/// to the HiddenExternal linkage.
5055
///
5156
/// When deserialized, such declarations receive Shared linkage.
57+
///
58+
/// PublicNonABI functions must be definitions.
5259
PublicNonABI,
5360

5461
/// This object definition is visible only to the current Swift
5562
/// module (and thus should not be visible across linkage-unit
5663
/// boundaries). There are no other object definitions with this
5764
/// name in the module.
65+
///
66+
/// Hidden functions must be definitions, i.e. must have a body, except the
67+
/// body is emitted by clang.
5868
Hidden,
5969

6070
/// This object definition is visible only within a single Swift
6171
/// module. There may be other object definitions with this name in
6272
/// the module; those definitions are all guaranteed to be
6373
/// semantically equivalent to this one.
74+
///
75+
/// This linkage is used e.g. for thunks and for specialized functions.
76+
///
77+
/// Public functions must be definitions, i.e. must have a body, except the
78+
/// body is emitted by clang.
6479
Shared,
6580

6681
/// This object definition is visible only within a single Swift
6782
/// file.
83+
///
84+
/// Private functions must be definitions, i.e. must have a body, except the
85+
/// body is emitted by clang.
6886
Private,
6987

7088
/// A Public definition with the same name as this object will be
@@ -74,17 +92,12 @@ enum class SILLinkage : uint8_t {
7492
PublicExternal,
7593

7694
/// A Public or Hidden definition with the same name as this object
77-
/// will be defined by the current Swift module at runtime. If this
78-
/// object is a definition, it is semantically equivalent to that
79-
/// definition.
95+
/// will be defined by the current Swift module at runtime.
96+
///
97+
/// This linkage is only used for non-whole-module compilations to refer to
98+
/// functions in other files of the same module.
8099
HiddenExternal,
81100

82-
/// This Shared definition was imported from another module. It is not
83-
/// necessary to serialize it since it can be deserialized from the original
84-
/// module. Besides that caveat this should be treated exactly the same as
85-
/// shared.
86-
SharedExternal,
87-
88101
/// The default linkage for a definition.
89102
DefaultForDefinition = Public,
90103

@@ -97,14 +110,40 @@ enum {
97110
NumSILLinkageBits = 4
98111
};
99112

100-
/// Related to linkage: flag if a function or global variable is serialized,
101-
/// either unconditionally, or if referenced from another serialized function.
113+
/// Related to linkage: flag if a function, global variable, vtable or witness
114+
/// table is serialized.
115+
///
116+
/// Used, e.g. for @inlinable functions.
117+
///
118+
/// This flag serves for two purposes:
119+
/// * Imposes restrictions for optimizations. For example, non-serialized functions
120+
/// cannot be inlined into serialized functions, because that could expose
121+
/// internal types/functions to client modules.
122+
/// * Tells the serializer which functions (and tables) need to be serialized:
123+
/// - all public functions with the IsSerialized flag and
124+
/// - all IsSerialized shared functions which are referenced from such functions.
125+
///
126+
/// After the swiftmodule file is written, the IsSerialized flag is cleared from
127+
/// all functions. This means that optimizations after the serialization point
128+
/// are not limited anymore regarding serialized functions.
102129
enum IsSerialized_t : unsigned char {
103-
// Never serialized.
130+
131+
/// The function is not inlinable and will not be serialized.
104132
IsNotSerialized,
105-
// Serialized if referenced from another serialized function.
106-
IsSerializable,
107-
// Always serialized.
133+
134+
/// The function (or table) will be serialized.
135+
///
136+
/// This flag is only valid for Public, PublicNonABI, PublicExternal,
137+
/// HiddenExternal and Shared functions.
138+
/// Functions with external linkage (PublicExternl, HiddenExternal) will not
139+
/// be serialized, because they are available in a different module (from which
140+
/// they were de-serialized).
141+
///
142+
/// Functions with Shared linkage will only be serialized if they are referenced
143+
/// from another serialized function (or table).
144+
///
145+
/// This flag is removed from all functions after the serialization point in
146+
/// the optimizer pipeline.
108147
IsSerialized
109148
};
110149

@@ -131,8 +170,6 @@ inline SILLinkage stripExternalFromLinkage(SILLinkage linkage) {
131170
return SILLinkage::Public;
132171
if (linkage == SILLinkage::HiddenExternal)
133172
return SILLinkage::Hidden;
134-
if (linkage == SILLinkage::SharedExternal)
135-
return SILLinkage::Shared;
136173
return linkage;
137174
}
138175

@@ -146,13 +183,11 @@ inline SILLinkage addExternalToLinkage(SILLinkage linkage) {
146183
// if the function was emitted in another translation unit of the
147184
// same Swift module, so we treat it as hidden here.
148185
return SILLinkage::HiddenExternal;
149-
case SILLinkage::Shared:
150-
return SILLinkage::SharedExternal;
151186
case SILLinkage::Hidden:
152187
return SILLinkage::HiddenExternal;
188+
case SILLinkage::Shared:
153189
case SILLinkage::Private:
154190
case SILLinkage::PublicExternal:
155-
case SILLinkage::SharedExternal:
156191
case SILLinkage::HiddenExternal:
157192
return linkage;
158193
}
@@ -186,7 +221,6 @@ inline bool hasPublicVisibility(SILLinkage linkage) {
186221
return true;
187222
case SILLinkage::Hidden:
188223
case SILLinkage::Shared:
189-
case SILLinkage::SharedExternal:
190224
case SILLinkage::Private:
191225
case SILLinkage::HiddenExternal:
192226
return false;
@@ -198,7 +232,6 @@ inline bool hasPublicVisibility(SILLinkage linkage) {
198232
inline bool hasSharedVisibility(SILLinkage linkage) {
199233
switch (linkage) {
200234
case SILLinkage::Shared:
201-
case SILLinkage::SharedExternal:
202235
return true;
203236
case SILLinkage::Public:
204237
case SILLinkage::PublicExternal:
@@ -222,7 +255,6 @@ inline bool hasPrivateVisibility(SILLinkage linkage) {
222255
case SILLinkage::Hidden:
223256
case SILLinkage::HiddenExternal:
224257
case SILLinkage::Shared:
225-
case SILLinkage::SharedExternal:
226258
return false;
227259
}
228260

include/swift/SIL/SILModule.h

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ class SILModule {
167167
llvm::DenseMap<const SILBasicBlock *, std::string>;
168168

169169
enum class LinkingMode : uint8_t {
170-
/// Link functions with non-public linkage. Used by the mandatory pipeline.
170+
/// Link functions with shared linkage. Used by the mandatory pipeline.
171171
LinkNormal,
172172

173173
/// Link all functions. Used by the performance pipeine.
@@ -349,6 +349,8 @@ class SILModule {
349349
/// to ensure that the module is serialized only once.
350350
bool serialized;
351351

352+
bool parsedAsSerializedSIL;
353+
352354
/// Set if we have registered a deserialization notification handler for
353355
/// lowering ownership in non transparent functions.
354356
/// This gets set in NonTransparent OwnershipModelEliminator pass.
@@ -455,6 +457,12 @@ class SILModule {
455457
void setSerialized() { serialized = true; }
456458
bool isSerialized() const { return serialized; }
457459

460+
void setParsedAsSerializedSIL() {
461+
serialized = true;
462+
parsedAsSerializedSIL = true;
463+
}
464+
bool isParsedAsSerializedSIL() const { return parsedAsSerializedSIL; }
465+
458466
void setBasicBlockName(const SILBasicBlock *block, StringRef name) {
459467
#ifndef NDEBUG
460468
basicBlockNames[block] = name.str();
@@ -688,9 +696,20 @@ class SILModule {
688696
/// \return null if this module has no such function
689697
SILFunction *lookUpFunction(SILDeclRef fnRef);
690698

691-
/// Attempt to deserialize the SILFunction. Returns true if deserialization
692-
/// succeeded, false otherwise.
693-
bool loadFunction(SILFunction *F);
699+
/// Attempt to deserialize function \p F and all functions which are referenced
700+
/// from \p F (according to the \p LinkMode).
701+
///
702+
/// Returns true if deserialization succeeded, false otherwise.
703+
bool loadFunction(SILFunction *F, LinkingMode LinkMode);
704+
705+
/// Attempt to deserialize a function with \p name and all functions which are
706+
/// referenced from that function (according to the \p LinkMode).
707+
///
708+
/// If \p linkage is provided, the deserialized function is required to have
709+
/// that linkage. Returns null, if this is not the case.
710+
SILFunction *loadFunction(StringRef name,
711+
LinkingMode LinkMode,
712+
Optional<SILLinkage> linkage = None);
694713

695714
/// Update the linkage of the SILFunction with the linkage of the serialized
696715
/// function.
@@ -699,19 +718,10 @@ class SILModule {
699718
/// AST, e.g. cross-module-optimization can change the SIL linkages.
700719
void updateFunctionLinkage(SILFunction *F);
701720

702-
/// Attempt to link the SILFunction. Returns true if linking succeeded, false
703-
/// otherwise.
704-
///
705-
/// \return false if the linking failed.
706-
bool linkFunction(SILFunction *F,
707-
LinkingMode LinkMode = LinkingMode::LinkNormal);
708-
709-
/// Check if a given function exists in any of the modules with a
710-
/// required linkage, i.e. it can be linked by linkFunction.
721+
/// Attempt to deserialize function \p F and all required referenced functions.
711722
///
712-
/// \return null if this module has no such function. Otherwise
713-
/// the declaration of a function.
714-
SILFunction *findFunction(StringRef Name, SILLinkage Linkage);
723+
/// Returns true if linking succeeded, false otherwise.
724+
bool linkFunction(SILFunction *F, LinkingMode LinkMode);
715725

716726
/// Check if a given function exists in any of the modules.
717727
/// i.e. it can be linked by linkFunction.
@@ -725,15 +735,15 @@ class SILModule {
725735
/// table.
726736
/// \arg deserializeLazily If we cannot find the witness table should we
727737
/// attempt to lazily deserialize it.
728-
SILWitnessTable *
729-
lookUpWitnessTable(ProtocolConformanceRef C, bool deserializeLazily=true);
730-
SILWitnessTable *
731-
lookUpWitnessTable(const ProtocolConformance *C, bool deserializeLazily=true);
738+
SILWitnessTable *lookUpWitnessTable(const ProtocolConformance *C);
732739

733740
/// Attempt to lookup \p Member in the witness table for \p C.
741+
///
742+
/// Also, deserialize all referenced functions according to the \p linkgingMode.
734743
std::pair<SILFunction *, SILWitnessTable *>
735744
lookUpFunctionInWitnessTable(ProtocolConformanceRef C,
736-
SILDeclRef Requirement);
745+
SILDeclRef Requirement,
746+
SILModule::LinkingMode linkingMode);
737747

738748
/// Look up the SILDefaultWitnessTable representing the default witnesses
739749
/// of a resilient protocol, if any.

include/swift/SIL/SILVTable.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ class SILVTable final : public SILAllocated<SILVTable>,
144144

145145
/// Sets the serialized flag.
146146
void setSerialized(IsSerialized_t serialized) {
147-
assert(serialized != IsSerializable);
148147
Serialized = (serialized ? 1 : 0);
149148
}
150149

include/swift/SIL/SILWitnessTable.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,6 @@ class SILWitnessTable : public llvm::ilist_node<SILWitnessTable>,
260260

261261
/// Sets the serialized flag.
262262
void setSerialized(IsSerialized_t serialized) {
263-
assert(serialized != IsSerializable);
264263
Serialized = (serialized ? 1 : 0);
265264
}
266265

include/swift/Serialization/SerializedSILLoader.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,7 @@ class SerializedSILLoader {
6060
~SerializedSILLoader();
6161

6262
SILFunction *lookupSILFunction(SILFunction *Callee, bool onlyUpdateLinkage);
63-
SILFunction *
64-
lookupSILFunction(StringRef Name, bool declarationOnly = false,
65-
Optional<SILLinkage> linkage = None);
63+
SILFunction *lookupSILFunction(StringRef Name, Optional<SILLinkage> linkage);
6664
bool hasSILFunction(StringRef Name, Optional<SILLinkage> linkage = None);
6765
SILVTable *lookupVTable(const ClassDecl *C);
6866
SILWitnessTable *lookupWitnessTable(SILWitnessTable *C);

lib/IRGen/GenDecl.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2106,7 +2106,6 @@ getIRLinkage(const UniversalLinkageInfo &info, SILLinkage linkage,
21062106
: RESULT(External, Hidden, Default);
21072107

21082108
case SILLinkage::Shared:
2109-
case SILLinkage::SharedExternal:
21102109
return isDefinition ? RESULT(LinkOnceODR, Hidden, Default)
21112110
: RESULT(External, Hidden, Default);
21122111

lib/IRGen/GenMeta.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2080,7 +2080,6 @@ namespace {
20802080
return true;
20812081

20822082
case SILLinkage::Shared:
2083-
case SILLinkage::SharedExternal:
20842083
case SILLinkage::PublicNonABI:
20852084
return false;
20862085
}

lib/IRGen/IRGenModule.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1152,7 +1152,7 @@ bool IRGenerator::canEmitWitnessTableLazily(SILWitnessTable *wt) {
11521152
}
11531153

11541154
void IRGenerator::addLazyWitnessTable(const ProtocolConformance *Conf) {
1155-
if (auto *wt = SIL.lookUpWitnessTable(Conf, /*deserializeLazily=*/false)) {
1155+
if (auto *wt = SIL.lookUpWitnessTable(Conf)) {
11561156
// Add it to the queue if it hasn't already been put there.
11571157
if (canEmitWitnessTableLazily(wt) &&
11581158
LazilyEmittedWitnessTables.insert(wt).second) {

0 commit comments

Comments
 (0)