1 #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
2 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
3 #include "llvm/ExecutionEngine/Orc/Core.h"
4 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
5 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
6 #include "llvm/ExecutionEngine/Orc/IRPartitionLayer.h"
7 #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
8 #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
9 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
10 #include "llvm/ExecutionEngine/Orc/SpeculateAnalyses.h"
11 #include "llvm/ExecutionEngine/Orc/Speculation.h"
12 #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
13 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
14 #include "llvm/IRReader/IRReader.h"
15 #include "llvm/Support/CommandLine.h"
16 #include "llvm/Support/Debug.h"
17 #include "llvm/Support/InitLLVM.h"
18 #include "llvm/Support/SourceMgr.h"
19 #include "llvm/Support/TargetSelect.h"
20 #include "llvm/Support/ThreadPool.h"
26 using namespace llvm::orc
;
28 static cl::list
<std::string
> InputFiles(cl::Positional
, cl::OneOrMore
,
29 cl::desc("input files"));
31 static cl::list
<std::string
> InputArgv("args", cl::Positional
,
32 cl::desc("<program arguments>..."),
33 cl::PositionalEatsArgs
);
35 static cl::opt
<unsigned> NumThreads("num-threads", cl::Optional
,
36 cl::desc("Number of compile threads"),
39 ExitOnError ExitOnErr
;
42 class SpeculativeJIT
{
44 static Expected
<std::unique_ptr
<SpeculativeJIT
>> Create() {
45 auto JTMB
= orc::JITTargetMachineBuilder::detectHost();
47 return JTMB
.takeError();
49 auto DL
= JTMB
->getDefaultDataLayoutForTarget();
51 return DL
.takeError();
53 auto EPC
= SelfExecutorProcessControl::Create(
55 std::make_unique
<DynamicThreadPoolTaskDispatcher
>(std::nullopt
));
57 return EPC
.takeError();
59 auto ES
= std::make_unique
<ExecutionSession
>(std::move(*EPC
));
61 auto LCTMgr
= createLocalLazyCallThroughManager(
62 JTMB
->getTargetTriple(), *ES
,
63 ExecutorAddr::fromPtr(explodeOnLazyCompileFailure
));
65 return LCTMgr
.takeError();
68 createLocalIndirectStubsManagerBuilder(JTMB
->getTargetTriple());
70 return make_error
<StringError
>("No indirect stubs manager for target",
71 inconvertibleErrorCode());
73 auto ProcessSymbolsSearchGenerator
=
74 DynamicLibrarySearchGenerator::GetForCurrentProcess(
75 DL
->getGlobalPrefix());
76 if (!ProcessSymbolsSearchGenerator
)
77 return ProcessSymbolsSearchGenerator
.takeError();
79 std::unique_ptr
<SpeculativeJIT
> SJ(new SpeculativeJIT(
80 std::move(ES
), std::move(*DL
), std::move(*JTMB
), std::move(*LCTMgr
),
81 std::move(ISMBuilder
), std::move(*ProcessSymbolsSearchGenerator
)));
85 ExecutionSession
&getES() { return *ES
; }
87 Error
addModule(ThreadSafeModule TSM
) {
88 return CODLayer
.add(MainJD
, std::move(TSM
));
91 Expected
<ExecutorSymbolDef
> lookup(StringRef UnmangledName
) {
92 return ES
->lookup({&MainJD
}, Mangle(UnmangledName
));
95 ~SpeculativeJIT() { CompileThreads
.wait(); }
98 using IndirectStubsManagerBuilderFunction
=
99 std::function
<std::unique_ptr
<IndirectStubsManager
>()>;
101 static void explodeOnLazyCompileFailure() {
102 errs() << "Lazy compilation failed, Symbol Implmentation not found!\n";
107 std::unique_ptr
<ExecutionSession
> ES
, DataLayout DL
,
108 orc::JITTargetMachineBuilder JTMB
,
109 std::unique_ptr
<LazyCallThroughManager
> LCTMgr
,
110 IndirectStubsManagerBuilderFunction ISMBuilder
,
111 std::unique_ptr
<DynamicLibrarySearchGenerator
> ProcessSymbolsGenerator
)
112 : ES(std::move(ES
)), DL(std::move(DL
)),
113 MainJD(this->ES
->createBareJITDylib("<main>")),
114 LCTMgr(std::move(LCTMgr
)),
115 CompileLayer(*this->ES
, ObjLayer
,
116 std::make_unique
<ConcurrentIRCompiler
>(std::move(JTMB
))),
118 SpeculateLayer(*this->ES
, CompileLayer
, S
, Mangle
, BlockFreqQuery()),
119 IPLayer(*this->ES
, SpeculateLayer
),
120 CODLayer(*this->ES
, IPLayer
, *this->LCTMgr
, std::move(ISMBuilder
)) {
121 MainJD
.addGenerator(std::move(ProcessSymbolsGenerator
));
122 this->CODLayer
.setImplMap(&Imps
);
123 ExitOnErr(S
.addSpeculationRuntime(MainJD
, Mangle
));
124 LocalCXXRuntimeOverrides CXXRuntimeoverrides
;
125 ExitOnErr(CXXRuntimeoverrides
.enable(MainJD
, Mangle
));
128 static std::unique_ptr
<SectionMemoryManager
> createMemMgr() {
129 return std::make_unique
<SectionMemoryManager
>();
132 std::unique_ptr
<ExecutionSession
> ES
;
134 MangleAndInterner Mangle
{*ES
, DL
};
135 DefaultThreadPool CompileThreads
{llvm::hardware_concurrency(NumThreads
)};
140 std::unique_ptr
<LazyCallThroughManager
> LCTMgr
;
141 IRCompileLayer CompileLayer
;
144 RTDyldObjectLinkingLayer ObjLayer
{*ES
, createMemMgr
};
145 IRSpeculationLayer SpeculateLayer
;
146 IRPartitionLayer IPLayer
;
147 CompileOnDemandLayer CODLayer
;
150 int main(int argc
, char *argv
[]) {
152 InitLLVM
X(argc
, argv
);
154 InitializeNativeTarget();
155 InitializeNativeTargetAsmPrinter();
157 cl::ParseCommandLineOptions(argc
, argv
, "SpeculativeJIT");
158 ExitOnErr
.setBanner(std::string(argv
[0]) + ": ");
160 if (NumThreads
< 1) {
161 errs() << "Speculative compilation requires one or more dedicated compile "
166 // Create a JIT instance.
167 auto SJ
= ExitOnErr(SpeculativeJIT::Create());
169 // Load the IR inputs.
170 for (const auto &InputFile
: InputFiles
) {
172 auto Ctx
= std::make_unique
<LLVMContext
>();
173 auto M
= parseIRFile(InputFile
, Err
, *Ctx
);
175 Err
.print(argv
[0], errs());
179 ExitOnErr(SJ
->addModule(ThreadSafeModule(std::move(M
), std::move(Ctx
))));
182 auto MainSym
= ExitOnErr(SJ
->lookup("main"));
183 auto Main
= MainSym
.getAddress().toPtr
<int (*)(int, char *[])>();
185 return runAsMain(Main
, InputArgv
, StringRef(InputFiles
.front()));