[interp] Fix DEBUG_INTERP build (#16057)
[mono-project.git] / mono / mini / llvm-jit.cpp
blobc35abbfa26251b484563094f3850aa49f5d400eb
1 //
2 // jit-llvm.cpp: Support code for using LLVM as a JIT backend
3 //
4 // (C) 2009-2011 Novell, Inc.
5 // Copyright 2011-2015 Xamarin, Inc (http://www.xamarin.com)
6 //
7 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
8 //
9 // Mono's internal header files are not C++ clean, so avoid including them if
10 // possible
13 #include "config.h"
15 #include <llvm-c/Core.h>
16 #include <llvm-c/ExecutionEngine.h>
18 #include "mini-llvm-cpp.h"
19 #include "llvm-jit.h"
21 #if defined(MONO_ARCH_LLVM_JIT_SUPPORTED) && !defined(MONO_CROSS_COMPILE) && LLVM_API_VERSION > 600
23 #include <llvm/Support/raw_ostream.h>
24 #include <llvm/Support/Host.h>
25 #include <llvm/Support/TargetSelect.h>
26 #include <llvm/IR/Mangler.h>
27 #include <llvm/ExecutionEngine/ExecutionEngine.h>
28 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
29 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
30 #include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
31 #include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
32 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
33 #include "llvm/ExecutionEngine/JITSymbol.h"
35 #include <cstdlib>
37 #include <mono/utils/mono-dl.h>
39 using namespace llvm;
40 using namespace llvm::orc;
42 extern cl::opt<bool> EnableMonoEH;
43 extern cl::opt<std::string> MonoEHFrameSymbol;
45 void
46 mono_llvm_set_unhandled_exception_handler (void)
50 template <typename T>
51 static std::vector<T> singletonSet(T t) {
52 std::vector<T> Vec;
53 Vec.push_back(std::move(t));
54 return Vec;
57 #ifdef __MINGW32__
59 #include <stddef.h>
60 extern void *memset(void *, int, size_t);
61 void bzero (void *to, size_t count) { memset (to, 0, count); }
63 #endif
65 static AllocCodeMemoryCb *alloc_code_mem_cb;
67 class MonoJitMemoryManager : public RTDyldMemoryManager
69 public:
70 ~MonoJitMemoryManager() override;
72 uint8_t *allocateDataSection(uintptr_t Size,
73 unsigned Alignment,
74 unsigned SectionID,
75 StringRef SectionName,
76 bool IsReadOnly) override;
78 uint8_t *allocateCodeSection(uintptr_t Size,
79 unsigned Alignment,
80 unsigned SectionID,
81 StringRef SectionName) override;
83 bool finalizeMemory(std::string *ErrMsg = nullptr) override;
86 MonoJitMemoryManager::~MonoJitMemoryManager()
90 uint8_t *
91 MonoJitMemoryManager::allocateDataSection(uintptr_t Size,
92 unsigned Alignment,
93 unsigned SectionID,
94 StringRef SectionName,
95 bool IsReadOnly) {
96 uint8_t *res = (uint8_t*)malloc (Size);
97 assert (res);
98 memset (res, 0, Size);
99 return res;
102 uint8_t *
103 MonoJitMemoryManager::allocateCodeSection(uintptr_t Size,
104 unsigned Alignment,
105 unsigned SectionID,
106 StringRef SectionName)
108 return alloc_code_mem_cb (NULL, Size);
111 bool
112 MonoJitMemoryManager::finalizeMemory(std::string *ErrMsg)
114 return false;
117 #if LLVM_API_VERSION >= 900
119 struct MonoLLVMJIT {
120 std::shared_ptr<MonoJitMemoryManager> mmgr;
121 ExecutionSession execution_session;
122 std::map<VModuleKey, std::shared_ptr<SymbolResolver>> resolvers;
123 TargetMachine *target_machine;
124 LegacyRTDyldObjectLinkingLayer object_layer;
125 LegacyIRCompileLayer<decltype(object_layer), SimpleCompiler> compile_layer;
126 DataLayout data_layout;
128 MonoLLVMJIT (TargetMachine *tm)
129 : mmgr (std::make_shared<MonoJitMemoryManager>())
130 , target_machine (tm)
131 , object_layer (
132 AcknowledgeORCv1Deprecation, execution_session,
133 [this] (VModuleKey k) {
134 return LegacyRTDyldObjectLinkingLayer::Resources{
135 mmgr, resolvers[k] };
137 , compile_layer (
138 AcknowledgeORCv1Deprecation, object_layer,
139 SimpleCompiler{*target_machine})
140 , data_layout (target_machine->createDataLayout())
142 compile_layer.setNotifyCompiled ([] (VModuleKey, std::unique_ptr<Module> module) {
143 module.release ();
147 VModuleKey
148 add_module (std::unique_ptr<Module> m)
150 auto k = execution_session.allocateVModule();
151 auto lookup_name = [this] (const std::string &namestr) {
152 auto jit_sym = compile_layer.findSymbol(namestr, false);
153 if (jit_sym) {
154 return jit_sym;
156 auto namebuf = namestr.c_str();
157 JITSymbolFlags flags{};
158 if (!strcmp(namebuf, "___bzero")) {
159 return JITSymbol{(uint64_t)(gssize)(void*)bzero, flags};
161 auto current = mono_dl_open (NULL, 0, NULL);
162 g_assert (current);
163 auto name = namebuf[0] == '_' ? namebuf + 1 : namebuf;
164 void *sym = nullptr;
165 auto err = mono_dl_symbol (current, name, &sym);
166 if (!sym) {
167 outs () << "R: " << namestr << "\n";
169 assert (sym);
170 return JITSymbol{(uint64_t)(gssize)sym, flags};
172 auto on_error = [] (Error err) {
173 outs () << "R2: " << err << "\n";
174 assert (0);
176 auto resolver = createLegacyLookupResolver (execution_session,
177 lookup_name, on_error);
178 resolvers[k] = std::move (resolver);
179 compile_layer.addModule (k, std::move(m));
180 return k;
183 std::string
184 mangle (const std::string &name)
186 std::string ret;
187 raw_string_ostream out{ret};
188 Mangler::getNameWithPrefix (out, name, data_layout);
189 return ret;
192 std::string
193 mangle (const GlobalValue *gv)
195 std::string ret;
196 raw_string_ostream out{ret};
197 Mangler{}.getNameWithPrefix (out, gv, false);
198 return ret;
201 gpointer
202 compile (
203 Function *func, int nvars, LLVMValueRef *callee_vars,
204 gpointer *callee_addrs, gpointer *eh_frame)
206 auto module = func->getParent ();
207 module->setDataLayout (data_layout);
208 // The lifetime of this module is managed by the C API, and the
209 // `unique_ptr` created here will be released in the
210 // NotifyCompiled callback.
211 auto k = add_module (std::unique_ptr<Module>(module));
212 auto bodysym = compile_layer.findSymbolIn (k, mangle (func), false);
213 auto bodyaddr = bodysym.getAddress ();
214 assert (bodyaddr);
215 for (int i = 0; i < nvars; ++i) {
216 auto var = unwrap<GlobalVariable> (callee_vars[i]);
217 auto sym = compile_layer.findSymbolIn (k, mangle (var->getName ()), true);
218 auto addr = sym.getAddress ();
219 g_assert ((bool)addr);
220 callee_addrs[i] = (gpointer)addr.get ();
222 auto ehsym = compile_layer.findSymbolIn (k, "mono_eh_frame", false);
223 auto ehaddr = ehsym.getAddress ();
224 g_assert ((bool)ehaddr);
225 *eh_frame = (gpointer)ehaddr.get ();
226 return (gpointer)bodyaddr.get ();
230 static void
231 init_mono_llvm_jit ()
235 static MonoLLVMJIT *
236 make_mono_llvm_jit (TargetMachine *target_machine)
238 return new MonoLLVMJIT{target_machine};
241 #elif LLVM_API_VERSION > 600
243 class MonoLLVMJIT {
244 public:
245 /* We use our own trampoline infrastructure instead of the Orc one */
246 typedef RTDyldObjectLinkingLayer ObjLayerT;
247 typedef IRCompileLayer<ObjLayerT, SimpleCompiler> CompileLayerT;
248 typedef CompileLayerT::ModuleHandleT ModuleHandleT;
250 MonoLLVMJIT (TargetMachine *TM, MonoJitMemoryManager *mm)
251 : TM(TM), ObjectLayer([=] { return std::shared_ptr<RuntimeDyld::MemoryManager> (mm); }),
252 CompileLayer (ObjectLayer, SimpleCompiler (*TM)),
253 modules() {
256 ModuleHandleT addModule(Function *F, std::shared_ptr<Module> M) {
257 auto Resolver = createLambdaResolver(
258 [&](const std::string &Name) {
259 const char *name = Name.c_str ();
260 JITSymbolFlags flags = JITSymbolFlags ();
261 if (!strcmp (name, "___bzero"))
262 return JITSymbol((uint64_t)(gssize)(void*)bzero, flags);
264 MonoDl *current;
265 char *err;
266 void *symbol;
267 current = mono_dl_open (NULL, 0, NULL);
268 g_assert (current);
269 if (name [0] == '_')
270 err = mono_dl_symbol (current, name + 1, &symbol);
271 else
272 err = mono_dl_symbol (current, name, &symbol);
273 mono_dl_close (current);
274 if (!symbol)
275 outs () << "R: " << Name << "\n";
276 assert (symbol);
277 return JITSymbol((uint64_t)(gssize)symbol, flags);
279 [](const std::string &S) {
280 outs () << "R2: " << S << "\n";
281 assert (0);
282 return nullptr;
283 } );
285 auto m = CompileLayer.addModule(M, std::move(Resolver));
286 g_assert (!!m);
287 return m.get ();
290 std::string mangle(const std::string &Name) {
291 std::string MangledName;
293 raw_string_ostream MangledNameStream(MangledName);
294 Mangler::getNameWithPrefix(MangledNameStream, Name,
295 TM->createDataLayout());
297 return MangledName;
300 std::string mangle(const GlobalValue *GV) {
301 std::string MangledName;
303 Mangler Mang;
305 raw_string_ostream MangledNameStream(MangledName);
306 Mang.getNameWithPrefix(MangledNameStream, GV, false);
308 return MangledName;
311 gpointer compile (Function *F, int nvars, LLVMValueRef *callee_vars, gpointer *callee_addrs, gpointer *eh_frame) {
312 F->getParent ()->setDataLayout (TM->createDataLayout ());
313 // Orc uses a shared_ptr to refer to modules so we have to save them ourselves to keep a ref
314 std::shared_ptr<Module> m (F->getParent ());
315 modules.push_back (m);
316 auto ModuleHandle = addModule (F, m);
317 auto BodySym = CompileLayer.findSymbolIn(ModuleHandle, mangle (F), false);
318 auto BodyAddr = BodySym.getAddress();
319 assert (BodyAddr);
321 for (int i = 0; i < nvars; ++i) {
322 GlobalVariable *var = unwrap<GlobalVariable>(callee_vars [i]);
324 auto sym = CompileLayer.findSymbolIn (ModuleHandle, mangle (var->getName ()), true);
325 auto addr = sym.getAddress ();
326 g_assert ((bool)addr);
327 callee_addrs [i] = (gpointer)addr.get ();
330 auto ehsym = CompileLayer.findSymbolIn(ModuleHandle, "mono_eh_frame", false);
331 auto ehaddr = ehsym.getAddress ();
332 g_assert ((bool)ehaddr);
333 *eh_frame = (gpointer)ehaddr.get ();
334 return (gpointer)BodyAddr.get ();
337 private:
338 TargetMachine *TM;
339 ObjLayerT ObjectLayer;
340 CompileLayerT CompileLayer;
341 std::vector<std::shared_ptr<Module>> modules;
344 static MonoJitMemoryManager *mono_mm;
346 static void
347 init_mono_llvm_jit ()
349 mono_mm = new MonoJitMemoryManager ();
352 static MonoLLVMJIT *
353 make_mono_llvm_jit (TargetMachine *target_machine)
355 return new MonoLLVMJIT(target_machine, mono_mm);
358 #endif
360 static MonoLLVMJIT *jit;
362 MonoEERef
363 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, LLVMExecutionEngineRef *ee)
365 alloc_code_mem_cb = alloc_cb;
367 InitializeNativeTarget ();
368 InitializeNativeTargetAsmPrinter();
370 EnableMonoEH = true;
371 MonoEHFrameSymbol = "mono_eh_frame";
373 EngineBuilder EB;
374 #if defined(TARGET_AMD64) || defined(TARGET_X86)
375 std::vector<std::string> attrs;
376 // FIXME: Autodetect this
377 attrs.push_back("sse3");
378 attrs.push_back("sse4.1");
379 EB.setMAttrs (attrs);
380 #endif
381 auto TM = EB.selectTarget ();
382 assert (TM);
384 init_mono_llvm_jit ();
385 jit = make_mono_llvm_jit (TM);
387 return NULL;
391 * mono_llvm_compile_method:
393 * Compile METHOD to native code. Compute the addresses of the variables in CALLEE_VARS and store them into
394 * CALLEE_ADDRS. Return the EH frame address in EH_FRAME.
396 gpointer
397 mono_llvm_compile_method (MonoEERef mono_ee, LLVMValueRef method, int nvars, LLVMValueRef *callee_vars, gpointer *callee_addrs, gpointer *eh_frame)
399 return jit->compile (unwrap<Function> (method), nvars, callee_vars, callee_addrs, eh_frame);
402 void
403 mono_llvm_dispose_ee (MonoEERef *eeref)
407 #else /* MONO_CROSS_COMPILE or LLVM_API_VERSION < 600 */
409 void
410 mono_llvm_set_unhandled_exception_handler (void)
414 MonoEERef
415 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, LLVMExecutionEngineRef *ee)
417 g_error ("LLVM JIT not supported on this platform.");
418 return NULL;
421 gpointer
422 mono_llvm_compile_method (MonoEERef mono_ee, LLVMValueRef method, int nvars, LLVMValueRef *callee_vars, gpointer *callee_addrs, gpointer *eh_frame)
424 g_assert_not_reached ();
425 return NULL;
428 void
429 mono_llvm_dispose_ee (MonoEERef *eeref)
431 g_assert_not_reached ();
434 #endif /* !MONO_CROSS_COMPILE */