Skip to content

Commit 17fedab

Browse files
author
Zak Kent
committed
[Immediate] Implemented SwiftMaterializationUnit
Implemented SwiftMaterializationUnit, supporting lazy compilation of individual Swift functions.
1 parent 94530c7 commit 17fedab

File tree

8 files changed

+254
-15
lines changed

8 files changed

+254
-15
lines changed

include/swift/AST/TBDGenRequests.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,13 +209,13 @@ class SymbolSourceMap {
209209
friend class SymbolSourceMapRequest;
210210

211211
using Storage = llvm::StringMap<SymbolSource>;
212-
const Storage *storage;
213212

214-
explicit SymbolSourceMap(const Storage *storage) : storage(storage) {
213+
explicit SymbolSourceMap(Storage *storage) : storage(storage) {
215214
assert(storage);
216215
}
217216

218217
public:
218+
Storage *storage;
219219
llvm::Optional<SymbolSource> find(StringRef symbol) const {
220220
auto result = storage->find(symbol);
221221
if (result == storage->end())

include/swift/AST/TypeCheckRequests.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2997,8 +2997,8 @@ class TypeCheckSourceFileRequest
29972997
friend SimpleRequest;
29982998

29992999
// Evaluation.
3000-
evaluator::SideEffect
3001-
evaluate(Evaluator &evaluator, SourceFile *SF) const;
3000+
evaluator::SideEffect evaluate(Evaluator &evaluator, SourceFile *SF,
3001+
bool CheckFunctionBodies = true) const;
30023002

30033003
public:
30043004
// Separate caching.

include/swift/Immediate/Immediate.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ namespace swift {
4141
int RunImmediately(CompilerInstance &CI, const ProcessCmdLine &CmdLine,
4242
const IRGenOptions &IRGenOpts, const SILOptions &SILOpts,
4343
std::unique_ptr<SILModule> &&SM);
44+
45+
int RunImmediatelyFromAST(CompilerInstance &CI);
46+
4447
} // end namespace swift
4548

4649
#endif // SWIFT_IMMEDIATE_IMMEDIATE_H

include/swift/Subsystems.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include "swift/Basic/OptionSet.h"
2222
#include "swift/Basic/PrimarySpecificPaths.h"
2323
#include "swift/Basic/Version.h"
24+
#include "swift/Frontend/Frontend.h"
25+
#include "swift/SIL/SILDeclRef.h"
2426
#include "llvm/ADT/ArrayRef.h"
2527
#include "llvm/ADT/StringRef.h"
2628
#include "llvm/ADT/StringSet.h"
@@ -185,6 +187,14 @@ namespace swift {
185187
const SILOptions &options,
186188
const IRGenOptions *irgenOptions = nullptr);
187189

190+
/// Turn the given module into SIL IR.
191+
///
192+
/// The module must contain source files. The optimizer will assume that the
193+
/// SIL of all files in the module is present in the SILModule.
194+
std::unique_ptr<SILModule>
195+
performASTLowering(CompilerInstance &CI,
196+
llvm::SmallVector<SILDeclRef, 1> Refs);
197+
188198
/// Turn a source file into SIL IR.
189199
std::unique_ptr<SILModule>
190200
performASTLowering(FileUnit &SF, Lowering::TypeConverter &TC,

lib/FrontendTool/FrontendTool.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,10 @@ bool swift::performCompileStepsPostSema(CompilerInstance &Instance,
843843
Instance.getPrimarySpecificPathsForWholeModuleOptimizationMode();
844844
SILOptions SILOpts = getSILOptions(PSPs);
845845
IRGenOptions irgenOpts = Invocation.getIRGenOptions();
846+
if (Invocation.getFrontendOptions().RequestedAction ==
847+
FrontendOptions::ActionType::Immediate) {
848+
return RunImmediatelyFromAST(Instance) != -1;
849+
}
846850
auto SM = performASTLowering(mod, Instance.getSILTypes(), SILOpts,
847851
&irgenOpts);
848852
return performCompileStepsPostSILGen(Instance, std::move(SM), mod, PSPs,

lib/Immediate/Immediate.cpp

Lines changed: 215 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include "swift/AST/IRGenOptions.h"
2424
#include "swift/AST/IRGenRequests.h"
2525
#include "swift/AST/Module.h"
26+
#include "swift/AST/SILGenRequests.h"
27+
#include "swift/AST/TBDGenRequests.h"
2628
#include "swift/Basic/LLVM.h"
2729
#include "swift/Frontend/Frontend.h"
2830
#include "swift/IRGen/IRGenPublic.h"
@@ -303,6 +305,7 @@ createLLJIT(const IRGenOptions &IRGenOpts, ASTContext &Ctx) {
303305
}
304306

305307
class SILMaterializationUnit;
308+
class SwiftMaterializationUnit;
306309

307310
/// Wraps an LLJIT instance, adds lazy compilation.
308311
class SwiftJIT {
@@ -351,7 +354,7 @@ class SwiftJIT {
351354
/// Register a the materialization unit `MU` with the `JITDylib``JD` and
352355
/// create lazy reexports for all functions defined in the interface of `MU`
353356
llvm::Error addSwift(llvm::orc::JITDylib &JD,
354-
std::unique_ptr<SILMaterializationUnit> MU);
357+
std::unique_ptr<llvm::orc::MaterializationUnit> MU);
355358

356359
llvm::Error initialize(llvm::orc::JITDylib &JD) { return J->initialize(JD); }
357360

@@ -374,6 +377,10 @@ class SwiftJIT {
374377
return J->mangleAndIntern(Name);
375378
}
376379

380+
llvm::orc::SymbolStringPtr intern(StringRef Name) {
381+
return J->getExecutionSession().intern(Name);
382+
}
383+
377384
llvm::orc::IRCompileLayer &getIRCompileLayer() {
378385
return J->getIRCompileLayer();
379386
}
@@ -489,13 +496,14 @@ static void dumpJIT(llvm::orc::LLJIT &JIT, const llvm::Module &Module,
489496
/// IRGen the provided `SILModule` with the specified options.
490497
/// Returns `std::nullopt` if a compiler error is encountered
491498
static std::optional<GeneratedModule>
492-
generateModule(const CompilerInstance &CI, const IRGenOptions &IRGenOpts,
493-
std::unique_ptr<SILModule> SM) {
499+
generateModule(const CompilerInstance &CI, std::unique_ptr<SILModule> SM) {
494500
// TODO: Use OptimizedIRRequest for this.
495501
const auto &Context = CI.getASTContext();
496502
auto *swiftModule = CI.getMainModule();
497503
const auto PSPs = CI.getPrimarySpecificPathsForAtMostOnePrimary();
498-
const auto &TBDOpts = CI.getInvocation().getTBDGenOptions();
504+
const auto &Invocation = CI.getInvocation();
505+
const auto &TBDOpts = Invocation.getTBDGenOptions();
506+
const auto &IRGenOpts = Invocation.getIRGenOptions();
499507

500508
// Lower the SIL module to LLVM IR
501509
auto GenModule = performIRGeneration(
@@ -527,6 +535,122 @@ static void logError(llvm::Error Err) {
527535
logAllUnhandledErrors(std::move(Err), llvm::errs(), "");
528536
}
529537

538+
/// Allows lazy materialization of `SILDeclRef`s
539+
class SwiftMaterializationUnit : public llvm::orc::MaterializationUnit {
540+
public:
541+
static std::unique_ptr<SwiftMaterializationUnit>
542+
Create(SwiftJIT &JIT, CompilerInstance &CI) {
543+
auto *M = CI.getMainModule();
544+
TBDGenOptions Opts;
545+
Opts.PublicSymbolsOnly = false;
546+
auto TBDDesc = TBDGenDescriptor::forModule(M, std::move(Opts));
547+
SymbolSourceMapRequest SourceReq{TBDDesc};
548+
auto Sources =
549+
llvm::cantFail(M->getASTContext().evaluator(std::move(SourceReq)));
550+
llvm::orc::SymbolFlagsMap PublicInterface;
551+
for (const auto &Entry : *Sources.storage) {
552+
const auto &Source = Entry.getValue();
553+
if (Source.kind != SymbolSource::Kind::SIL) {
554+
continue;
555+
}
556+
auto Ref = Source.getSILDeclRef();
557+
if (Ref.getDefinitionLinkage() != SILLinkage::Public)
558+
continue;
559+
const auto &SymbolName = Entry.getKey();
560+
const auto Flags =
561+
llvm::JITSymbolFlags::Exported | llvm::JITSymbolFlags::Callable;
562+
PublicInterface[JIT.intern(SymbolName)] = Flags;
563+
}
564+
return std::unique_ptr<SwiftMaterializationUnit>(
565+
new SwiftMaterializationUnit(JIT, CI, std::move(Sources),
566+
std::move(PublicInterface)));
567+
}
568+
569+
StringRef getName() const override { return "SwiftMaterializationUnit"; }
570+
571+
private:
572+
SwiftMaterializationUnit(SwiftJIT &JIT, CompilerInstance &CI,
573+
SymbolSourceMap Sources,
574+
llvm::orc::SymbolFlagsMap Symbols)
575+
: MaterializationUnit({std::move(Symbols), nullptr}),
576+
Sources(std::move(Sources)), JIT(JIT), CI(CI) {}
577+
578+
void addGlobal(llvm::orc::SymbolFlagsMap &Symbols,
579+
const llvm::GlobalValue &Global,
580+
const llvm::orc::MaterializationResponsibility &MR) {
581+
// Ignore all symbols that will not appear in symbol table
582+
if (Global.hasLocalLinkage() || Global.hasAppendingLinkage() ||
583+
Global.isDeclaration()) {
584+
return;
585+
}
586+
auto Name = Global.getName();
587+
auto MangledName = JIT.mangleAndIntern(Name);
588+
if (MR.getRequestedSymbols().contains(MangledName)) {
589+
return;
590+
}
591+
Symbols[MangledName] = llvm::JITSymbolFlags::fromGlobalValue(Global);
592+
}
593+
594+
void materialize(
595+
std::unique_ptr<llvm::orc::MaterializationResponsibility> R) override {
596+
SILRefsToEmit Refs;
597+
for (auto &Sym : R->getRequestedSymbols()) {
598+
const auto &Source = Sources.storage->find(*Sym)->getValue();
599+
Refs.push_back(Source.getSILDeclRef());
600+
}
601+
auto SM = performASTLowering(CI, std::move(Refs));
602+
runSILDiagnosticPasses(*SM);
603+
runSILLoweringPasses(*SM);
604+
auto GM = generateModule(CI, std::move(SM));
605+
if (!GM) {
606+
R->failMaterialization();
607+
return;
608+
}
609+
auto *Module = GM->getModule();
610+
// Now we must register all other public symbols defined by
611+
// the module with the JIT
612+
llvm::orc::SymbolFlagsMap LazilyDiscoveredSymbols;
613+
// Register all global objects, including global
614+
// variables and functions
615+
for (const auto &Global : Module->global_objects()) {
616+
addGlobal(LazilyDiscoveredSymbols, Global, *R);
617+
}
618+
// Register all global aliases
619+
for (const auto &Global : Module->aliases()) {
620+
addGlobal(LazilyDiscoveredSymbols, Global, *R);
621+
}
622+
llvm::orc::SymbolFlagsMap UnrequestedSymbols;
623+
for (auto &[Sym, Flags] : R->getSymbols()) {
624+
if (!R->getRequestedSymbols().contains(Sym) &&
625+
!LazilyDiscoveredSymbols.count(Sym)) {
626+
UnrequestedSymbols[Sym] = Flags;
627+
}
628+
}
629+
std::unique_ptr<MaterializationUnit> UnrequestedMU(
630+
new SwiftMaterializationUnit(JIT, CI, std::move(Sources),
631+
std::move(UnrequestedSymbols)));
632+
if (auto Err = R->replace(std::move(UnrequestedMU))) {
633+
logError(std::move(Err));
634+
R->failMaterialization();
635+
return;
636+
}
637+
if (auto Err = R->defineMaterializing(std::move(LazilyDiscoveredSymbols))) {
638+
logError(std::move(Err));
639+
R->failMaterialization();
640+
return;
641+
}
642+
auto TSM = std::move(*GM).intoThreadSafeContext();
643+
JIT.getIRCompileLayer().emit(std::move(R), std::move(TSM));
644+
}
645+
646+
void discard(const llvm::orc::JITDylib &JD,
647+
const llvm::orc::SymbolStringPtr &Sym) override {}
648+
649+
SymbolSourceMap Sources;
650+
SwiftJIT &JIT;
651+
CompilerInstance &CI;
652+
};
653+
530654
/// Lazily materializes an entire SIL module
531655
class SILMaterializationUnit : public llvm::orc::MaterializationUnit {
532656
public:
@@ -539,7 +663,7 @@ class SILMaterializationUnit : public llvm::orc::MaterializationUnit {
539663
void materialize(
540664
std::unique_ptr<llvm::orc::MaterializationResponsibility> R) override {
541665

542-
auto GenModule = generateModule(CI, IRGenOpts, std::move(SM));
666+
auto GenModule = generateModule(CI, std::move(SM));
543667

544668
if (!GenModule) {
545669
R->failMaterialization();
@@ -614,8 +738,9 @@ class SILMaterializationUnit : public llvm::orc::MaterializationUnit {
614738
std::unique_ptr<SILModule> SM;
615739
};
616740

617-
llvm::Error SwiftJIT::addSwift(llvm::orc::JITDylib &JD,
618-
std::unique_ptr<SILMaterializationUnit> MU) {
741+
llvm::Error
742+
SwiftJIT::addSwift(llvm::orc::JITDylib &JD,
743+
std::unique_ptr<llvm::orc::MaterializationUnit> MU) {
619744
// Create stub map.
620745
llvm::orc::SymbolAliasMap Stubs;
621746
for (auto &[Name, Flags] : MU->getSymbols()) {
@@ -749,7 +874,7 @@ int swift::RunImmediately(CompilerInstance &CI, const ProcessCmdLine &CmdLine,
749874
logError(std::move(Err));
750875
return -1;
751876
}
752-
auto GenModule = generateModule(CI, IRGenOpts, std::move(SM));
877+
auto GenModule = generateModule(CI, std::move(SM));
753878
if (!GenModule)
754879
return -1;
755880
auto *Module = GenModule->getModule();
@@ -761,3 +886,85 @@ int swift::RunImmediately(CompilerInstance &CI, const ProcessCmdLine &CmdLine,
761886
}
762887
return runMain(**JIT, CmdLine);
763888
}
889+
890+
int swift::RunImmediatelyFromAST(CompilerInstance &CI) {
891+
892+
auto &Context = CI.getASTContext();
893+
894+
const auto &Invocation = CI.getInvocation();
895+
const auto &FrontendOpts = Invocation.getFrontendOptions();
896+
897+
const ProcessCmdLine &CmdLine = ProcessCmdLine(
898+
FrontendOpts.ImmediateArgv.begin(), FrontendOpts.ImmediateArgv.end());
899+
900+
// Load libSwiftCore to setup process arguments.
901+
//
902+
// This must be done here, before any library loading has been done, to avoid
903+
// racing with the static initializers in user code.
904+
// Setup interpreted process arguments.
905+
using ArgOverride = void (*SWIFT_CC(swift))(const char **, int);
906+
#if defined(_WIN32)
907+
auto stdlib = loadSwiftRuntime(Context.SearchPathOpts.RuntimeLibraryPaths);
908+
if (!stdlib) {
909+
CI.getDiags().diagnose(SourceLoc(),
910+
diag::error_immediate_mode_missing_stdlib);
911+
return -1;
912+
}
913+
auto module = static_cast<HMODULE>(stdlib);
914+
auto emplaceProcessArgs = reinterpret_cast<ArgOverride>(
915+
GetProcAddress(module, "_swift_stdlib_overrideUnsafeArgvArgc"));
916+
if (emplaceProcessArgs == nullptr)
917+
return -1;
918+
#else
919+
// In case the compiler is built with swift modules, it already has the stdlib
920+
// linked to. First try to lookup the symbol with the standard library
921+
// resolving.
922+
auto emplaceProcessArgs =
923+
(ArgOverride)dlsym(RTLD_DEFAULT, "_swift_stdlib_overrideUnsafeArgvArgc");
924+
925+
if (dlerror()) {
926+
// If this does not work (= the Swift modules are not linked to the tool),
927+
// we have to explicitly load the stdlib.
928+
auto stdlib = loadSwiftRuntime(Context.SearchPathOpts.RuntimeLibraryPaths);
929+
if (!stdlib) {
930+
CI.getDiags().diagnose(SourceLoc(),
931+
diag::error_immediate_mode_missing_stdlib);
932+
return -1;
933+
}
934+
dlerror();
935+
emplaceProcessArgs =
936+
(ArgOverride)dlsym(stdlib, "_swift_stdlib_overrideUnsafeArgvArgc");
937+
if (dlerror())
938+
return -1;
939+
}
940+
#endif
941+
942+
SmallVector<const char *, 32> argBuf;
943+
for (size_t i = 0; i < CmdLine.size(); ++i) {
944+
argBuf.push_back(CmdLine[i].c_str());
945+
}
946+
argBuf.push_back(nullptr);
947+
948+
(*emplaceProcessArgs)(argBuf.data(), CmdLine.size());
949+
950+
auto *swiftModule = CI.getMainModule();
951+
const auto &IRGenOpts = Invocation.getIRGenOptions();
952+
if (autolinkImportedModules(swiftModule, IRGenOpts))
953+
return -1;
954+
955+
auto &Target = swiftModule->getASTContext().LangOpts.Target;
956+
assert(Target.isMacOSX());
957+
auto JIT = SwiftJIT::Create(IRGenOpts, swiftModule->getASTContext());
958+
if (auto Err = JIT.takeError()) {
959+
logError(std::move(Err));
960+
return -1;
961+
}
962+
963+
auto MU = SwiftMaterializationUnit::Create(**JIT, CI);
964+
if (auto Err = (*JIT)->addSwift((*JIT)->getMainJITDylib(), std::move(MU))) {
965+
logError(std::move(Err));
966+
return -1;
967+
}
968+
969+
return runMain((*JIT)->getJIT(), CmdLine);
970+
}

lib/SILGen/SILGen.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "swift/AST/TypeCheckRequests.h"
3535
#include "swift/Basic/Statistic.h"
3636
#include "swift/ClangImporter/ClangModule.h"
37+
#include "swift/Frontend/Frontend.h"
3738
#include "swift/SIL/PrettyStackTrace.h"
3839
#include "swift/SIL/SILArgument.h"
3940
#include "swift/SIL/SILDebugScope.h"
@@ -2108,6 +2109,18 @@ swift::performASTLowering(ModuleDecl *mod, Lowering::TypeConverter &tc,
21082109
mod->getASTContext().evaluator(ASTLoweringRequest{desc}));
21092110
}
21102111

2112+
std::unique_ptr<SILModule> swift::performASTLowering(CompilerInstance &CI,
2113+
SILRefsToEmit Refs) {
2114+
auto *M = CI.getMainModule();
2115+
const auto &Invocation = CI.getInvocation();
2116+
const auto &SILOpts = Invocation.getSILOptions();
2117+
const auto &IRGenOpts = Invocation.getIRGenOptions();
2118+
auto &TC = CI.getSILTypes();
2119+
auto Desc =
2120+
ASTLoweringDescriptor::forWholeModule(M, TC, SILOpts, Refs, &IRGenOpts);
2121+
return llvm::cantFail(M->getASTContext().evaluator(ASTLoweringRequest{Desc}));
2122+
}
2123+
21112124
std::unique_ptr<SILModule>
21122125
swift::performASTLowering(FileUnit &sf, Lowering::TypeConverter &tc,
21132126
const SILOptions &options,

0 commit comments

Comments
 (0)