Skip to content

Commit c2c41f8

Browse files
author
Zak Kent
committed
[Immediate] Only lazily compile on Darwin
Fallback to eager compilation on Linux and Windows due to issues with older versions of JITLink on those platforms.
1 parent e96f1d8 commit c2c41f8

File tree

1 file changed

+157
-100
lines changed

1 file changed

+157
-100
lines changed

lib/Immediate/Immediate.cpp

Lines changed: 157 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,35 @@ StringRef demangleFunctionBody(const StringRef Mangled) {
273273
return Mangled.drop_back(ManglingSuffix.size());
274274
}
275275

276+
/// Creates an `LLJIT` instance with the given target options and an
277+
/// attached generator that resolves symbols from the current process
278+
static llvm::Expected<std::unique_ptr<llvm::orc::LLJIT>>
279+
createLLJIT(const IRGenOptions &IRGenOpts, ASTContext &Ctx) {
280+
llvm::TargetOptions TargetOpt;
281+
std::string CPU;
282+
std::string Triple;
283+
std::vector<std::string> Features;
284+
std::tie(TargetOpt, CPU, Features, Triple) =
285+
getIRTargetOptions(IRGenOpts, Ctx);
286+
auto JTMB = llvm::orc::JITTargetMachineBuilder(llvm::Triple(Triple))
287+
.setRelocationModel(llvm::Reloc::PIC_)
288+
.setOptions(std::move(TargetOpt))
289+
.setCPU(std::move(CPU))
290+
.addFeatures(Features)
291+
.setCodeGenOptLevel(llvm::CodeGenOpt::Default);
292+
auto J = llvm::orc::LLJITBuilder()
293+
.setJITTargetMachineBuilder(std::move(JTMB))
294+
.create();
295+
if (!J)
296+
return J.takeError();
297+
auto G = llvm::orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
298+
(*J)->getDataLayout().getGlobalPrefix());
299+
if (!G)
300+
return G.takeError();
301+
(*J)->getMainJITDylib().addGenerator(std::move(*G));
302+
return J;
303+
}
304+
276305
class SILMaterializationUnit;
277306

