Skip to content

Commit 6aafeec

Browse files
author
Zak Kent
committed
[Immediate] [SILGen] Implement on-demand compilation of globals
1 parent e276c79 commit 6aafeec

File tree

11 files changed

+211
-42
lines changed

11 files changed

+211
-42
lines changed

include/swift/AST/SILGenRequests.h

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "swift/AST/EvaluatorDependencies.h"
2222
#include "swift/AST/SimpleRequest.h"
2323
#include "swift/AST/SourceFile.h"
24+
#include "swift/AST/TBDGenRequests.h"
2425
#include "swift/SIL/SILDeclRef.h"
2526

2627
namespace swift {
@@ -43,6 +44,8 @@ void reportEvaluatedRequest(UnifiedStatsReporter &stats,
4344

4445
using SILRefsToEmit = llvm::SmallVector<SILDeclRef, 1>;
4546

47+
using SymbolSources = llvm::SmallVector<SymbolSource, 1>;
48+
4649
/// Describes a file or module to be lowered to SIL.
4750
struct ASTLoweringDescriptor {
4851
llvm::PointerUnion<FileUnit *, ModuleDecl *> context;
@@ -52,20 +55,17 @@ struct ASTLoweringDescriptor {
5255

5356
/// A specific set of SILDeclRefs to emit. If set, only these refs will be
5457
/// emitted. Otherwise the entire \c context will be emitted.
55-
llvm::Optional<SILRefsToEmit> refsToEmit;
58+
llvm::Optional<SymbolSources> SourcesToEmit;
5659

5760
friend llvm::hash_code hash_value(const ASTLoweringDescriptor &owner) {
5861
return llvm::hash_combine(owner.context, (void *)&owner.conv,
59-
(void *)&owner.opts,
60-
owner.refsToEmit);
62+
(void *)&owner.opts, owner.SourcesToEmit);
6163
}
6264

6365
friend bool operator==(const ASTLoweringDescriptor &lhs,
6466
const ASTLoweringDescriptor &rhs) {
65-
return lhs.context == rhs.context &&
66-
&lhs.conv == &rhs.conv &&
67-
&lhs.opts == &rhs.opts &&
68-
lhs.refsToEmit == rhs.refsToEmit;
67+
return lhs.context == rhs.context && &lhs.conv == &rhs.conv &&
68+
&lhs.opts == &rhs.opts && lhs.SourcesToEmit == rhs.SourcesToEmit;
6969
}
7070

7171
friend bool operator!=(const ASTLoweringDescriptor &lhs,
@@ -76,17 +76,19 @@ struct ASTLoweringDescriptor {
7676
public:
7777
static ASTLoweringDescriptor
7878
forFile(FileUnit &sf, Lowering::TypeConverter &conv, const SILOptions &opts,
79-
llvm::Optional<SILRefsToEmit> refsToEmit = llvm::None,
79+
llvm::Optional<SymbolSources> SourcesToEmit = llvm::None,
8080
const IRGenOptions *irgenOptions = nullptr) {
81-
return ASTLoweringDescriptor{&sf, conv, opts, irgenOptions, refsToEmit};
81+
return ASTLoweringDescriptor{&sf, conv, opts, irgenOptions,
82+
std::move(SourcesToEmit)};
8283
}
8384

8485
static ASTLoweringDescriptor
8586
forWholeModule(ModuleDecl *mod, Lowering::TypeConverter &conv,
8687
const SILOptions &opts,
87-
llvm::Optional<SILRefsToEmit> refsToEmit = llvm::None,
88+
llvm::Optional<SymbolSources> SourcesToEmit = llvm::None,
8889
const IRGenOptions *irgenOptions = nullptr) {
89-
return ASTLoweringDescriptor{mod, conv, opts, irgenOptions, refsToEmit};
90+
return ASTLoweringDescriptor{mod, conv, opts, irgenOptions,
91+
std::move(SourcesToEmit)};
9092
}
9193

9294
/// Retrieves the files to generate SIL for. If the descriptor is configured

include/swift/AST/TBDGenRequests.h

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#ifndef SWIFT_TBDGEN_REQUESTS_H
1818
#define SWIFT_TBDGEN_REQUESTS_H
1919

20+
#include "llvm/ExecutionEngine/JITSymbol.h"
21+
2022
#include "swift/AST/ASTTypeIDs.h"
2123
#include "swift/AST/SimpleRequest.h"
2224
#include "swift/IRGen/Linking.h"
@@ -148,6 +150,10 @@ class SymbolSource {
148150
/// A symbol introduced when emitting a SIL decl.
149151
SIL,
150152

153+
/// A symbol introduced when emitting a SIL global variable.
154+
/// Only used in piecewise compilation for Immediate mode.
155+
Global,
156+
151157
/// A symbol introduced when emitting LLVM IR.
152158
IR,
153159

@@ -162,13 +168,17 @@ class SymbolSource {
162168

163169
private:
164170
union {
171+
VarDecl *Global;
165172
SILDeclRef silDeclRef;
166173
irgen::LinkEntity irEntity;
167174
};
168175

169176
explicit SymbolSource(SILDeclRef ref) : kind(Kind::SIL) {
170177
silDeclRef = ref;
171178
}
179+
180+
SymbolSource(VarDecl *Global) : kind(Kind::Global), Global(Global) {}
181+
172182
explicit SymbolSource(irgen::LinkEntity entity) : kind(Kind::IR) {
173183
irEntity = entity;
174184
}
@@ -180,6 +190,9 @@ class SymbolSource {
180190
static SymbolSource forSILDeclRef(SILDeclRef ref) {
181191
return SymbolSource{ref};
182192
}
193+
194+
static SymbolSource forGlobal(VarDecl *Global) { return Global; }
195+
183196
static SymbolSource forIRLinkEntity(irgen::LinkEntity entity) {
184197
return SymbolSource{entity};
185198
}
@@ -198,10 +211,84 @@ class SymbolSource {
198211
assert(kind == Kind::SIL);
199212
return silDeclRef;
200213
}
214+
215+
VarDecl *getGlobal() const {
216+
assert(kind == Kind::Global);
217+
return Global;
218+
}
219+
201220
irgen::LinkEntity getIRLinkEntity() const {
202221
assert(kind == Kind::IR);
203222
return irEntity;
204223
}
224+
225+
/// Typecheck the entity wrapped by this `SymbolSource`
226+
void typecheck() const {
227+
switch (kind) {
228+
case Kind::SIL: {
229+
if (auto *AFD = silDeclRef.getAbstractFunctionDecl())
230+
// If this entity is a `SILFunction`, check its body
231+
AFD->getTypecheckedBody();
232+
break;
233+
}
234+
case Kind::Global:
235+
case Kind::IR:
236+
case Kind::LinkerDirective:
237+
case Kind::Unknown:
238+
// Nothing to do
239+
break;
240+
}
241+
}
242+
243+
friend llvm::hash_code hash_value(const SymbolSource &S) {
244+
auto Kind = S.kind;
245+
switch (Kind) {
246+
case Kind::SIL:
247+
return llvm::hash_combine(Kind, S.silDeclRef);
248+
case Kind::Global:
249+
return llvm::hash_combine(Kind, S.Global);
250+
case Kind::IR:
251+
return llvm::hash_combine(Kind, S.irEntity);
252+
case Kind::LinkerDirective:
253+
case Kind::Unknown:
254+
return llvm::hash_value(Kind);
255+
}
256+
}
257+
258+
friend bool operator==(const SymbolSource &LHS, const SymbolSource &RHS) {
259+
if (LHS.kind != RHS.kind)
260+
return false;
261+
switch (LHS.kind) {
262+
case Kind::SIL:
263+
return LHS.silDeclRef == RHS.silDeclRef;
264+
case Kind::Global:
265+
return LHS.Global == RHS.Global;
266+
case Kind::IR:
267+
return LHS.irEntity == RHS.irEntity;
268+
case Kind::LinkerDirective:
269+
case Kind::Unknown:
270+
return true;
271+
}
272+
}
273+
274+
friend bool operator!=(const SymbolSource &LHS, const SymbolSource &RHS) {
275+
return !(LHS == RHS);
276+
}
277+
278+
llvm::JITSymbolFlags getJITSymbolFlags() const {
279+
switch (kind) {
280+
case Kind::SIL:
281+
return llvm::JITSymbolFlags::Callable | llvm::JITSymbolFlags::Exported;
282+
case Kind::Global:
283+
return llvm::JITSymbolFlags::Exported;
284+
case Kind::IR:
285+
llvm_unreachable("Unimplemented: Symbol flags for LinkEntities");
286+
case Kind::LinkerDirective:
287+
llvm_unreachable("Unsupported: Symbol flags for linker directives");
288+
case Kind::Unknown:
289+
llvm_unreachable("Unsupported: Symbol flags for unknown source");
290+
}
291+
}
205292
};
206293

207294
/// Maps a symbol back to its source for lazy compilation.

include/swift/IRGen/Linking.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,20 @@ class LinkEntity {
515515
return Kind(LINKENTITY_GET_FIELD(Data, Kind));
516516
}
517517

518+
friend llvm::hash_code hash_value(const LinkEntity &Entity) {
519+
return llvm::hash_combine(Entity.Pointer, Entity.SecondaryPointer,
520+
Entity.Data);
521+
}
522+
523+
friend bool operator==(const LinkEntity &LHS, const LinkEntity &RHS) {
524+
return LHS.Pointer == RHS.Pointer &&
525+
LHS.SecondaryPointer == RHS.SecondaryPointer && LHS.Data == RHS.Data;
526+
}
527+
528+
friend bool operator!=(const LinkEntity &LHS, const LinkEntity &RHS) {
529+
return !(LHS == RHS);
530+
}
531+
518532
static bool isDeclKind(Kind k) {
519533
return k <= Kind::AsyncFunctionPointerAST;
520534
}

include/swift/Subsystems.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#ifndef SWIFT_SUBSYSTEMS_H
1818
#define SWIFT_SUBSYSTEMS_H
1919

20+
#include "swift/AST/TBDGenRequests.h"
2021
#include "swift/Basic/LLVM.h"
2122
#include "swift/Basic/OptionSet.h"
2223
#include "swift/Basic/PrimarySpecificPaths.h"
@@ -193,7 +194,7 @@ namespace swift {
193194
/// SIL of all files in the module is present in the SILModule.
194195
std::unique_ptr<SILModule>
195196
performASTLowering(CompilerInstance &CI,
196-
llvm::SmallVector<SILDeclRef, 1> Refs);
197+
llvm::SmallVector<SymbolSource, 1> Sources);
197198

198199
/// Turn a source file into SIL IR.
199200
std::unique_ptr<SILModule>

lib/IRGen/IRGen.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,6 +1097,7 @@ getSymbolSourcesToEmit(const IRGenDescriptor &desc) {
10971097
break;
10981098
case SymbolSource::Kind::LinkerDirective:
10991099
case SymbolSource::Kind::Unknown:
1100+
case SymbolSource::Kind::Global:
11001101
llvm_unreachable("Not supported");
11011102
}
11021103
}
@@ -1122,9 +1123,8 @@ GeneratedModule IRGenRequest::evaluate(Evaluator &evaluator,
11221123
// SIL for the file or module.
11231124
auto SILMod = std::unique_ptr<SILModule>(desc.SILMod);
11241125
if (!SILMod) {
1125-
auto loweringDesc = ASTLoweringDescriptor{
1126-
desc.Ctx, desc.Conv, desc.SILOpts, nullptr,
1127-
symsToEmit.transform([](const auto &x) { return x.silRefsToEmit; })};
1126+
auto loweringDesc = ASTLoweringDescriptor{desc.Ctx, desc.Conv, desc.SILOpts,
1127+
nullptr, llvm::None};
11281128
SILMod = llvm::cantFail(Ctx.evaluator(LoweredSILRequest{loweringDesc}));
11291129

11301130
// If there was an error, bail.

lib/IRGen/TBDGen.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,9 +441,8 @@ void TBDGenVisitor::addFunction(StringRef name, SILDeclRef declRef) {
441441
}
442442

443443
void TBDGenVisitor::addGlobalVar(VarDecl *VD) {
444-
// FIXME: We ought to have a symbol source for this.
445444
Mangle::ASTMangler mangler;
446-
addSymbol(mangler.mangleEntity(VD), SymbolSource::forUnknown());
445+
addSymbol(mangler.mangleEntity(VD), SymbolSource::forGlobal(VD));
447446
}
448447

449448
void TBDGenVisitor::addLinkEntity(LinkEntity entity) {

lib/Immediate/SwiftMaterializationUnit.cpp

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -298,14 +298,15 @@ LazySwiftMaterializationUnit::Create(SwiftJIT &JIT, CompilerInstance &CI) {
298298
llvm::orc::SymbolFlagsMap PublicInterface;
299299
for (const auto &Entry : *Sources) {
300300
const auto &Source = Entry.getValue();
301-
if (Source.kind != SymbolSource::Kind::SIL) {
302-
continue;
303-
}
304301
const auto &SymbolName = Entry.getKey();
305-
auto Flags =
306-
llvm::JITSymbolFlags::Callable | llvm::JITSymbolFlags::Exported;
307-
auto MangledName = mangle(SymbolName);
308-
PublicInterface[JIT.intern(MangledName)] = Flags;
302+
auto Flags = Source.getJITSymbolFlags();
303+
if (Flags.isCallable()) {
304+
// Only create lazy reexports for callable symbols
305+
auto MangledName = mangle(SymbolName);
306+
PublicInterface[JIT.intern(MangledName)] = Flags;
307+
} else {
308+
PublicInterface[JIT.intern(SymbolName)] = Flags;
309+
}
309310
}
310311
return std::unique_ptr<LazySwiftMaterializationUnit>(
311312
new LazySwiftMaterializationUnit(JIT, CI, std::move(Sources),
@@ -324,24 +325,22 @@ LazySwiftMaterializationUnit::LazySwiftMaterializationUnit(
324325

325326
void LazySwiftMaterializationUnit::materialize(
326327
std::unique_ptr<llvm::orc::MaterializationResponsibility> MR) {
327-
SILRefsToEmit Refs;
328+
SymbolSources Entities;
328329
const auto &RS = MR->getRequestedSymbols();
329330
for (auto &Sym : RS) {
330331
auto Name = demangle(*Sym);
331332
auto itr = Sources->find(Name);
332333
assert(itr != Sources->end() && "Requested symbol doesn't have source?");
333334
const auto &Source = itr->getValue();
334-
auto Ref = Source.getSILDeclRef();
335-
if (auto *AFD = Ref.getAbstractFunctionDecl()) {
336-
AFD->getTypecheckedBody();
337-
if (CI.getASTContext().hadError()) {
338-
MR->failMaterialization();
339-
return;
340-
}
335+
Source.typecheck();
336+
if (CI.getASTContext().hadError()) {
337+
// If encounter type error, bail out
338+
MR->failMaterialization();
339+
return;
341340
}
342-
Refs.push_back(std::move(Ref));
341+
Entities.push_back(Source);
343342
}
344-
auto SM = performASTLowering(CI, std::move(Refs));
343+
auto SM = performASTLowering(CI, std::move(Entities));
345344

346345
// Promote linkages of SIL entities
347346
// defining requested symbols so they are

lib/SIL/IR/SILModule.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -865,9 +865,27 @@ void SILModule::installSILRemarkStreamer() {
865865
}
866866

867867
void SILModule::promoteLinkages() {
868-
for (auto &Fn : functions)
868+
for (auto &Fn : functions) {
869+
// Ignore functions with shared linkage
870+
if (Fn.getLinkage() == SILLinkage::Shared)
871+
continue;
872+
869873
if (Fn.isDefinition())
870874
Fn.setLinkage(SILLinkage::Public);
875+
else
876+
Fn.setLinkage(SILLinkage::PublicExternal);
877+
}
878+
879+
for (auto &Global : silGlobals) {
880+
// Ignore globals with shared linkage
881+
if (Global.getLinkage() == SILLinkage::Shared)
882+
continue;
883+
884+
if (Global.isDefinition())
885+
Global.setLinkage(SILLinkage::Public);
886+
else
887+
Global.setLinkage(SILLinkage::PublicExternal);
888+
}
871889

872890
// TODO: Promote linkage of other SIL entities
873891
}

0 commit comments

Comments
 (0)