ETISS 0.11.2
ExtendableTranslatingInstructionSetSimulator(version0.11.2)
Loading...
Searching...
No Matches
LLVMJIT.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSD-3-Clause
2//
3// This file is part of ETISS. It is licensed under the BSD 3-Clause License; you may not use this file except in
4// compliance with the License. You should have received a copy of the license along with this project. If not, see the
5// LICENSE file.
6
7#include <vector>
8#include <iostream>
9
10#include "LLVMJIT.h"
11#include "etiss/ETISS.h"
13
14using namespace etiss;
15
16using namespace llvm;
17using namespace clang;
18using namespace llvm::orc;
19
22
23class OrcJit
24{
25 public:
26 OrcJit(llvm::orc::JITTargetMachineBuilder JTMB, llvm::DataLayout DL)
27 : ObjectLayer(*ES, []() { return std::make_unique<llvm::SectionMemoryManager>(); })
28 , CompileLayer(*ES, ObjectLayer, std::make_unique<llvm::orc::ConcurrentIRCompiler>(std::move(JTMB)))
30 , DL(std::move(DL))
31 , Mangle(*ES, this->DL)
32 , Ctx(std::make_unique<llvm::LLVMContext>())
33 , MainJITDylib(ES->createBareJITDylib("<main>"))
34 {
35 MainJITDylib.addGenerator(
36 llvm::cantFail(llvm::orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(DL.getGlobalPrefix())));
37 }
38
39 static llvm::Expected<std::unique_ptr<OrcJit>> Create()
40 {
41 auto JTMB = llvm::orc::JITTargetMachineBuilder::detectHost();
42 if (!JTMB)
43 return JTMB.takeError();
44
45 auto DL = JTMB->getDefaultDataLayoutForTarget();
46 if (!DL)
47 return DL.takeError();
48
49 return std::make_unique<OrcJit>(std::move(*JTMB), std::move(*DL));
50 }
51
52 const llvm::DataLayout &getDataLayout() const { return DL; }
53 llvm::LLVMContext &getContext() { return *Ctx.getContext(); }
54
55 void addModule(std::unique_ptr<llvm::Module> M)
56 {
57 llvm::cantFail(OptimizeLayer.add(MainJITDylib, llvm::orc::ThreadSafeModule(std::move(M), Ctx)));
58 }
59
60 llvm::Expected<compat::lookup_symbol_T> lookup(llvm::StringRef Name)
61 {
62 return ES->lookup({ &MainJITDylib }, Mangle(Name.str()));
63 }
64
65 bool loadLib(const std::string &libName, const std::set<std::string> &libPaths)
66 {
67 for (const auto &libPath : libPaths)
68 {
69 SmallString<128> fullPath;
70 sys::path::append(fullPath, libPath, "lib" + libName + ".so");
71 if (sys::fs::exists(fullPath))
72 {
73 MainJITDylib.addGenerator(llvm::cantFail(
74 llvm::orc::DynamicLibrarySearchGenerator::Load(fullPath.c_str(), DL.getGlobalPrefix())));
75 return true;
76 }
77 }
78
79 return false;
80 }
81
82 static llvm::orc::ThreadSafeModule optimizeModule(llvm::orc::ThreadSafeModule TSM,
83 const llvm::orc::MaterializationResponsibility &R)
84 {
85 auto lock = TSM.getContext();
86 auto M = TSM.getModuleUnlocked();
87
88 // Create a function pass manager.
89 auto FPM = std::make_unique<llvm::legacy::FunctionPassManager>(M);
90
91 // Add some optimizations.
92 FPM->add(llvm::createInstructionCombiningPass());
93 FPM->add(llvm::createReassociatePass());
94 FPM->add(llvm::createGVNPass());
95 FPM->add(llvm::createCFGSimplificationPass());
96 FPM->doInitialization();
97
98 // Run the optimizations over all functions in the module being added to
99 // the JIT.
100 for (auto &F : *M)
101 FPM->run(F);
102
103 return TSM;
104 }
105
106 std::unique_ptr<llvm::orc::ExecutionSession> ES{ compat::createExecutionSession() };
107 llvm::orc::RTDyldObjectLinkingLayer ObjectLayer;
108 llvm::orc::IRCompileLayer CompileLayer;
109 llvm::orc::IRTransformLayer OptimizeLayer;
110
111 llvm::DataLayout DL;
112 llvm::orc::MangleAndInterner Mangle;
113 llvm::orc::ThreadSafeContext Ctx;
114 llvm::orc::JITDylib &MainJITDylib;
115};
116
117LLVMJIT::LLVMJIT() : JIT("LLVMJIT")
118{
119
120 // init environment once
123 {
124 // LLVMInitializeNativeTarget();
125 InitializeNativeTarget();
126 InitializeNativeTargetAsmPrinter();
127 InitializeNativeTargetAsmParser();
129 }
131 orcJit_ = cantFail(OrcJit::Create());
132}
133
135
136void *LLVMJIT::translate(std::string code, std::set<std::string> headerpaths, std::set<std::string> librarypaths,
137 std::set<std::string> libraries, std::string &error, bool debug)
138{
139 clang::CompilerInstance CI;
141 auto pto = std::make_shared<clang::TargetOptions>();
142 pto->Triple = llvm::sys::getDefaultTargetTriple();
143 TargetInfo *pti = TargetInfo::CreateTargetInfo(CI.getDiagnostics(), pto);
144 CI.setTarget(pti);
145 CI.createFileManager();
146 CI.createSourceManager(CI.getFileManager());
147 CI.createPreprocessor(compat::tu_module_T);
148
149 // compilation task
150 std::vector<std::string> args;
151 if (debug)
152 {
153 args.push_back("-O0");
154 }
155 else
156 {
157 args.push_back("-O3");
158 }
159 args.push_back("-std=c99");
160 args.push_back("-isystem" + etiss::jitFiles() + "/clang_stdlib");
161 args.push_back("-isystem/usr/include");
162 for (const auto &headerPath : headerpaths)
163 {
164 args.push_back("-isystem" + headerPath);
165 }
166 args.push_back("/etiss_llvm_clang_memory_mapped_file.c");
167 args.push_back("-isystem/usr/include/x86_64-linux-gnu");
168
169 for (const auto &lib : libraries)
170 {
171 if (loadedLibs_.count(lib) == 0)
172 {
173 if (!orcJit_->loadLib(lib, librarypaths))
174 {
175 error = "could not load library";
176 return 0;
177 }
178 loadedLibs_.insert(lib);
179 }
180 }
181
182 // configure compiler call
183 std::vector<const char *> argsCStr;
184 for (const auto &arg : args)
185 {
186 argsCStr.push_back(arg.c_str());
187 }
188 if (!CompilerInvocation::CreateFromArgs(CI.getInvocation(), argsCStr, CI.getDiagnostics()))
189 {
190 error = "error on parsing args";
191 return 0;
192 }
193
194 // input file is mapped to memory area containing the code
195 auto buffer = compat::get_virtual_source(code, CI);
196 // compiler should only output llvm module
197
198 EmitLLVMOnlyAction action(&orcJit_->getContext());
199
200 // compile
201 if (!CI.ExecuteAction(action))
202 {
203 error = "failed to execute translation action ";
204 return 0;
205 }
206
207 // load module with orcjit
208 orcJit_->addModule(action.takeModule());
209
210 return (void *)1;
211}
212
213void LLVMJIT::free(void *handle) {}
214
215void *LLVMJIT::getFunction(void *handle, std::string name, std::string &error)
216{
217 return compat::get_function_ptr(cantFail(orcJit_->lookup(name)));
218}
Header file of the ETISS library.
bool etiss_jit_llvm_init_done_
Definition LLVMJIT.cpp:21
std::mutex etiss_jit_llvm_init_mu_
Definition LLVMJIT.cpp:20
llvm::orc::RTDyldObjectLinkingLayer ObjectLayer
Definition LLVMJIT.cpp:107
llvm::orc::IRCompileLayer CompileLayer
Definition LLVMJIT.cpp:108
OrcJit(llvm::orc::JITTargetMachineBuilder JTMB, llvm::DataLayout DL)
Definition LLVMJIT.cpp:26
llvm::orc::ThreadSafeContext Ctx
Definition LLVMJIT.cpp:113
llvm::orc::IRTransformLayer OptimizeLayer
Definition LLVMJIT.cpp:109
llvm::Expected< compat::lookup_symbol_T > lookup(llvm::StringRef Name)
Definition LLVMJIT.cpp:60
std::unique_ptr< llvm::orc::ExecutionSession > ES
Definition LLVMJIT.cpp:106
void addModule(std::unique_ptr< llvm::Module > M)
Definition LLVMJIT.cpp:55
llvm::DataLayout DL
Definition LLVMJIT.cpp:111
bool loadLib(const std::string &libName, const std::set< std::string > &libPaths)
Definition LLVMJIT.cpp:65
llvm::LLVMContext & getContext()
Definition LLVMJIT.cpp:53
llvm::orc::JITDylib & MainJITDylib
Definition LLVMJIT.cpp:114
const llvm::DataLayout & getDataLayout() const
Definition LLVMJIT.cpp:52
llvm::orc::MangleAndInterner Mangle
Definition LLVMJIT.cpp:112
static llvm::orc::ThreadSafeModule optimizeModule(llvm::orc::ThreadSafeModule TSM, const llvm::orc::MaterializationResponsibility &R)
Definition LLVMJIT.cpp:82
static llvm::Expected< std::unique_ptr< OrcJit > > Create()
Definition LLVMJIT.cpp:39
compiler interface for just in time compilation of generated C code
Definition JIT.h:29
virtual ~LLVMJIT()
Definition LLVMJIT.cpp:134
virtual void * getFunction(void *handle, std::string name, std::string &error)
returns a function pointer to a compiled function from the handle returned by etiss::JIT::translate
Definition LLVMJIT.cpp:215
std::unordered_set< std::string > loadedLibs_
Definition LLVMJIT.h:31
virtual void free(void *handle)
clean up handled returned by etiss::JIT::translate
Definition LLVMJIT.cpp:213
virtual void * translate(std::string code, std::set< std::string > headerpaths, std::set< std::string > librarypaths, std::set< std::string > libraries, std::string &error, bool debug=false)
translate C code to executable code and return a handle/pointer that identifies the compilation resul...
Definition LLVMJIT.cpp:136
std::unique_ptr< OrcJit > orcJit_
Definition LLVMJIT.h:30
std::unique_ptr< llvm::MemoryBuffer > get_virtual_source(llvm::StringRef code, clang::CompilerInstance &CI)
void * get_function_ptr(const compat::lookup_symbol_T &func)
void createDiagnostics(clang::CompilerInstance &CI)
std::unique_ptr< llvm::orc::ExecutionSession > createExecutionSession()
forwards: include/jit/*
Definition Benchmark.h:17
std::string jitFiles()
Get ETISS JIT files path.
Definition Misc.cpp:563