278307
/// Wraps an LLJIT instance, adds lazy compilation.
@@ -288,30 +317,12 @@ class SwiftJIT {
288317
/// current process.
289318
static llvm::Expected<std::unique_ptr<SwiftJIT>>
290319
Create(const IRGenOptions &IRGenOpts, ASTContext &Ctx) {
291-
llvm::TargetOptions TargetOpt;
292-
std::string CPU;
293-
std::string Triple;
294-
std::vector<std::string> Features;
295-
std::tie(TargetOpt, CPU, Features, Triple) =
296-
getIRTargetOptions(IRGenOpts, Ctx);
297-
auto JTMB = llvm::orc::JITTargetMachineBuilder(llvm::Triple(Triple))
298-
.setRelocationModel(llvm::Reloc::PIC_)
299-
.setOptions(std::move(TargetOpt))
300-
.setCPU(std::move(CPU))
301-
.addFeatures(Features)
302-
.setCodeGenOptLevel(llvm::CodeGenOpt::Default);
303-
304-
auto J =
305-
getLLJITBuilder().setJITTargetMachineBuilder(std::move(JTMB)).create();
320+
321+
auto J = createLLJIT(IRGenOpts, Ctx);
306322
if (!J)
307323
return J.takeError();
308324

309325
// Create generator to resolve symbols defined in current process
310-
auto G = llvm::orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
311-
(*J)->getDataLayout().getGlobalPrefix());
312-
if (!G)
313-
return G.takeError();
314-
(*J)->getMainJITDylib().addGenerator(std::move(*G));
315326

316327
auto EPCIU = llvm::orc::EPCIndirectionUtils::Create(
317328
(*J)->getExecutionSession().getExecutorProcessControl());
@@ -333,6 +344,8 @@ class SwiftJIT {
333344
J->getExecutionSession().reportError(std::move(Err));
334345
}
335346

347+
llvm::orc::LLJIT &getJIT() { return *J; }
348+
336349
llvm::orc::JITDylib &getMainJITDylib() { return J->getMainJITDylib(); }
337350

338351
/// Register a the materialization unit `MU` with the `JITDylib``JD` and
@@ -370,19 +383,6 @@ class SwiftJIT {
370383
}
371384

372385
private:
373-
/// Creates a `LLJITTargetBuilder` and configures its `ObjectLinkingLayer`
374-
static llvm::orc::LLJITBuilder getLLJITBuilder() {
375-
using ObjLayer = llvm::Expected<std::unique_ptr<llvm::orc::ObjectLayer>>;
376-
return std::move(llvm::orc::LLJITBuilder().setObjectLinkingLayerCreator(
377-
[&](auto &ES, const auto &TargetTriple) -> ObjLayer {
378-
auto MemMgr = llvm::jitlink::InProcessMemoryManager::Create();
379-
if (!MemMgr)
380-
return MemMgr.takeError();
381-
return std::make_unique<llvm::orc::ObjectLinkingLayer>(
382-
ES, std::move(*MemMgr));
383-
}));
384-
}
385-
386386
/// An ORC layer to rename the names of function bodies to support lazy
387387
/// reexports
388388
class SwiftJITPlugin : public llvm::orc::ObjectLinkingLayer::Plugin {
@@ -470,6 +470,63 @@ class SwiftJIT {
470470
std::unique_ptr<llvm::orc::IndirectStubsManager> ISM;
471471
};
472472

473+
/// Dump the contents of `Module` if requested
474+
static void dumpJIT(llvm::orc::LLJIT &JIT, const llvm::Module &Module,
475+
const IRGenOptions &IRGenOpts) {
476+
LLVM_DEBUG(llvm::dbgs() << "Module to be executed:\n"; Module.dump());
477+
switch (IRGenOpts.DumpJIT) {
478+
case JITDebugArtifact::None:
479+
break;
480+
case JITDebugArtifact::LLVMIR:
481+
DumpLLVMIR(Module);
482+
break;
483+
case JITDebugArtifact::Object:
484+
JIT.getObjTransformLayer().setTransform(llvm::orc::DumpObjects());
485+
break;
486+
}
487+
}
488+
489+
/// IRGen the provided `SILModule` with the specified options.
490+
/// Returns `std::nullopt` if a compiler error is encountered
491+
static std::optional<GeneratedModule>
492+
generateModule(const CompilerInstance &CI, const IRGenOptions &IRGenOpts,
493+
std::unique_ptr<SILModule> SM) {
494+
// TODO: Use OptimizedIRRequest for this.
495+
const auto &Context = CI.getASTContext();
496+
auto *swiftModule = CI.getMainModule();
497+
const auto PSPs = CI.getPrimarySpecificPathsForAtMostOnePrimary();
498+
const auto &TBDOpts = CI.getInvocation().getTBDGenOptions();
499+
500+
// Lower the SIL module to LLVM IR
501+
auto GenModule = performIRGeneration(
502+
swiftModule, IRGenOpts, TBDOpts, std::move(SM),
503+
swiftModule->getName().str(), PSPs, ArrayRef<std::string>());
504+
505+
if (Context.hadError()) {
506+
return std::nullopt;
507+
}
508+
509+
assert(GenModule && "Emitted no diagnostics but IR generation failed?");
510+
auto *Module = GenModule.getModule();
511+
512+
// Run LLVM passes on the resulting module
513+
performLLVM(IRGenOpts, Context.Diags, /*diagMutex*/ nullptr,
514+
/*hash*/ nullptr, Module, GenModule.getTargetMachine(),
515+
CI.getPrimarySpecificPathsForAtMostOnePrimary().OutputFilename,
516+
CI.getOutputBackend(), Context.Stats);
517+
518+
if (Context.hadError()) {
519+
return std::nullopt;
520+
}
521+
522+
return GenModule;
523+
}
524+
525+
/// Log a compilation error to standard error
526+
static void logError(llvm::Error Err) {
527+
logAllUnhandledErrors(std::move(Err), llvm::errs(), "");
528+
}
529+
473530
/// Lazily materializes an entire SIL module
474531
class SILMaterializationUnit : public llvm::orc::MaterializationUnit {
475532
public:
@@ -482,33 +539,16 @@ class SILMaterializationUnit : public llvm::orc::MaterializationUnit {
482539
void materialize(
483540
std::unique_ptr<llvm::orc::MaterializationResponsibility> R) override {
484541

485-
// TODO: Use OptimizedIRRequest for this.
486-
const auto &Context = CI.getASTContext();
487-
auto *swiftModule = CI.getMainModule();
488-
const auto PSPs = CI.getPrimarySpecificPathsForAtMostOnePrimary();
489-
const auto &TBDOpts = CI.getInvocation().getTBDGenOptions();
490-
491-
// Lower the SIL module to LLVM IR
492-
auto GenModule = performIRGeneration(
493-
swiftModule, IRGenOpts, TBDOpts, std::move(SM),
494-
swiftModule->getName().str(), PSPs, ArrayRef<std::string>());
542+
auto GenModule = generateModule(CI, IRGenOpts, std::move(SM));
495543

496-
if (Context.hadError()) {
544+
if (!GenModule) {
497545
R->failMaterialization();
498546
return;
499547
}
500548

501-
assert(GenModule && "Emitted no diagnostics but IR generation failed?");
502-
auto *Module = GenModule.getModule();
503-
504-
// Run LLVM passes on the resulting module
505-
performLLVM(IRGenOpts, Context.Diags, /*diagMutex*/ nullptr,
506-
/*hash*/ nullptr, Module, GenModule.getTargetMachine(),
507-
CI.getPrimarySpecificPathsForAtMostOnePrimary().OutputFilename,
508-
CI.getOutputBackend(), Context.Stats);
549+
auto *Module = GenModule->getModule();
509550

510551
// Dump IR if requested
511-
LLVM_DEBUG(llvm::dbgs() << "Module to be executed:\n"; Module->dump());
512552
dumpJIT(*Module);
513553

514554
// Now we must register all other public symbols defined by
@@ -525,9 +565,9 @@ class SILMaterializationUnit : public llvm::orc::MaterializationUnit {
525565
}
526566
// Register the symbols we have discovered with the JIT
527567
if (auto Err = R->defineMaterializing(Symbols)) {
528-
logAllUnhandledErrors(std::move(Err), llvm::errs(), "");
568+
logError(std::move(Err));
529569
}
530-
auto TSM = std::move(GenModule).intoThreadSafeContext();
570+
auto TSM = std::move(*GenModule).intoThreadSafeContext();
531571
JIT.getIRCompileLayer().emit(std::move(R), std::move(TSM));
532572
}
533573

@@ -536,16 +576,7 @@ class SILMaterializationUnit : public llvm::orc::MaterializationUnit {
536576
private:
537577
/// Dump the contents of `Module` if requested
538578
void dumpJIT(const llvm::Module &Module) {
539-
switch (IRGenOpts.DumpJIT) {
540-
case JITDebugArtifact::None:
541-
break;
542-
case JITDebugArtifact::LLVMIR:
543-
DumpLLVMIR(Module);
544-
break;
545-
case JITDebugArtifact::Object:
546-
JIT.getObjTransformLayer().setTransform(llvm::orc::DumpObjects());
547-
break;
548-
}
579+
::dumpJIT(JIT.getJIT(), Module, IRGenOpts);
549580
}
550581

551582
/// All global value `Global` to `Symbols` if it is a public definition
@@ -608,17 +639,49 @@ llvm::Error SwiftJIT::addSwift(llvm::orc::JITDylib &JD,
608639
return JD.define(std::move(MU));
609640
}
610641

642+
/// Lookup the entry point in `J` and run it with the given command line
643+
/// arguments `CmdLine`. Returns `-1` if failed to compile, or the status
644+
/// returned by the entry point following execution.
645+
static int runMain(llvm::orc::LLJIT &J, const ProcessCmdLine &CmdLine) {
646+
LLVM_DEBUG(llvm::dbgs() << "Running static constructors\n");
647+
if (auto Err = J.initialize(J.getMainJITDylib())) {
648+
logError(std::move(Err));
649+
return -1;
650+
}
651+
652+
auto MainSym = J.lookup("main");
653+
if (!MainSym) {
654+
logError(MainSym.takeError());
655+
return -1;
656+
}
657+
658+
using MainFnTy = int (*)(int, char *[]);
659+
MainFnTy JITMain = MainSym->toPtr<MainFnTy>();
660+
661+
LLVM_DEBUG(llvm::dbgs() << "Running main\n");
662+
int Result = llvm::orc::runAsMain(JITMain, CmdLine);
663+
664+
LLVM_DEBUG(llvm::dbgs() << "Running static destructors\n");
665+
if (auto Err = J.deinitialize(J.getMainJITDylib())) {
666+
logError(std::move(Err));
667+
return -1;
668+
}
669+
670+
return Result;
671+
}
672+
611673
int swift::RunImmediately(CompilerInstance &CI, const ProcessCmdLine &CmdLine,
612674
const IRGenOptions &IRGenOpts,
613675
const SILOptions &SILOpts,
614676
std::unique_ptr<SILModule> &&SM) {
615-
ASTContext &Context = CI.getASTContext();
677+
678+
auto &Context = CI.getASTContext();
679+
616680
// Load libSwiftCore to setup process arguments.
617681
//
618682
// This must be done here, before any library loading has been done, to avoid
619683
// racing with the static initializers in user code.
620684
// Setup interpreted process arguments.
621-
622685
using ArgOverride = void (* SWIFT_CC(swift))(const char **, int);
623686
#if defined(_WIN32)
624687
auto stdlib = loadSwiftRuntime(Context.SearchPathOpts.RuntimeLibraryPaths);
@@ -656,8 +719,6 @@ int swift::RunImmediately(CompilerInstance &CI, const ProcessCmdLine &CmdLine,
656719
}
657720
#endif
658721

659-
auto *swiftModule = CI.getMainModule();
660-
661722
SmallVector<const char *, 32> argBuf;
662723
for (size_t i = 0; i < CmdLine.size(); ++i) {
663724
argBuf.push_back(CmdLine[i].c_str());
@@ -666,45 +727,41 @@ int swift::RunImmediately(CompilerInstance &CI, const ProcessCmdLine &CmdLine,
666727

667728
(*emplaceProcessArgs)(argBuf.data(), CmdLine.size());
668729

730+
auto *swiftModule = CI.getMainModule();
669731
if (autolinkImportedModules(swiftModule, IRGenOpts))
670732
return -1;
671733

672-
auto JIT = SwiftJIT::Create(IRGenOpts, swiftModule->getASTContext());
673-
if (auto Err = JIT.takeError()) {
674-
llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "");
675-
return -1;
676-
}
734+
auto &Target = swiftModule->getASTContext().LangOpts.Target;
735+
if (Target.isMacOSX()) {
736+
auto JIT = SwiftJIT::Create(IRGenOpts, swiftModule->getASTContext());
737+
if (auto Err = JIT.takeError()) {
738+
logError(std::move(Err));
739+
return -1;
740+
}
677741

678-
auto MU = std::make_unique<SILMaterializationUnit>(**JIT, CI, IRGenOpts,
679-
std::move(SM));
680-
if (auto Err = (*JIT)->addSwift((*JIT)->getMainJITDylib(), std::move(MU))) {
681-
llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "");
682-
return -1;
683-
}
742+
auto MU = std::make_unique<SILMaterializationUnit>(**JIT, CI, IRGenOpts,
743+
std::move(SM));
744+
if (auto Err = (*JIT)->addSwift((*JIT)->getMainJITDylib(), std::move(MU))) {
745+
logError(std::move(Err));
746+
return -1;
747+
}
684748

685-
LLVM_DEBUG(llvm::dbgs() << "Running static constructors\n");
686-
if (auto Err = (*JIT)->initialize((*JIT)->getMainJITDylib())) {
687-
llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "");
688-
return -1;
749+
return runMain((*JIT)->getJIT(), CmdLine);
689750
}
690-
691-
auto MainSym = (*JIT)->lookup("main");
692-
if (!MainSym) {
693-
llvm::logAllUnhandledErrors(MainSym.takeError(), llvm::errs(), "");
751+
auto JIT = createLLJIT(IRGenOpts, swiftModule->getASTContext());
752+
if (auto Err = JIT.takeError()) {
753+
logError(std::move(Err));
694754
return -1;
695755
}
696-
697-
using MainFnTy = int (*)(int, char *[]);
698-
auto JITMain = MainSym->toPtr<MainFnTy>();
699-
700-
LLVM_DEBUG(llvm::dbgs() << "Running main\n");
701-
int Result = llvm::orc::runAsMain(JITMain, CmdLine);
702-
703-
LLVM_DEBUG(llvm::dbgs() << "Running static destructors\n");
704-
if (auto Err = (*JIT)->deinitialize((*JIT)->getMainJITDylib())) {
705-
logAllUnhandledErrors(std::move(Err), llvm::errs(), "");
756+
auto GenModule = generateModule(CI, IRGenOpts, std::move(SM));
757+
if (!GenModule)
758+
return -1;
759+
auto *Module = GenModule->getModule();
760+
dumpJIT(**JIT, *Module, IRGenOpts);
761+
auto TSM = std::move(*GenModule).intoThreadSafeContext();
762+
if (auto Err = (*JIT)->addIRModule(std::move(TSM))) {
763+
logError(std::move(Err));
706764
return -1;
707765
}
708-
709-
return Result;
766+
return runMain(**JIT, CmdLine);
710767
}

0 commit comments

Comments
 (0)