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/IndirectionUtils.h"
7#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
8#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
9#include "llvm/ExecutionEngine/Orc/SpeculateAnalyses.h"
10#include "llvm/ExecutionEngine/Orc/Speculation.h"
11#include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
12#include "llvm/ExecutionEngine/SectionMemoryManager.h"
13#include "llvm/IRReader/IRReader.h"
14#include "llvm/Support/CommandLine.h"
15#include "llvm/Support/Debug.h"
16#include "llvm/Support/InitLLVM.h"
17#include "llvm/Support/SourceMgr.h"
18#include "llvm/Support/TargetSelect.h"
19#include "llvm/Support/ThreadPool.h"
20
21#include <list>
22#include <string>
23
24using namespace llvm;
25using namespace llvm::orc;
26
27static cl::list<std::string> InputFiles(cl::Positional, cl::OneOrMore,
28 cl::desc("input files"));
29
30static cl::list<std::string> InputArgv("args", cl::Positional,
31 cl::desc("<program arguments>..."),
32 cl::PositionalEatsArgs);
33
34static cl::opt<unsigned> NumThreads("num-threads", cl::Optional,
35 cl::desc("Number of compile threads"),
36 cl::init(Val: 4));
37
38ExitOnError ExitOnErr;
39
40// Add Layers
41class SpeculativeJIT {
42public:
43 static Expected<std::unique_ptr<SpeculativeJIT>> Create() {
44 auto JTMB = orc::JITTargetMachineBuilder::detectHost();
45 if (!JTMB)
46 return JTMB.takeError();
47
48 auto DL = JTMB->getDefaultDataLayoutForTarget();
49 if (!DL)
50 return DL.takeError();
51
52 auto EPC = SelfExecutorProcessControl::Create(
53 SSP: nullptr,
54 D: std::make_unique<DynamicThreadPoolTaskDispatcher>(args: std::nullopt));
55 if (!EPC)
56 return EPC.takeError();
57
58 auto ES = std::make_unique<ExecutionSession>(args: std::move(*EPC));
59
60 auto LCTMgr = createLocalLazyCallThroughManager(
61 T: JTMB->getTargetTriple(), ES&: *ES,
62 ErrorHandlerAddr: ExecutorAddr::fromPtr(Ptr: explodeOnLazyCompileFailure));
63 if (!LCTMgr)
64 return LCTMgr.takeError();
65
66 auto ISMBuilder =
67 createLocalIndirectStubsManagerBuilder(T: JTMB->getTargetTriple());
68 if (!ISMBuilder)
69 return make_error<StringError>(Args: "No indirect stubs manager for target",
70 Args: inconvertibleErrorCode());
71
72 auto ProcessSymbolsSearchGenerator =
73 DynamicLibrarySearchGenerator::GetForCurrentProcess(
74 GlobalPrefix: DL->getGlobalPrefix());
75 if (!ProcessSymbolsSearchGenerator)
76 return ProcessSymbolsSearchGenerator.takeError();
77
78 std::unique_ptr<SpeculativeJIT> SJ(new SpeculativeJIT(
79 std::move(ES), std::move(*DL), std::move(*JTMB), std::move(*LCTMgr),
80 std::move(ISMBuilder), std::move(*ProcessSymbolsSearchGenerator)));
81 return std::move(SJ);
82 }
83
84 ExecutionSession &getES() { return *ES; }
85
86 Error addModule(ThreadSafeModule TSM) {
87 return CODLayer.add(JD&: MainJD, TSM: std::move(TSM));
88 }
89
90 Expected<ExecutorSymbolDef> lookup(StringRef UnmangledName) {
91 return ES->lookup(SearchOrder: {&MainJD}, Symbol: Mangle(UnmangledName));
92 }
93
94 ~SpeculativeJIT() { CompileThreads.wait(); }
95
96private:
97 using IndirectStubsManagerBuilderFunction =
98 std::function<std::unique_ptr<IndirectStubsManager>()>;
99
100 static void explodeOnLazyCompileFailure() {
101 errs() << "Lazy compilation failed, Symbol Implmentation not found!\n";
102 exit(status: 1);
103 }
104
105 SpeculativeJIT(
106 std::unique_ptr<ExecutionSession> ES, DataLayout DL,
107 orc::JITTargetMachineBuilder JTMB,
108 std::unique_ptr<LazyCallThroughManager> LCTMgr,
109 IndirectStubsManagerBuilderFunction ISMBuilder,
110 std::unique_ptr<DynamicLibrarySearchGenerator> ProcessSymbolsGenerator)
111 : ES(std::move(ES)), DL(std::move(DL)),
112 MainJD(this->ES->createBareJITDylib(Name: "<main>")), LCTMgr(std::move(LCTMgr)),
113 CompileLayer(*this->ES, ObjLayer,
114 std::make_unique<ConcurrentIRCompiler>(args: std::move(JTMB))),
115 S(Imps, *this->ES),
116 SpeculateLayer(*this->ES, CompileLayer, S, Mangle, BlockFreqQuery()),
117 CODLayer(*this->ES, SpeculateLayer, *this->LCTMgr,
118 std::move(ISMBuilder)) {
119 MainJD.addGenerator(DefGenerator: std::move(ProcessSymbolsGenerator));
120 this->CODLayer.setImplMap(&Imps);
121 ExitOnErr(S.addSpeculationRuntime(JD&: MainJD, Mangle));
122 LocalCXXRuntimeOverrides CXXRuntimeoverrides;
123 ExitOnErr(CXXRuntimeoverrides.enable(JD&: MainJD, Mangler&: Mangle));
124 }
125
126 static std::unique_ptr<SectionMemoryManager> createMemMgr() {
127 return std::make_unique<SectionMemoryManager>();
128 }
129
130 std::unique_ptr<ExecutionSession> ES;
131 DataLayout DL;
132 MangleAndInterner Mangle{*ES, DL};
133 DefaultThreadPool CompileThreads{llvm::hardware_concurrency(ThreadCount: NumThreads)};
134
135 JITDylib &MainJD;
136
137 Triple TT;
138 std::unique_ptr<LazyCallThroughManager> LCTMgr;
139 IRCompileLayer CompileLayer;
140 ImplSymbolMap Imps;
141 Speculator S;
142 RTDyldObjectLinkingLayer ObjLayer{*ES, createMemMgr};
143 IRSpeculationLayer SpeculateLayer;
144 CompileOnDemandLayer CODLayer;
145};
146
147int main(int argc, char *argv[]) {
148 // Initialize LLVM.
149 InitLLVM X(argc, argv);
150
151 InitializeNativeTarget();
152 InitializeNativeTargetAsmPrinter();
153
154 cl::ParseCommandLineOptions(argc, argv, Overview: "SpeculativeJIT");
155 ExitOnErr.setBanner(std::string(argv[0]) + ": ");
156
157 if (NumThreads < 1) {
158 errs() << "Speculative compilation requires one or more dedicated compile "
159 "threads\n";
160 return 1;
161 }
162
163 // Create a JIT instance.
164 auto SJ = ExitOnErr(SpeculativeJIT::Create());
165
166 // Load the IR inputs.
167 for (const auto &InputFile : InputFiles) {
168 SMDiagnostic Err;
169 auto Ctx = std::make_unique<LLVMContext>();
170 auto M = parseIRFile(Filename: InputFile, Err, Context&: *Ctx);
171 if (!M) {
172 Err.print(ProgName: argv[0], S&: errs());
173 return 1;
174 }
175
176 ExitOnErr(SJ->addModule(TSM: ThreadSafeModule(std::move(M), std::move(Ctx))));
177 }
178
179 auto MainSym = ExitOnErr(SJ->lookup(UnmangledName: "main"));
180 auto Main = MainSym.getAddress().toPtr<int (*)(int, char *[])>();
181
182 return runAsMain(Main, Args: InputArgv, ProgramName: StringRef(InputFiles.front()));
183
184 return 0;
185}
186

source code of llvm/examples/SpeculativeJIT/SpeculativeJIT.cpp