[jit] Constant folding for some Math operations on doubles (#9281)
[mono-project.git] / mono / mini / llvm-jit.cpp
bloba8aaa54a8ad426762f7d71640b08a8b5dfd264a1
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 > 100
24 * LLVM 3.9 uses the OrcJIT APIs
27 #include <llvm/Support/raw_ostream.h>
28 #include <llvm/Support/Host.h>
29 #include <llvm/Support/TargetSelect.h>
30 #include <llvm/IR/Mangler.h>
31 #include <llvm/ExecutionEngine/ExecutionEngine.h>
32 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
33 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
34 #include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
35 #if LLVM_API_VERSION >= 500
36 #include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
37 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
38 #include "llvm/ExecutionEngine/JITSymbol.h"
39 #else
40 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
41 #endif
43 #include <cstdlib>
45 extern "C" {
46 #include <mono/utils/mono-dl.h>
49 using namespace llvm;
50 using namespace llvm::orc;
52 extern cl::opt<bool> EnableMonoEH;
53 extern cl::opt<std::string> MonoEHFrameSymbol;
55 void
56 mono_llvm_set_unhandled_exception_handler (void)
60 template <typename T>
61 static std::vector<T> singletonSet(T t) {
62 std::vector<T> Vec;
63 Vec.push_back(std::move(t));
64 return Vec;
67 #ifdef __MINGW32__
69 #include <stddef.h>
70 extern void *memset(void *, int, size_t);
71 void bzero (void *to, size_t count) { memset (to, 0, count); }
73 #endif
75 static AllocCodeMemoryCb *alloc_code_mem_cb;
77 class MonoJitMemoryManager : public RTDyldMemoryManager
79 public:
80 ~MonoJitMemoryManager() override;
82 uint8_t *allocateDataSection(uintptr_t Size,
83 unsigned Alignment,
84 unsigned SectionID,
85 StringRef SectionName,
86 bool IsReadOnly) override;
88 uint8_t *allocateCodeSection(uintptr_t Size,
89 unsigned Alignment,
90 unsigned SectionID,
91 StringRef SectionName) override;
93 bool finalizeMemory(std::string *ErrMsg = nullptr) override;
96 MonoJitMemoryManager::~MonoJitMemoryManager()
100 uint8_t *
101 MonoJitMemoryManager::allocateDataSection(uintptr_t Size,
102 unsigned Alignment,
103 unsigned SectionID,
104 StringRef SectionName,
105 bool IsReadOnly) {
106 uint8_t *res = (uint8_t*)malloc (Size);
107 assert (res);
108 memset (res, 0, Size);
109 return res;
112 uint8_t *
113 MonoJitMemoryManager::allocateCodeSection(uintptr_t Size,
114 unsigned Alignment,
115 unsigned SectionID,
116 StringRef SectionName)
118 return alloc_code_mem_cb (NULL, Size);
121 bool
122 MonoJitMemoryManager::finalizeMemory(std::string *ErrMsg)
124 return false;
127 class MonoLLVMJIT {
128 public:
129 /* We use our own trampoline infrastructure instead of the Orc one */
130 #if LLVM_API_VERSION >= 500
131 typedef RTDyldObjectLinkingLayer ObjLayerT;
132 typedef IRCompileLayer<ObjLayerT, SimpleCompiler> CompileLayerT;
133 typedef CompileLayerT::ModuleHandleT ModuleHandleT;
134 #else
135 typedef ObjectLinkingLayer<> ObjLayerT;
136 typedef IRCompileLayer<ObjLayerT> CompileLayerT;
137 typedef CompileLayerT::ModuleSetHandleT ModuleHandleT;
138 #endif
140 MonoLLVMJIT (TargetMachine *TM, MonoJitMemoryManager *mm)
141 #if LLVM_API_VERSION >= 500
142 : TM(TM), ObjectLayer([=] { return std::shared_ptr<RuntimeDyld::MemoryManager> (mm); }),
143 #else
144 : TM(TM),
145 #endif
146 CompileLayer (ObjectLayer, SimpleCompiler (*TM)),
147 modules() {
150 #if LLVM_API_VERSION >= 500
151 ModuleHandleT addModule(Function *F, std::shared_ptr<Module> M) {
152 #else
153 ModuleHandleT addModule(Function *F, Module *M) {
154 #endif
155 auto Resolver = createLambdaResolver(
156 [&](const std::string &Name) {
157 const char *name = Name.c_str ();
158 #if LLVM_API_VERSION >= 500
159 JITSymbolFlags flags = JITSymbolFlags ();
160 #else
161 JITSymbolFlags flags = (JITSymbolFlags)0;
162 #endif
163 if (!strcmp (name, "___bzero")) {
164 #if LLVM_API_VERSION >= 500
165 return JITSymbol((uint64_t)(gssize)(void*)bzero, flags);
166 #else
167 return RuntimeDyld::SymbolInfo((uint64_t)(gssize)(void*)bzero, flags);
168 #endif
171 MonoDl *current;
172 char *err;
173 void *symbol;
174 current = mono_dl_open (NULL, 0, NULL);
175 g_assert (current);
176 if (name [0] == '_')
177 err = mono_dl_symbol (current, name + 1, &symbol);
178 else
179 err = mono_dl_symbol (current, name, &symbol);
180 mono_dl_close (current);
181 if (!symbol)
182 outs () << "R: " << Name << "\n";
183 assert (symbol);
184 #if LLVM_API_VERSION >= 500
185 return JITSymbol((uint64_t)(gssize)symbol, flags);
186 #else
187 return RuntimeDyld::SymbolInfo((uint64_t)(gssize)symbol, flags);
188 #endif
190 [](const std::string &S) {
191 outs () << "R2: " << S << "\n";
192 assert (0);
193 return nullptr;
194 } );
196 #if LLVM_API_VERSION >= 500
197 auto m = CompileLayer.addModule(M, std::move(Resolver));
198 g_assert (!!m);
199 return m.get ();
200 #else
201 return CompileLayer.addModuleSet(singletonSet(M),
202 make_unique<MonoJitMemoryManager>(),
203 std::move(Resolver));
204 #endif
207 std::string mangle(const std::string &Name) {
208 std::string MangledName;
210 raw_string_ostream MangledNameStream(MangledName);
211 Mangler::getNameWithPrefix(MangledNameStream, Name,
212 TM->createDataLayout());
214 return MangledName;
217 std::string mangle(const GlobalValue *GV) {
218 std::string MangledName;
220 Mangler Mang;
222 raw_string_ostream MangledNameStream(MangledName);
223 Mang.getNameWithPrefix(MangledNameStream, GV, false);
225 return MangledName;
228 gpointer compile (Function *F, int nvars, LLVMValueRef *callee_vars, gpointer *callee_addrs, gpointer *eh_frame) {
229 F->getParent ()->setDataLayout (TM->createDataLayout ());
230 #if LLVM_API_VERSION >= 500
231 // Orc uses a shared_ptr to refer to modules so we have to save them ourselves to keep a ref
232 std::shared_ptr<Module> m (F->getParent ());
233 modules.push_back (m);
234 auto ModuleHandle = addModule (F, m);
235 #else
236 auto ModuleHandle = addModule (F, F->getParent ());
237 #endif
238 auto BodySym = CompileLayer.findSymbolIn(ModuleHandle, mangle (F), false);
239 auto BodyAddr = BodySym.getAddress();
240 assert (BodyAddr);
242 for (int i = 0; i < nvars; ++i) {
243 GlobalVariable *var = unwrap<GlobalVariable>(callee_vars [i]);
245 auto sym = CompileLayer.findSymbolIn (ModuleHandle, mangle (var->getName ()), true);
246 auto addr = sym.getAddress ();
247 #if LLVM_API_VERSION >= 500
248 g_assert ((bool)addr);
249 callee_addrs [i] = (gpointer)addr.get ();
250 #else
251 g_assert (addr);
252 callee_addrs [i] = (gpointer)addr;
253 #endif
256 auto ehsym = CompileLayer.findSymbolIn(ModuleHandle, "mono_eh_frame", false);
257 auto ehaddr = ehsym.getAddress ();
258 #if LLVM_API_VERSION >= 500
259 g_assert ((bool)ehaddr);
260 *eh_frame = (gpointer)ehaddr.get ();
261 return (gpointer)BodyAddr.get ();
262 #else
263 g_assert (ehaddr);
264 *eh_frame = (gpointer)ehaddr;
265 return (gpointer)BodyAddr;
266 #endif
269 private:
270 TargetMachine *TM;
271 ObjLayerT ObjectLayer;
272 CompileLayerT CompileLayer;
273 std::vector<std::shared_ptr<Module>> modules;
276 static MonoLLVMJIT *jit;
277 static MonoJitMemoryManager *mono_mm;
279 MonoEERef
280 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb, LLVMExecutionEngineRef *ee)
282 alloc_code_mem_cb = alloc_cb;
284 InitializeNativeTarget ();
285 InitializeNativeTargetAsmPrinter();
287 EnableMonoEH = true;
288 MonoEHFrameSymbol = "mono_eh_frame";
290 EngineBuilder EB;
291 #if defined(TARGET_AMD64) || defined(TARGET_X86)
292 std::vector<std::string> attrs;
293 // FIXME: Autodetect this
294 attrs.push_back("sse3");
295 attrs.push_back("sse4.1");
296 EB.setMAttrs (attrs);
297 #endif
298 auto TM = EB.selectTarget ();
299 assert (TM);
301 mono_mm = new MonoJitMemoryManager ();
302 jit = new MonoLLVMJIT (TM, mono_mm);
304 return NULL;
308 * mono_llvm_compile_method:
310 * Compile METHOD to native code. Compute the addresses of the variables in CALLEE_VARS and store them into
311 * CALLEE_ADDRS. Return the EH frame address in EH_FRAME.
313 gpointer
314 mono_llvm_compile_method (MonoEERef mono_ee, LLVMValueRef method, int nvars, LLVMValueRef *callee_vars, gpointer *callee_addrs, gpointer *eh_frame)
316 return jit->compile (unwrap<Function> (method), nvars, callee_vars, callee_addrs, eh_frame);
319 void
320 mono_llvm_dispose_ee (MonoEERef *eeref)
324 void
325 LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global,
326 void* Addr)
328 g_assert_not_reached ();
331 void*
332 LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global)
334 g_assert_not_reached ();
335 return NULL;
338 #elif defined(MONO_ARCH_LLVM_JIT_SUPPORTED) && !defined(MONO_CROSS_COMPILE) && LLVM_API_VERSION < 100
340 #include <stdint.h>
342 #include <llvm/Support/raw_ostream.h>
343 #include <llvm/Support/Host.h>
344 #include <llvm/PassManager.h>
345 #include <llvm/ExecutionEngine/ExecutionEngine.h>
346 #include <llvm/ExecutionEngine/JITMemoryManager.h>
347 #include <llvm/ExecutionEngine/JITEventListener.h>
348 #include <llvm/Target/TargetOptions.h>
349 #include <llvm/Target/TargetRegisterInfo.h>
350 #include <llvm/IR/Verifier.h>
351 #include <llvm/Analysis/Passes.h>
352 #include <llvm/Transforms/Scalar.h>
353 #include <llvm/Support/CommandLine.h>
354 #include <llvm/IR/LegacyPassNameParser.h>
355 #include <llvm/Support/PrettyStackTrace.h>
356 #include <llvm/CodeGen/Passes.h>
357 #include <llvm/CodeGen/MachineFunctionPass.h>
358 #include <llvm/CodeGen/MachineFunction.h>
359 #include <llvm/CodeGen/MachineFrameInfo.h>
360 #include <llvm/IR/Function.h>
361 #include <llvm/IR/IRBuilder.h>
362 #include <llvm/IR/Module.h>
364 using namespace llvm;
366 static void (*unhandled_exception)() = default_mono_llvm_unhandled_exception;
368 void
369 mono_llvm_set_unhandled_exception_handler (void)
371 std::set_terminate (unhandled_exception);
374 class MonoJITMemoryManager : public JITMemoryManager
376 private:
377 JITMemoryManager *mm;
379 public:
380 /* Callbacks installed by mono */
381 AllocCodeMemoryCb *alloc_cb;
382 DlSymCb *dlsym_cb;
383 ExceptionTableCb *exception_cb;
385 MonoJITMemoryManager ();
386 ~MonoJITMemoryManager ();
388 void setMemoryWritable (void);
390 void setMemoryExecutable (void);
392 void AllocateGOT();
394 unsigned char *getGOTBase() const {
395 return mm->getGOTBase ();
398 void setPoisonMemory(bool) {
401 unsigned char *startFunctionBody(const Function *F,
402 uintptr_t &ActualSize);
404 unsigned char *allocateStub(const GlobalValue* F, unsigned StubSize,
405 unsigned Alignment);
407 void endFunctionBody(const Function *F, unsigned char *FunctionStart,
408 unsigned char *FunctionEnd);
410 unsigned char *allocateSpace(intptr_t Size, unsigned Alignment);
412 uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment);
414 void deallocateMemForFunction(const Function *F);
416 unsigned char*startExceptionTable(const Function* F,
417 uintptr_t &ActualSize);
419 void endExceptionTable(const Function *F, unsigned char *TableStart,
420 unsigned char *TableEnd,
421 unsigned char* FrameRegister);
423 virtual void deallocateFunctionBody(void*) {
426 virtual void deallocateExceptionTable(void*) {
429 virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
430 StringRef SectionName) {
431 // FIXME:
432 assert(0);
433 return NULL;
436 virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
437 StringRef SectionName, bool IsReadOnly) {
438 // FIXME:
439 assert(0);
440 return NULL;
443 virtual bool applyPermissions(std::string*) {
444 // FIXME:
445 assert(0);
446 return false;
449 virtual bool finalizeMemory(std::string *ErrMsg = 0) {
450 // FIXME:
451 assert(0);
452 return false;
455 virtual void* getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure) {
456 void *res;
457 char *err;
459 err = dlsym_cb (Name.c_str (), &res);
460 if (err) {
461 outs () << "Unable to resolve: " << Name << ": " << err << "\n";
462 assert(0);
463 return NULL;
465 return res;
469 MonoJITMemoryManager::MonoJITMemoryManager ()
471 mm = JITMemoryManager::CreateDefaultMemManager ();
474 MonoJITMemoryManager::~MonoJITMemoryManager ()
476 delete mm;
479 void
480 MonoJITMemoryManager::setMemoryWritable (void)
484 void
485 MonoJITMemoryManager::setMemoryExecutable (void)
489 void
490 MonoJITMemoryManager::AllocateGOT()
492 mm->AllocateGOT ();
495 unsigned char *
496 MonoJITMemoryManager::startFunctionBody(const Function *F,
497 uintptr_t &ActualSize)
499 // FIXME: This leaks memory
500 if (ActualSize == 0)
501 ActualSize = 128;
502 return alloc_cb (wrap (F), ActualSize);
505 unsigned char *
506 MonoJITMemoryManager::allocateStub(const GlobalValue* F, unsigned StubSize,
507 unsigned Alignment)
509 return alloc_cb (wrap (F), StubSize);
512 void
513 MonoJITMemoryManager::endFunctionBody(const Function *F, unsigned char *FunctionStart,
514 unsigned char *FunctionEnd)
518 unsigned char *
519 MonoJITMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment)
521 return new unsigned char [Size];
524 uint8_t *
525 MonoJITMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment)
527 return new unsigned char [Size];
530 void
531 MonoJITMemoryManager::deallocateMemForFunction(const Function *F)
535 unsigned char*
536 MonoJITMemoryManager::startExceptionTable(const Function* F,
537 uintptr_t &ActualSize)
539 return startFunctionBody(F, ActualSize);
542 void
543 MonoJITMemoryManager::endExceptionTable(const Function *F, unsigned char *TableStart,
544 unsigned char *TableEnd,
545 unsigned char* FrameRegister)
547 exception_cb (FrameRegister);
550 class MonoJITEventListener : public JITEventListener {
552 public:
553 FunctionEmittedCb *emitted_cb;
555 MonoJITEventListener (FunctionEmittedCb *cb) {
556 emitted_cb = cb;
559 virtual void NotifyFunctionEmitted(const Function &F,
560 void *Code, size_t Size,
561 const EmittedFunctionDetails &Details) {
562 emitted_cb (wrap (&F), Code, (char*)Code + Size);
566 class MonoEE {
567 public:
568 ExecutionEngine *EE;
569 MonoJITMemoryManager *mm;
570 MonoJITEventListener *listener;
571 FunctionPassManager *fpm;
574 void
575 mono_llvm_optimize_method (MonoEERef eeref, LLVMValueRef method)
577 MonoEE *mono_ee = (MonoEE*)eeref;
580 * The verifier does some checks on the whole module, leading to quadratic behavior.
582 //verifyFunction (*(unwrap<Function> (method)));
583 mono_ee->fpm->run (*unwrap<Function> (method));
586 static cl::list<const PassInfo*, bool, PassNameParser>
587 PassList(cl::desc("Optimizations available:"));
589 static void
590 force_pass_linking (void)
592 // Make sure the rest is linked in, but never executed
593 char *foo = g_getenv ("FOO");
594 gboolean ret = (foo != (char*)-1);
595 g_free (foo);
597 if (ret)
598 return;
600 // This is a subset of the passes in LinkAllPasses.h
601 // The utility passes and the interprocedural passes are commented out
603 (void) llvm::createAAEvalPass();
604 (void) llvm::createAggressiveDCEPass();
605 (void) llvm::createAliasAnalysisCounterPass();
606 (void) llvm::createAliasDebugger();
608 (void) llvm::createArgumentPromotionPass();
609 (void) llvm::createStructRetPromotionPass();
611 (void) llvm::createBasicAliasAnalysisPass();
612 (void) llvm::createLibCallAliasAnalysisPass(0);
613 (void) llvm::createScalarEvolutionAliasAnalysisPass();
614 //(void) llvm::createBlockPlacementPass();
615 (void) llvm::createBreakCriticalEdgesPass();
616 (void) llvm::createCFGSimplificationPass();
618 (void) llvm::createConstantMergePass();
619 (void) llvm::createConstantPropagationPass();
622 (void) llvm::createDeadArgEliminationPass();
624 (void) llvm::createDeadCodeEliminationPass();
625 (void) llvm::createDeadInstEliminationPass();
626 (void) llvm::createDeadStoreEliminationPass();
628 (void) llvm::createDeadTypeEliminationPass();
629 (void) llvm::createDomOnlyPrinterPass();
630 (void) llvm::createDomPrinterPass();
631 (void) llvm::createDomOnlyViewerPass();
632 (void) llvm::createDomViewerPass();
633 (void) llvm::createEdgeProfilerPass();
634 (void) llvm::createOptimalEdgeProfilerPass();
635 (void) llvm::createFunctionInliningPass();
636 (void) llvm::createAlwaysInlinerPass();
637 (void) llvm::createGlobalDCEPass();
638 (void) llvm::createGlobalOptimizerPass();
639 (void) llvm::createGlobalsModRefPass();
640 (void) llvm::createIPConstantPropagationPass();
641 (void) llvm::createIPSCCPPass();
643 (void) llvm::createIndVarSimplifyPass();
644 (void) llvm::createInstructionCombiningPass();
646 (void) llvm::createInternalizePass(false);
648 (void) llvm::createLCSSAPass();
649 (void) llvm::createLICMPass();
650 (void) llvm::createLazyValueInfoPass();
651 //(void) llvm::createLoopDependenceAnalysisPass();
653 (void) llvm::createLoopExtractorPass();
655 (void) llvm::createLoopSimplifyPass();
656 (void) llvm::createLoopStrengthReducePass();
657 (void) llvm::createLoopUnrollPass();
658 (void) llvm::createLoopUnswitchPass();
659 (void) llvm::createLoopRotatePass();
660 (void) llvm::createLowerInvokePass();
662 (void) llvm::createLowerSetJmpPass();
664 (void) llvm::createLowerSwitchPass();
665 (void) llvm::createNoAAPass();
667 (void) llvm::createNoProfileInfoPass();
668 (void) llvm::createProfileEstimatorPass();
669 (void) llvm::createProfileVerifierPass();
670 (void) llvm::createProfileLoaderPass();
672 (void) llvm::createPromoteMemoryToRegisterPass();
673 (void) llvm::createDemoteRegisterToMemoryPass();
675 (void) llvm::createPruneEHPass();
676 (void) llvm::createPostDomOnlyPrinterPass();
677 (void) llvm::createPostDomPrinterPass();
678 (void) llvm::createPostDomOnlyViewerPass();
679 (void) llvm::createPostDomViewerPass();
681 (void) llvm::createReassociatePass();
682 (void) llvm::createSCCPPass();
683 (void) llvm::createScalarReplAggregatesPass();
684 //(void) llvm::createSimplifyLibCallsPass();
686 (void) llvm::createSingleLoopExtractorPass();
687 (void) llvm::createStripSymbolsPass();
688 (void) llvm::createStripNonDebugSymbolsPass();
689 (void) llvm::createStripDeadDebugInfoPass();
690 (void) llvm::createStripDeadPrototypesPass();
691 (void) llvm::createTailCallEliminationPass();
692 (void) llvm::createTailDuplicationPass();
693 (void) llvm::createJumpThreadingPass();
696 (void) llvm::createUnifyFunctionExitNodesPass();
698 (void) llvm::createInstCountPass();
699 (void) llvm::createCodeGenPreparePass();
700 (void) llvm::createGVNPass();
701 (void) llvm::createMemCpyOptPass();
702 (void) llvm::createLoopDeletionPass();
704 (void) llvm::createPostDomTree();
705 (void) llvm::createPostDomFrontier();
706 (void) llvm::createInstructionNamerPass();
707 (void) llvm::createPartialSpecializationPass();
708 (void) llvm::createFunctionAttrsPass();
709 (void) llvm::createMergeFunctionsPass();
710 (void) llvm::createPrintModulePass(0);
711 (void) llvm::createPrintFunctionPass("", 0);
712 (void) llvm::createDbgInfoPrinterPass();
713 (void) llvm::createModuleDebugInfoPrinterPass();
714 (void) llvm::createPartialInliningPass();
715 (void) llvm::createGEPSplitterPass();
716 (void) llvm::createLintPass();
718 (void) llvm::createSinkingPass();
721 static gboolean inited;
723 static void
724 init_llvm (void)
726 if (inited)
727 return;
729 force_pass_linking ();
731 #ifdef TARGET_ARM
732 LLVMInitializeARMTarget ();
733 LLVMInitializeARMTargetInfo ();
734 LLVMInitializeARMTargetMC ();
735 #elif defined(TARGET_ARM64)
736 LLVMInitializeAArch64Target ();
737 LLVMInitializeAArch64TargetInfo ();
738 LLVMInitializeAArch64TargetMC ();
739 #elif defined(TARGET_X86) || defined(TARGET_AMD64)
740 LLVMInitializeX86Target ();
741 LLVMInitializeX86TargetInfo ();
742 LLVMInitializeX86TargetMC ();
743 #elif defined(TARGET_POWERPC)
744 LLVMInitializePowerPCTarget ();
745 LLVMInitializePowerPCTargetInfo ();
746 LLVMInitializePowerPCTargetMC ();
747 #else
748 #error Unsupported mono-llvm target
749 #endif
751 PassRegistry &Registry = *PassRegistry::getPassRegistry();
752 initializeCore(Registry);
753 initializeScalarOpts(Registry);
754 initializeAnalysis(Registry);
755 initializeIPA(Registry);
756 initializeTransformUtils(Registry);
757 initializeInstCombine(Registry);
758 initializeTarget(Registry);
760 llvm::cl::ParseEnvironmentOptions("mono", "MONO_LLVM", "");
762 inited = true;
765 MonoEERef
766 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb, LLVMExecutionEngineRef *ee)
768 std::string Error;
769 MonoEE *mono_ee;
771 init_llvm ();
773 mono_ee = new MonoEE ();
775 MonoJITMemoryManager *mono_mm = new MonoJITMemoryManager ();
776 mono_mm->alloc_cb = alloc_cb;
777 mono_mm->dlsym_cb = dlsym_cb;
778 mono_mm->exception_cb = exception_cb;
779 mono_ee->mm = mono_mm;
782 * The Default code model doesn't seem to work on amd64,
783 * test_0_fields_with_big_offsets (among others) crashes, because LLVM tries to call
784 * memset using a normal pcrel code which is in 32bit memory, while memset isn't.
787 TargetOptions opts;
788 opts.JITExceptionHandling = 1;
790 StringRef cpu_name = sys::getHostCPUName ();
792 // EngineBuilder no longer has a copy assignment operator (?)
793 std::unique_ptr<Module> Owner(unwrap(MP));
794 EngineBuilder b (std::move(Owner));
795 ExecutionEngine *EE = b.setJITMemoryManager (mono_mm).setTargetOptions (opts).setAllocateGVsWithCode (true).setMCPU (cpu_name).create ();
797 g_assert (EE);
798 mono_ee->EE = EE;
800 MonoJITEventListener *listener = new MonoJITEventListener (emitted_cb);
801 EE->RegisterJITEventListener (listener);
802 mono_ee->listener = listener;
804 FunctionPassManager *fpm = new FunctionPassManager (unwrap (MP));
805 mono_ee->fpm = fpm;
807 fpm->add(new DataLayoutPass(*EE->getDataLayout()));
809 if (PassList.size() > 0) {
810 /* Use the passes specified by the env variable */
811 /* Only the passes in force_pass_linking () can be used */
812 for (unsigned i = 0; i < PassList.size(); ++i) {
813 const PassInfo *PassInf = PassList[i];
814 Pass *P = 0;
816 if (PassInf->getNormalCtor())
817 P = PassInf->getNormalCtor()();
818 fpm->add (P);
820 } else {
821 /* Use the same passes used by 'opt' by default, without the ipo passes */
822 const char *opts = "-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -domfrontier -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -iv-users -indvars -loop-deletion -loop-simplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -gvn -simplifycfg";
823 char **args;
824 int i;
826 args = g_strsplit (opts, " ", 1000);
827 for (i = 0; args [i]; i++)
829 llvm::cl::ParseCommandLineOptions (i, args, "");
830 g_strfreev (args);
832 for (unsigned i = 0; i < PassList.size(); ++i) {
833 const PassInfo *PassInf = PassList[i];
834 Pass *P = 0;
836 if (PassInf->getNormalCtor())
837 P = PassInf->getNormalCtor()();
838 g_assert (P->getPassKind () == llvm::PT_Function || P->getPassKind () == llvm::PT_Loop);
839 fpm->add (P);
843 fpm->add(createInstructionCombiningPass());
844 fpm->add(createReassociatePass());
845 fpm->add(createGVNPass());
846 fpm->add(createCFGSimplificationPass());
850 *ee = wrap (EE);
852 return mono_ee;
855 void
856 mono_llvm_dispose_ee (MonoEERef *eeref)
858 MonoEE *mono_ee = (MonoEE*)eeref;
860 delete mono_ee->EE;
861 delete mono_ee->fpm;
862 //delete mono_ee->mm;
863 delete mono_ee->listener;
864 delete mono_ee;
867 #else /* MONO_CROSS_COMPILE */
869 void
870 mono_llvm_set_unhandled_exception_handler (void)
874 MonoEERef
875 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb, LLVMExecutionEngineRef *ee)
877 g_error ("LLVM JIT not supported on this platform.");
878 return NULL;
881 void
882 mono_llvm_optimize_method (MonoEERef eeref, LLVMValueRef method)
884 g_assert_not_reached ();
887 gpointer
888 mono_llvm_compile_method (MonoEERef mono_ee, LLVMValueRef method, int nvars, LLVMValueRef *callee_vars, gpointer *callee_addrs, gpointer *eh_frame)
890 g_assert_not_reached ();
891 return NULL;
894 void
895 mono_llvm_dispose_ee (MonoEERef *eeref)
897 g_assert_not_reached ();
900 /* Not linked in */
901 void
902 LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global,
903 void* Addr)
905 g_assert_not_reached ();
908 void*
909 LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global)
911 g_assert_not_reached ();
912 return NULL;
915 #endif /* !MONO_CROSS_COMPILE */