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
17 #include <llvm/Support/raw_ostream.h>
18 #include <llvm/Support/Host.h>
19 #include <llvm/PassManager.h>
20 #include <llvm/ExecutionEngine/ExecutionEngine.h>
21 #include <llvm/ExecutionEngine/JITMemoryManager.h>
22 #include <llvm/ExecutionEngine/JITEventListener.h>
23 #include <llvm/Target/TargetOptions.h>
24 #include <llvm/Target/TargetRegisterInfo.h>
25 #include <llvm/IR/Verifier.h>
26 #include <llvm/Analysis/Passes.h>
27 #include <llvm/Transforms/Scalar.h>
28 #include <llvm/Support/CommandLine.h>
29 #include <llvm/IR/LegacyPassNameParser.h>
30 #include <llvm/Support/PrettyStackTrace.h>
31 #include <llvm/CodeGen/Passes.h>
32 #include <llvm/CodeGen/MachineFunctionPass.h>
33 #include <llvm/CodeGen/MachineFunction.h>
34 #include <llvm/CodeGen/MachineFrameInfo.h>
35 #include <llvm/IR/Function.h>
36 #include <llvm/IR/IRBuilder.h>
37 #include <llvm/IR/Module.h>
39 #include <llvm-c/Core.h>
40 #include <llvm-c/ExecutionEngine.h>
42 #include "mini-llvm-cpp.h"
44 #ifndef MONO_CROSS_COMPILE
48 static void (*unhandled_exception)() = default_mono_llvm_unhandled_exception;
51 mono_llvm_set_unhandled_exception_handler (void)
53 std::set_terminate (unhandled_exception);
56 class MonoJITMemoryManager : public JITMemoryManager
62 /* Callbacks installed by mono */
63 AllocCodeMemoryCb *alloc_cb;
65 ExceptionTableCb *exception_cb;
67 MonoJITMemoryManager ();
68 ~MonoJITMemoryManager ();
70 void setMemoryWritable (void);
72 void setMemoryExecutable (void);
76 unsigned char *getGOTBase() const {
77 return mm->getGOTBase ();
80 void setPoisonMemory(bool) {
83 unsigned char *startFunctionBody(const Function *F,
84 uintptr_t &ActualSize);
86 unsigned char *allocateStub(const GlobalValue* F, unsigned StubSize,
89 void endFunctionBody(const Function *F, unsigned char *FunctionStart,
90 unsigned char *FunctionEnd);
92 unsigned char *allocateSpace(intptr_t Size, unsigned Alignment);
94 uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment);
96 void deallocateMemForFunction(const Function *F);
98 unsigned char*startExceptionTable(const Function* F,
99 uintptr_t &ActualSize);
101 void endExceptionTable(const Function *F, unsigned char *TableStart,
102 unsigned char *TableEnd,
103 unsigned char* FrameRegister);
105 virtual void deallocateFunctionBody(void*) {
108 virtual void deallocateExceptionTable(void*) {
111 virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
112 StringRef SectionName) {
118 virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
119 StringRef SectionName, bool IsReadOnly) {
125 virtual bool applyPermissions(std::string*) {
131 virtual bool finalizeMemory(std::string *ErrMsg = 0) {
137 virtual void* getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure) {
141 err = dlsym_cb (Name.c_str (), &res);
143 outs () << "Unable to resolve: " << Name << ": " << err << "\n";
151 MonoJITMemoryManager::MonoJITMemoryManager ()
153 mm = JITMemoryManager::CreateDefaultMemManager ();
156 MonoJITMemoryManager::~MonoJITMemoryManager ()
162 MonoJITMemoryManager::setMemoryWritable (void)
167 MonoJITMemoryManager::setMemoryExecutable (void)
172 MonoJITMemoryManager::AllocateGOT()
178 MonoJITMemoryManager::startFunctionBody(const Function *F,
179 uintptr_t &ActualSize)
181 // FIXME: This leaks memory
184 return alloc_cb (wrap (F), ActualSize);
188 MonoJITMemoryManager::allocateStub(const GlobalValue* F, unsigned StubSize,
191 return alloc_cb (wrap (F), StubSize);
195 MonoJITMemoryManager::endFunctionBody(const Function *F, unsigned char *FunctionStart,
196 unsigned char *FunctionEnd)
201 MonoJITMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment)
203 return new unsigned char [Size];
207 MonoJITMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment)
209 return new unsigned char [Size];
213 MonoJITMemoryManager::deallocateMemForFunction(const Function *F)
218 MonoJITMemoryManager::startExceptionTable(const Function* F,
219 uintptr_t &ActualSize)
221 return startFunctionBody(F, ActualSize);
225 MonoJITMemoryManager::endExceptionTable(const Function *F, unsigned char *TableStart,
226 unsigned char *TableEnd,
227 unsigned char* FrameRegister)
229 exception_cb (FrameRegister);
232 class MonoJITEventListener : public JITEventListener {
235 FunctionEmittedCb *emitted_cb;
237 MonoJITEventListener (FunctionEmittedCb *cb) {
241 virtual void NotifyFunctionEmitted(const Function &F,
242 void *Code, size_t Size,
243 const EmittedFunctionDetails &Details) {
244 emitted_cb (wrap (&F), Code, (char*)Code + Size);
251 MonoJITMemoryManager *mm;
252 MonoJITEventListener *listener;
253 FunctionPassManager *fpm;
257 mono_llvm_optimize_method (MonoEERef eeref, LLVMValueRef method)
259 MonoEE *mono_ee = (MonoEE*)eeref;
262 * The verifier does some checks on the whole module, leading to quadratic behavior.
264 //verifyFunction (*(unwrap<Function> (method)));
265 mono_ee->fpm->run (*unwrap<Function> (method));
268 static cl::list<const PassInfo*, bool, PassNameParser>
269 PassList(cl::desc("Optimizations available:"));
272 force_pass_linking (void)
274 // Make sure the rest is linked in, but never executed
275 if (g_getenv ("FOO") != (char*)-1)
278 // This is a subset of the passes in LinkAllPasses.h
279 // The utility passes and the interprocedural passes are commented out
281 (void) llvm::createAAEvalPass();
282 (void) llvm::createAggressiveDCEPass();
283 (void) llvm::createAliasAnalysisCounterPass();
284 (void) llvm::createAliasDebugger();
286 (void) llvm::createArgumentPromotionPass();
287 (void) llvm::createStructRetPromotionPass();
289 (void) llvm::createBasicAliasAnalysisPass();
290 (void) llvm::createLibCallAliasAnalysisPass(0);
291 (void) llvm::createScalarEvolutionAliasAnalysisPass();
292 //(void) llvm::createBlockPlacementPass();
293 (void) llvm::createBreakCriticalEdgesPass();
294 (void) llvm::createCFGSimplificationPass();
296 (void) llvm::createConstantMergePass();
297 (void) llvm::createConstantPropagationPass();
300 (void) llvm::createDeadArgEliminationPass();
302 (void) llvm::createDeadCodeEliminationPass();
303 (void) llvm::createDeadInstEliminationPass();
304 (void) llvm::createDeadStoreEliminationPass();
306 (void) llvm::createDeadTypeEliminationPass();
307 (void) llvm::createDomOnlyPrinterPass();
308 (void) llvm::createDomPrinterPass();
309 (void) llvm::createDomOnlyViewerPass();
310 (void) llvm::createDomViewerPass();
311 (void) llvm::createEdgeProfilerPass();
312 (void) llvm::createOptimalEdgeProfilerPass();
313 (void) llvm::createFunctionInliningPass();
314 (void) llvm::createAlwaysInlinerPass();
315 (void) llvm::createGlobalDCEPass();
316 (void) llvm::createGlobalOptimizerPass();
317 (void) llvm::createGlobalsModRefPass();
318 (void) llvm::createIPConstantPropagationPass();
319 (void) llvm::createIPSCCPPass();
321 (void) llvm::createIndVarSimplifyPass();
322 (void) llvm::createInstructionCombiningPass();
324 (void) llvm::createInternalizePass(false);
326 (void) llvm::createLCSSAPass();
327 (void) llvm::createLICMPass();
328 (void) llvm::createLazyValueInfoPass();
329 //(void) llvm::createLoopDependenceAnalysisPass();
331 (void) llvm::createLoopExtractorPass();
333 (void) llvm::createLoopSimplifyPass();
334 (void) llvm::createLoopStrengthReducePass();
335 (void) llvm::createLoopUnrollPass();
336 (void) llvm::createLoopUnswitchPass();
337 (void) llvm::createLoopRotatePass();
338 (void) llvm::createLowerInvokePass();
340 (void) llvm::createLowerSetJmpPass();
342 (void) llvm::createLowerSwitchPass();
343 (void) llvm::createNoAAPass();
345 (void) llvm::createNoProfileInfoPass();
346 (void) llvm::createProfileEstimatorPass();
347 (void) llvm::createProfileVerifierPass();
348 (void) llvm::createProfileLoaderPass();
350 (void) llvm::createPromoteMemoryToRegisterPass();
351 (void) llvm::createDemoteRegisterToMemoryPass();
353 (void) llvm::createPruneEHPass();
354 (void) llvm::createPostDomOnlyPrinterPass();
355 (void) llvm::createPostDomPrinterPass();
356 (void) llvm::createPostDomOnlyViewerPass();
357 (void) llvm::createPostDomViewerPass();
359 (void) llvm::createReassociatePass();
360 (void) llvm::createSCCPPass();
361 (void) llvm::createScalarReplAggregatesPass();
362 //(void) llvm::createSimplifyLibCallsPass();
364 (void) llvm::createSingleLoopExtractorPass();
365 (void) llvm::createStripSymbolsPass();
366 (void) llvm::createStripNonDebugSymbolsPass();
367 (void) llvm::createStripDeadDebugInfoPass();
368 (void) llvm::createStripDeadPrototypesPass();
369 (void) llvm::createTailCallEliminationPass();
370 (void) llvm::createTailDuplicationPass();
371 (void) llvm::createJumpThreadingPass();
374 (void) llvm::createUnifyFunctionExitNodesPass();
376 (void) llvm::createInstCountPass();
377 (void) llvm::createCodeGenPreparePass();
378 (void) llvm::createGVNPass();
379 (void) llvm::createMemCpyOptPass();
380 (void) llvm::createLoopDeletionPass();
382 (void) llvm::createPostDomTree();
383 (void) llvm::createPostDomFrontier();
384 (void) llvm::createInstructionNamerPass();
385 (void) llvm::createPartialSpecializationPass();
386 (void) llvm::createFunctionAttrsPass();
387 (void) llvm::createMergeFunctionsPass();
388 (void) llvm::createPrintModulePass(0);
389 (void) llvm::createPrintFunctionPass("", 0);
390 (void) llvm::createDbgInfoPrinterPass();
391 (void) llvm::createModuleDebugInfoPrinterPass();
392 (void) llvm::createPartialInliningPass();
393 (void) llvm::createGEPSplitterPass();
394 (void) llvm::createLintPass();
396 (void) llvm::createSinkingPass();
399 static gboolean inited;
407 force_pass_linking ();
410 LLVMInitializeARMTarget ();
411 LLVMInitializeARMTargetInfo ();
412 LLVMInitializeARMTargetMC ();
413 #elif defined(TARGET_X86) || defined(TARGET_AMD64)
414 LLVMInitializeX86Target ();
415 LLVMInitializeX86TargetInfo ();
416 LLVMInitializeX86TargetMC ();
417 #elif defined(TARGET_POWERPC)
418 LLVMInitializePowerPCTarget ();
419 LLVMInitializePowerPCTargetInfo ();
420 LLVMInitializePowerPCTargetMC ();
422 #error Unsupported mono-llvm target
425 PassRegistry &Registry = *PassRegistry::getPassRegistry();
426 initializeCore(Registry);
427 initializeScalarOpts(Registry);
428 initializeAnalysis(Registry);
429 initializeIPA(Registry);
430 initializeTransformUtils(Registry);
431 initializeInstCombine(Registry);
432 initializeTarget(Registry);
434 llvm::cl::ParseEnvironmentOptions("mono", "MONO_LLVM", "");
440 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb, LLVMExecutionEngineRef *ee)
447 mono_ee = new MonoEE ();
449 MonoJITMemoryManager *mono_mm = new MonoJITMemoryManager ();
450 mono_mm->alloc_cb = alloc_cb;
451 mono_mm->dlsym_cb = dlsym_cb;
452 mono_mm->exception_cb = exception_cb;
453 mono_ee->mm = mono_mm;
456 * The Default code model doesn't seem to work on amd64,
457 * test_0_fields_with_big_offsets (among others) crashes, because LLVM tries to call
458 * memset using a normal pcrel code which is in 32bit memory, while memset isn't.
462 opts.JITExceptionHandling = 1;
464 StringRef cpu_name = sys::getHostCPUName ();
466 // EngineBuilder no longer has a copy assignment operator (?)
467 std::unique_ptr<Module> Owner(unwrap(MP));
468 EngineBuilder b (std::move(Owner));
469 ExecutionEngine *EE = b.setJITMemoryManager (mono_mm).setTargetOptions (opts).setAllocateGVsWithCode (true).setMCPU (cpu_name).create ();
474 MonoJITEventListener *listener = new MonoJITEventListener (emitted_cb);
475 EE->RegisterJITEventListener (listener);
476 mono_ee->listener = listener;
478 FunctionPassManager *fpm = new FunctionPassManager (unwrap (MP));
481 fpm->add(new DataLayoutPass(*EE->getDataLayout()));
483 if (PassList.size() > 0) {
484 /* Use the passes specified by the env variable */
485 /* Only the passes in force_pass_linking () can be used */
486 for (unsigned i = 0; i < PassList.size(); ++i) {
487 const PassInfo *PassInf = PassList[i];
490 if (PassInf->getNormalCtor())
491 P = PassInf->getNormalCtor()();
495 /* Use the same passes used by 'opt' by default, without the ipo passes */
496 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";
500 args = g_strsplit (opts, " ", 1000);
501 for (i = 0; args [i]; i++)
503 llvm::cl::ParseCommandLineOptions (i, args, "");
506 for (unsigned i = 0; i < PassList.size(); ++i) {
507 const PassInfo *PassInf = PassList[i];
510 if (PassInf->getNormalCtor())
511 P = PassInf->getNormalCtor()();
512 g_assert (P->getPassKind () == llvm::PT_Function || P->getPassKind () == llvm::PT_Loop);
517 fpm->add(createInstructionCombiningPass());
518 fpm->add(createReassociatePass());
519 fpm->add(createGVNPass());
520 fpm->add(createCFGSimplificationPass());
530 mono_llvm_dispose_ee (MonoEERef *eeref)
532 MonoEE *mono_ee = (MonoEE*)eeref;
536 //delete mono_ee->mm;
537 delete mono_ee->listener;
541 #else /* MONO_CROSS_COMPILE */
544 mono_llvm_set_unhandled_exception_handler (void)
549 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb, LLVMExecutionEngineRef *ee)
551 g_assert_not_reached ();
556 mono_llvm_optimize_method (MonoEERef eeref, LLVMValueRef method)
561 mono_llvm_dispose_ee (MonoEERef *eeref)
563 g_assert_not_reached ();
568 LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global,
571 g_assert_not_reached ();
575 LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global)
577 g_assert_not_reached ();
581 #endif /* !MONO_CROSS_COMPILE */