2 // jit-llvm.cpp: Support code for using LLVM as a JIT backend
4 // (C) 2009-2011 Novell, Inc.
5 // Copyright 2011-2015 Xamarin, Inc (http://www.xamarin.com)
9 // Mono's internal header files are not C++ clean, so avoid including them if
15 #include <llvm-c/Core.h>
16 #include <llvm-c/ExecutionEngine.h>
18 #include "mini-llvm-cpp.h"
20 #if !defined(MONO_CROSS_COMPILE) && LLVM_API_VERSION > 100
23 * LLVM 3.9 uses the OrcJIT APIs
26 #include <llvm/Support/raw_ostream.h>
27 #include <llvm/Support/Host.h>
28 #include <llvm/Support/TargetSelect.h>
29 #include <llvm/ExecutionEngine/ExecutionEngine.h>
30 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
31 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
32 #include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
33 #include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h"
34 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
35 #include "llvm/ExecutionEngine/Orc/OrcArchitectureSupport.h"
38 using namespace llvm::orc;
41 mono_llvm_set_unhandled_exception_handler (void)
45 static gboolean inited;
53 InitializeNativeTarget ();
54 InitializeNativeTargetAsmPrinter();
58 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb, LLVMExecutionEngineRef *ee)
66 mono_llvm_optimize_method (MonoEERef eeref, LLVMValueRef method)
68 g_assert_not_reached ();
72 mono_llvm_dispose_ee (MonoEERef *eeref)
77 LLVMAddGlobalMapping (LLVMExecutionEngineRef EE, LLVMValueRef Global,
83 LLVMGetPointerToGlobal (LLVMExecutionEngineRef EE, LLVMValueRef Global)
85 g_assert_not_reached ();
89 #elif !defined(MONO_CROSS_COMPILE) && LLVM_API_VERSION < 100
93 #include <llvm/Support/raw_ostream.h>
94 #include <llvm/Support/Host.h>
95 #include <llvm/PassManager.h>
96 #include <llvm/ExecutionEngine/ExecutionEngine.h>
97 #include <llvm/ExecutionEngine/JITMemoryManager.h>
98 #include <llvm/ExecutionEngine/JITEventListener.h>
99 #include <llvm/Target/TargetOptions.h>
100 #include <llvm/Target/TargetRegisterInfo.h>
101 #include <llvm/IR/Verifier.h>
102 #include <llvm/Analysis/Passes.h>
103 #include <llvm/Transforms/Scalar.h>
104 #include <llvm/Support/CommandLine.h>
105 #include <llvm/IR/LegacyPassNameParser.h>
106 #include <llvm/Support/PrettyStackTrace.h>
107 #include <llvm/CodeGen/Passes.h>
108 #include <llvm/CodeGen/MachineFunctionPass.h>
109 #include <llvm/CodeGen/MachineFunction.h>
110 #include <llvm/CodeGen/MachineFrameInfo.h>
111 #include <llvm/IR/Function.h>
112 #include <llvm/IR/IRBuilder.h>
113 #include <llvm/IR/Module.h>
115 using namespace llvm;
117 static void (*unhandled_exception)() = default_mono_llvm_unhandled_exception;
120 mono_llvm_set_unhandled_exception_handler (void)
122 std::set_terminate (unhandled_exception);
125 class MonoJITMemoryManager : public JITMemoryManager
128 JITMemoryManager *mm;
131 /* Callbacks installed by mono */
132 AllocCodeMemoryCb *alloc_cb;
134 ExceptionTableCb *exception_cb;
136 MonoJITMemoryManager ();
137 ~MonoJITMemoryManager ();
139 void setMemoryWritable (void);
141 void setMemoryExecutable (void);
145 unsigned char *getGOTBase() const {
146 return mm->getGOTBase ();
149 void setPoisonMemory(bool) {
152 unsigned char *startFunctionBody(const Function *F,
153 uintptr_t &ActualSize);
155 unsigned char *allocateStub(const GlobalValue* F, unsigned StubSize,
158 void endFunctionBody(const Function *F, unsigned char *FunctionStart,
159 unsigned char *FunctionEnd);
161 unsigned char *allocateSpace(intptr_t Size, unsigned Alignment);
163 uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment);
165 void deallocateMemForFunction(const Function *F);
167 unsigned char*startExceptionTable(const Function* F,
168 uintptr_t &ActualSize);
170 void endExceptionTable(const Function *F, unsigned char *TableStart,
171 unsigned char *TableEnd,
172 unsigned char* FrameRegister);
174 virtual void deallocateFunctionBody(void*) {
177 virtual void deallocateExceptionTable(void*) {
180 virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
181 StringRef SectionName) {
187 virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
188 StringRef SectionName, bool IsReadOnly) {
194 virtual bool applyPermissions(std::string*) {
200 virtual bool finalizeMemory(std::string *ErrMsg = 0) {
206 virtual void* getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure) {
210 err = dlsym_cb (Name.c_str (), &res);
212 outs () << "Unable to resolve: " << Name << ": " << err << "\n";
220 MonoJITMemoryManager::MonoJITMemoryManager ()
222 mm = JITMemoryManager::CreateDefaultMemManager ();
225 MonoJITMemoryManager::~MonoJITMemoryManager ()
231 MonoJITMemoryManager::setMemoryWritable (void)
236 MonoJITMemoryManager::setMemoryExecutable (void)
241 MonoJITMemoryManager::AllocateGOT()
247 MonoJITMemoryManager::startFunctionBody(const Function *F,
248 uintptr_t &ActualSize)
250 // FIXME: This leaks memory
253 return alloc_cb (wrap (F), ActualSize);
257 MonoJITMemoryManager::allocateStub(const GlobalValue* F, unsigned StubSize,
260 return alloc_cb (wrap (F), StubSize);
264 MonoJITMemoryManager::endFunctionBody(const Function *F, unsigned char *FunctionStart,
265 unsigned char *FunctionEnd)
270 MonoJITMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment)
272 return new unsigned char [Size];
276 MonoJITMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment)
278 return new unsigned char [Size];
282 MonoJITMemoryManager::deallocateMemForFunction(const Function *F)
287 MonoJITMemoryManager::startExceptionTable(const Function* F,
288 uintptr_t &ActualSize)
290 return startFunctionBody(F, ActualSize);
294 MonoJITMemoryManager::endExceptionTable(const Function *F, unsigned char *TableStart,
295 unsigned char *TableEnd,
296 unsigned char* FrameRegister)
298 exception_cb (FrameRegister);
301 class MonoJITEventListener : public JITEventListener {
304 FunctionEmittedCb *emitted_cb;
306 MonoJITEventListener (FunctionEmittedCb *cb) {
310 virtual void NotifyFunctionEmitted(const Function &F,
311 void *Code, size_t Size,
312 const EmittedFunctionDetails &Details) {
313 emitted_cb (wrap (&F), Code, (char*)Code + Size);
320 MonoJITMemoryManager *mm;
321 MonoJITEventListener *listener;
322 FunctionPassManager *fpm;
326 mono_llvm_optimize_method (MonoEERef eeref, LLVMValueRef method)
328 MonoEE *mono_ee = (MonoEE*)eeref;
331 * The verifier does some checks on the whole module, leading to quadratic behavior.
333 //verifyFunction (*(unwrap<Function> (method)));
334 mono_ee->fpm->run (*unwrap<Function> (method));
337 static cl::list<const PassInfo*, bool, PassNameParser>
338 PassList(cl::desc("Optimizations available:"));
341 force_pass_linking (void)
343 // Make sure the rest is linked in, but never executed
344 if (g_getenv ("FOO") != (char*)-1)
347 // This is a subset of the passes in LinkAllPasses.h
348 // The utility passes and the interprocedural passes are commented out
350 (void) llvm::createAAEvalPass();
351 (void) llvm::createAggressiveDCEPass();
352 (void) llvm::createAliasAnalysisCounterPass();
353 (void) llvm::createAliasDebugger();
355 (void) llvm::createArgumentPromotionPass();
356 (void) llvm::createStructRetPromotionPass();
358 (void) llvm::createBasicAliasAnalysisPass();
359 (void) llvm::createLibCallAliasAnalysisPass(0);
360 (void) llvm::createScalarEvolutionAliasAnalysisPass();
361 //(void) llvm::createBlockPlacementPass();
362 (void) llvm::createBreakCriticalEdgesPass();
363 (void) llvm::createCFGSimplificationPass();
365 (void) llvm::createConstantMergePass();
366 (void) llvm::createConstantPropagationPass();
369 (void) llvm::createDeadArgEliminationPass();
371 (void) llvm::createDeadCodeEliminationPass();
372 (void) llvm::createDeadInstEliminationPass();
373 (void) llvm::createDeadStoreEliminationPass();
375 (void) llvm::createDeadTypeEliminationPass();
376 (void) llvm::createDomOnlyPrinterPass();
377 (void) llvm::createDomPrinterPass();
378 (void) llvm::createDomOnlyViewerPass();
379 (void) llvm::createDomViewerPass();
380 (void) llvm::createEdgeProfilerPass();
381 (void) llvm::createOptimalEdgeProfilerPass();
382 (void) llvm::createFunctionInliningPass();
383 (void) llvm::createAlwaysInlinerPass();
384 (void) llvm::createGlobalDCEPass();
385 (void) llvm::createGlobalOptimizerPass();
386 (void) llvm::createGlobalsModRefPass();
387 (void) llvm::createIPConstantPropagationPass();
388 (void) llvm::createIPSCCPPass();
390 (void) llvm::createIndVarSimplifyPass();
391 (void) llvm::createInstructionCombiningPass();
393 (void) llvm::createInternalizePass(false);
395 (void) llvm::createLCSSAPass();
396 (void) llvm::createLICMPass();
397 (void) llvm::createLazyValueInfoPass();
398 //(void) llvm::createLoopDependenceAnalysisPass();
400 (void) llvm::createLoopExtractorPass();
402 (void) llvm::createLoopSimplifyPass();
403 (void) llvm::createLoopStrengthReducePass();
404 (void) llvm::createLoopUnrollPass();
405 (void) llvm::createLoopUnswitchPass();
406 (void) llvm::createLoopRotatePass();
407 (void) llvm::createLowerInvokePass();
409 (void) llvm::createLowerSetJmpPass();
411 (void) llvm::createLowerSwitchPass();
412 (void) llvm::createNoAAPass();
414 (void) llvm::createNoProfileInfoPass();
415 (void) llvm::createProfileEstimatorPass();
416 (void) llvm::createProfileVerifierPass();
417 (void) llvm::createProfileLoaderPass();
419 (void) llvm::createPromoteMemoryToRegisterPass();
420 (void) llvm::createDemoteRegisterToMemoryPass();
422 (void) llvm::createPruneEHPass();
423 (void) llvm::createPostDomOnlyPrinterPass();
424 (void) llvm::createPostDomPrinterPass();
425 (void) llvm::createPostDomOnlyViewerPass();
426 (void) llvm::createPostDomViewerPass();
428 (void) llvm::createReassociatePass();
429 (void) llvm::createSCCPPass();
430 (void) llvm::createScalarReplAggregatesPass();
431 //(void) llvm::createSimplifyLibCallsPass();
433 (void) llvm::createSingleLoopExtractorPass();
434 (void) llvm::createStripSymbolsPass();
435 (void) llvm::createStripNonDebugSymbolsPass();
436 (void) llvm::createStripDeadDebugInfoPass();
437 (void) llvm::createStripDeadPrototypesPass();
438 (void) llvm::createTailCallEliminationPass();
439 (void) llvm::createTailDuplicationPass();
440 (void) llvm::createJumpThreadingPass();
443 (void) llvm::createUnifyFunctionExitNodesPass();
445 (void) llvm::createInstCountPass();
446 (void) llvm::createCodeGenPreparePass();
447 (void) llvm::createGVNPass();
448 (void) llvm::createMemCpyOptPass();
449 (void) llvm::createLoopDeletionPass();
451 (void) llvm::createPostDomTree();
452 (void) llvm::createPostDomFrontier();
453 (void) llvm::createInstructionNamerPass();
454 (void) llvm::createPartialSpecializationPass();
455 (void) llvm::createFunctionAttrsPass();
456 (void) llvm::createMergeFunctionsPass();
457 (void) llvm::createPrintModulePass(0);
458 (void) llvm::createPrintFunctionPass("", 0);
459 (void) llvm::createDbgInfoPrinterPass();
460 (void) llvm::createModuleDebugInfoPrinterPass();
461 (void) llvm::createPartialInliningPass();
462 (void) llvm::createGEPSplitterPass();
463 (void) llvm::createLintPass();
465 (void) llvm::createSinkingPass();
468 static gboolean inited;
476 force_pass_linking ();
479 LLVMInitializeARMTarget ();
480 LLVMInitializeARMTargetInfo ();
481 LLVMInitializeARMTargetMC ();
482 #elif defined(TARGET_X86) || defined(TARGET_AMD64)
483 LLVMInitializeX86Target ();
484 LLVMInitializeX86TargetInfo ();
485 LLVMInitializeX86TargetMC ();
486 #elif defined(TARGET_POWERPC)
487 LLVMInitializePowerPCTarget ();
488 LLVMInitializePowerPCTargetInfo ();
489 LLVMInitializePowerPCTargetMC ();
491 #error Unsupported mono-llvm target
494 PassRegistry &Registry = *PassRegistry::getPassRegistry();
495 initializeCore(Registry);
496 initializeScalarOpts(Registry);
497 initializeAnalysis(Registry);
498 initializeIPA(Registry);
499 initializeTransformUtils(Registry);
500 initializeInstCombine(Registry);
501 initializeTarget(Registry);
503 llvm::cl::ParseEnvironmentOptions("mono", "MONO_LLVM", "");
509 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb, LLVMExecutionEngineRef *ee)
516 mono_ee = new MonoEE ();
518 MonoJITMemoryManager *mono_mm = new MonoJITMemoryManager ();
519 mono_mm->alloc_cb = alloc_cb;
520 mono_mm->dlsym_cb = dlsym_cb;
521 mono_mm->exception_cb = exception_cb;
522 mono_ee->mm = mono_mm;
525 * The Default code model doesn't seem to work on amd64,
526 * test_0_fields_with_big_offsets (among others) crashes, because LLVM tries to call
527 * memset using a normal pcrel code which is in 32bit memory, while memset isn't.
531 opts.JITExceptionHandling = 1;
533 StringRef cpu_name = sys::getHostCPUName ();
535 // EngineBuilder no longer has a copy assignment operator (?)
536 std::unique_ptr<Module> Owner(unwrap(MP));
537 EngineBuilder b (std::move(Owner));
538 ExecutionEngine *EE = b.setJITMemoryManager (mono_mm).setTargetOptions (opts).setAllocateGVsWithCode (true).setMCPU (cpu_name).create ();
543 MonoJITEventListener *listener = new MonoJITEventListener (emitted_cb);
544 EE->RegisterJITEventListener (listener);
545 mono_ee->listener = listener;
547 FunctionPassManager *fpm = new FunctionPassManager (unwrap (MP));
550 fpm->add(new DataLayoutPass(*EE->getDataLayout()));
552 if (PassList.size() > 0) {
553 /* Use the passes specified by the env variable */
554 /* Only the passes in force_pass_linking () can be used */
555 for (unsigned i = 0; i < PassList.size(); ++i) {
556 const PassInfo *PassInf = PassList[i];
559 if (PassInf->getNormalCtor())
560 P = PassInf->getNormalCtor()();
564 /* Use the same passes used by 'opt' by default, without the ipo passes */
565 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";
569 args = g_strsplit (opts, " ", 1000);
570 for (i = 0; args [i]; i++)
572 llvm::cl::ParseCommandLineOptions (i, args, "");
575 for (unsigned i = 0; i < PassList.size(); ++i) {
576 const PassInfo *PassInf = PassList[i];
579 if (PassInf->getNormalCtor())
580 P = PassInf->getNormalCtor()();
581 g_assert (P->getPassKind () == llvm::PT_Function || P->getPassKind () == llvm::PT_Loop);
586 fpm->add(createInstructionCombiningPass());
587 fpm->add(createReassociatePass());
588 fpm->add(createGVNPass());
589 fpm->add(createCFGSimplificationPass());
599 mono_llvm_dispose_ee (MonoEERef *eeref)
601 MonoEE *mono_ee = (MonoEE*)eeref;
605 //delete mono_ee->mm;
606 delete mono_ee->listener;
610 #else /* MONO_CROSS_COMPILE */
613 mono_llvm_set_unhandled_exception_handler (void)
618 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb, LLVMExecutionEngineRef *ee)
620 g_assert_not_reached ();
625 mono_llvm_optimize_method (MonoEERef eeref, LLVMValueRef method)
627 g_assert_not_reached ();
631 mono_llvm_dispose_ee (MonoEERef *eeref)
633 g_assert_not_reached ();
638 LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global,
641 g_assert_not_reached ();
645 LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global)
647 g_assert_not_reached ();
651 #endif /* !MONO_CROSS_COMPILE */