14
14
#include " swift/SILOptimizer/PassManager/Transforms.h"
15
15
#include " swift/SIL/SILModule.h"
16
16
#include " swift/Serialization/SerializedSILLoader.h"
17
+ #include " swift/Serialization/SerializedModuleLoader.h"
17
18
18
19
using namespace swift ;
19
20
20
21
static llvm::cl::opt<bool > LinkEmbeddedRuntime (" link-embedded-runtime" ,
21
22
llvm::cl::init (true ));
22
23
24
+ static llvm::cl::opt<bool > LinkUsedFunctions (" link-used-functions" ,
25
+ llvm::cl::init (true ));
26
+
23
27
// ===----------------------------------------------------------------------===//
24
28
// Top Level Driver
25
29
// ===----------------------------------------------------------------------===//
@@ -45,6 +49,12 @@ class SILLinker : public SILModuleTransform {
45
49
if (M.getOptions ().EmbeddedSwift && LinkEmbeddedRuntime) {
46
50
linkEmbeddedRuntimeFromStdlib ();
47
51
}
52
+
53
+ // In embedded Swift, we need to explicitly link any @_used globals and
54
+ // functions from imported modules.
55
+ if (M.getOptions ().EmbeddedSwift && LinkUsedFunctions) {
56
+ linkUsedGlobalsAndFunctions ();
57
+ }
48
58
}
49
59
50
60
void linkEmbeddedRuntimeFromStdlib () {
@@ -82,23 +92,103 @@ class SILLinker : public SILModuleTransform {
82
92
// Don't link allocating runtime functions in -no-allocations mode.
83
93
if (M.getOptions ().NoAllocations && allocating) return ;
84
94
85
- // Bail if runtime function is already loaded.
86
- if (M.lookUpFunction (name)) return ;
95
+ // Swift Runtime functions are all expected to be SILLinkage::PublicExternal
96
+ linkUsedFunctionByName (name, SILLinkage::PublicExternal);
97
+ }
98
+
99
+ SILFunction *linkUsedFunctionByName (StringRef name,
100
+ std::optional<SILLinkage> Linkage) {
101
+ SILModule &M = *getModule ();
87
102
88
- SILFunction *Fn =
89
- M.getSILLoader ()->lookupSILFunction (name, SILLinkage::PublicExternal);
90
- if (!Fn) return ;
103
+ // Bail if function is already loaded.
104
+ if (auto *Fn = M.lookUpFunction (name)) return Fn;
105
+
106
+ SILFunction *Fn = M.getSILLoader ()->lookupSILFunction (name, Linkage);
107
+ if (!Fn) return nullptr ;
91
108
92
109
if (M.linkFunction (Fn, LinkMode))
93
110
invalidateAnalysis (Fn, SILAnalysis::InvalidationKind::Everything);
94
111
95
- // Make sure that dead-function-elimination doesn't remove runtime functions.
112
+ // Make sure that dead-function-elimination doesn't remove the explicitly
113
+ // linked functions.
114
+ //
96
115
// TODO: lazily emit runtime functions in IRGen so that we don't have to
97
116
// rely on dead-stripping in the linker to remove unused runtime
98
117
// functions.
99
118
if (Fn->isDefinition ())
100
119
Fn->setLinkage (SILLinkage::Public);
120
+
121
+ return Fn;
122
+ }
123
+
124
+ SILGlobalVariable *linkUsedGlobalVariableByName (StringRef name) {
125
+ SILModule &M = *getModule ();
126
+
127
+ // Bail if runtime function is already loaded.
128
+ if (auto *GV = M.lookUpGlobalVariable (name)) return GV;
129
+
130
+ SILGlobalVariable *GV = M.getSILLoader ()->lookupSILGlobalVariable (name);
131
+ if (!GV) return nullptr ;
132
+
133
+ // Make sure that dead-function-elimination doesn't remove the explicitly
134
+ // linked global variable.
135
+ if (GV->isDefinition ())
136
+ GV->setLinkage (SILLinkage::Public);
137
+
138
+ return GV;
101
139
}
140
+
141
+ void linkUsedGlobalsAndFunctions () {
142
+ SmallVector<VarDecl *, 32 > Globals;
143
+ SmallVector<AbstractFunctionDecl *, 32 > Functions;
144
+ collectUsedDeclsFromLoadedModules (Globals, Functions);
145
+
146
+ for (auto *G : Globals) {
147
+ auto declRef = SILDeclRef (G, SILDeclRef::Kind::Func);
148
+ linkUsedGlobalVariableByName (declRef.mangle ());
149
+ }
150
+
151
+ for (auto *F : Functions) {
152
+ auto declRef = SILDeclRef (F, SILDeclRef::Kind::Func);
153
+ auto *Fn = linkUsedFunctionByName (declRef.mangle (), /* Linkage*/ {});
154
+
155
+ // If we have @_cdecl or @_silgen_name, also link the foreign thunk
156
+ if (Fn->hasCReferences ()) {
157
+ auto declRef = SILDeclRef (F, SILDeclRef::Kind::Func, /* isForeign*/ true );
158
+ linkUsedFunctionByName (declRef.mangle (), /* Linkage*/ {});
159
+ }
160
+ }
161
+ }
162
+
163
+ void collectUsedDeclsFromLoadedModules (
164
+ SmallVectorImpl<VarDecl *> &Globals,
165
+ SmallVectorImpl<AbstractFunctionDecl *> &Functions) {
166
+ SILModule &M = *getModule ();
167
+
168
+ for (const auto &Entry : M.getASTContext ().getLoadedModules ()) {
169
+ for (auto File : Entry.second ->getFiles ()) {
170
+ if (auto LoadedAST = dyn_cast<SerializedASTFile>(File)) {
171
+ auto matcher = [](const DeclAttributes &attrs) -> bool {
172
+ return attrs.hasAttribute <UsedAttr>();
173
+ };
174
+
175
+ SmallVector<Decl *, 32 > Decls;
176
+ LoadedAST->getTopLevelDeclsWhereAttributesMatch (Decls, matcher);
177
+
178
+ for (Decl *D : Decls) {
179
+ if (AbstractFunctionDecl *F = dyn_cast<AbstractFunctionDecl>(D)) {
180
+ Functions.push_back (F);
181
+ } else if (VarDecl *G = dyn_cast<VarDecl>(D)) {
182
+ Globals.push_back (G);
183
+ } else {
184
+ assert (false && " only funcs and globals can be @_used" );
185
+ }
186
+ }
187
+ }
188
+ }
189
+ }
190
+ }
191
+
102
192
};
103
193
} // end anonymous namespace
104
194
0 commit comments