2 // mini-llvm-cpp.cpp: C++ support classes for the mono LLVM integration
4 // (C) 2009 Novell, Inc.
8 // We need to override some stuff in LLVM, but this cannot be done using the C
9 // interface, so we have to use some C++ code here.
10 // The things which we override are:
11 // - the default JIT code manager used by LLVM doesn't allocate memory using
12 // MAP_32BIT, we require it.
13 // - add some callbacks so we can obtain the size of methods and their exception
18 // Mono's internal header files are not C++ clean, so avoid including them if
24 #include <llvm/Support/raw_ostream.h>
25 #include <llvm/PassManager.h>
26 #include <llvm/ExecutionEngine/ExecutionEngine.h>
27 #include <llvm/ExecutionEngine/JITMemoryManager.h>
28 #include <llvm/ExecutionEngine/JITEventListener.h>
29 #include <llvm/Target/TargetOptions.h>
30 #include <llvm/Target/TargetData.h>
31 #include <llvm/Target/TargetRegisterInfo.h>
32 #include <llvm/Analysis/Verifier.h>
33 #include <llvm/Transforms/Scalar.h>
34 #include <llvm/Support/CommandLine.h>
35 #include "llvm/Support/PassNameParser.h"
36 #include "llvm/Support/PrettyStackTrace.h"
37 #include <llvm/CodeGen/Passes.h>
38 #include <llvm/CodeGen/MachineFunctionPass.h>
39 #include <llvm/CodeGen/MachineFunction.h>
40 #include <llvm/CodeGen/MachineFrameInfo.h>
41 #include <llvm/Support/StandardPasses.h>
42 //#include <llvm/LinkAllPasses.h>
44 #include "llvm-c/Core.h"
45 #include "llvm-c/ExecutionEngine.h"
47 #include "mini-llvm-cpp.h"
49 #define LLVM_CHECK_VERSION(major,minor) \
50 ((LLVM_MAJOR_VERSION > (major)) || \
51 ((LLVM_MAJOR_VERSION == (major)) && (LLVM_MINOR_VERSION >= (minor))))
53 extern "C" void LLVMInitializeX86TargetInfo();
57 class MonoJITMemoryManager : public JITMemoryManager
63 /* Callbacks installed by mono */
64 AllocCodeMemoryCb *alloc_cb;
66 MonoJITMemoryManager ();
67 ~MonoJITMemoryManager ();
69 void setMemoryWritable (void);
71 void setMemoryExecutable (void);
75 unsigned char *getGOTBase() const {
76 return mm->getGOTBase ();
79 #if LLVM_MAJOR_VERSION == 2 && LLVM_MINOR_VERSION < 7
80 void *getDlsymTable() const {
81 return mm->getDlsymTable ();
84 void SetDlsymTable(void *ptr);
87 void setPoisonMemory(bool) {
90 unsigned char *startFunctionBody(const Function *F,
91 uintptr_t &ActualSize);
93 unsigned char *allocateStub(const GlobalValue* F, unsigned StubSize,
96 void endFunctionBody(const Function *F, unsigned char *FunctionStart,
97 unsigned char *FunctionEnd);
99 unsigned char *allocateSpace(intptr_t Size, unsigned Alignment);
101 uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment);
103 void deallocateMemForFunction(const Function *F);
105 unsigned char*startExceptionTable(const Function* F,
106 uintptr_t &ActualSize);
108 void endExceptionTable(const Function *F, unsigned char *TableStart,
109 unsigned char *TableEnd,
110 unsigned char* FrameRegister);
112 #if LLVM_CHECK_VERSION(2, 7)
113 virtual void deallocateFunctionBody(void*) {
116 virtual void deallocateExceptionTable(void*) {
121 MonoJITMemoryManager::MonoJITMemoryManager ()
123 #if LLVM_MAJOR_VERSION == 2 && LLVM_MINOR_VERSION <= 7
126 mm = JITMemoryManager::CreateDefaultMemManager ();
129 MonoJITMemoryManager::~MonoJITMemoryManager ()
135 MonoJITMemoryManager::setMemoryWritable (void)
140 MonoJITMemoryManager::setMemoryExecutable (void)
145 MonoJITMemoryManager::AllocateGOT()
150 #if LLVM_MAJOR_VERSION == 2 && LLVM_MINOR_VERSION < 7
152 MonoJITMemoryManager::SetDlsymTable(void *ptr)
154 mm->SetDlsymTable (ptr);
159 MonoJITMemoryManager::startFunctionBody(const Function *F,
160 uintptr_t &ActualSize)
162 // FIXME: This leaks memory
165 return alloc_cb (wrap (F), ActualSize);
169 MonoJITMemoryManager::allocateStub(const GlobalValue* F, unsigned StubSize,
172 return alloc_cb (wrap (F), StubSize);
176 MonoJITMemoryManager::endFunctionBody(const Function *F, unsigned char *FunctionStart,
177 unsigned char *FunctionEnd)
182 MonoJITMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment)
184 return new unsigned char [Size];
188 MonoJITMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment)
190 return new unsigned char [Size];
194 MonoJITMemoryManager::deallocateMemForFunction(const Function *F)
199 MonoJITMemoryManager::startExceptionTable(const Function* F,
200 uintptr_t &ActualSize)
202 return startFunctionBody(F, ActualSize);
206 MonoJITMemoryManager::endExceptionTable(const Function *F, unsigned char *TableStart,
207 unsigned char *TableEnd,
208 unsigned char* FrameRegister)
212 class MonoJITEventListener : public JITEventListener {
215 FunctionEmittedCb *emitted_cb;
217 MonoJITEventListener (FunctionEmittedCb *cb) {
221 virtual void NotifyFunctionEmitted(const Function &F,
222 void *Code, size_t Size,
223 const EmittedFunctionDetails &Details) {
225 * X86TargetMachine::setCodeModelForJIT() sets the code model to Large on amd64,
226 * which means the JIT will generate calls of the form
229 * Our trampoline code can't patch this. Passing CodeModel::Small to createJIT
230 * doesn't seem to work, we need Default. A discussion is here:
231 * http://lists.cs.uiuc.edu/pipermail/llvmdev/2009-December/027999.html
232 * There seems to no way to get the TargeMachine used by an EE either, so we
233 * install a profiler hook and reset the code model here.
234 * This should be inside an ifdef, but we can't include our config.h either,
235 * since its definitions conflict with LLVM's config.h.
238 //#if defined(TARGET_X86) || defined(TARGET_AMD64)
239 #ifndef LLVM_MONO_BRANCH
240 /* The LLVM mono branch contains a workaround, so this is not needed */
241 if (Details.MF->getTarget ().getCodeModel () == CodeModel::Large) {
242 Details.MF->getTarget ().setCodeModel (CodeModel::Default);
247 emitted_cb (wrap (&F), Code, (char*)Code + Size);
251 static MonoJITMemoryManager *mono_mm;
252 static MonoJITEventListener *mono_event_listener;
254 static FunctionPassManager *fpm;
257 mono_llvm_optimize_method (LLVMValueRef method)
259 verifyFunction (*(unwrap<Function> (method)));
260 fpm->run (*unwrap<Function> (method));
264 mono_llvm_dump_value (LLVMValueRef value)
266 /* Same as LLVMDumpValue (), but print to stdout */
268 outs () << (*unwrap<Value> (value));
271 /* Missing overload for building an alloca with an alignment */
273 mono_llvm_build_alloca (LLVMBuilderRef builder, LLVMTypeRef Ty,
274 LLVMValueRef ArraySize,
275 int alignment, const char *Name)
277 return wrap (unwrap (builder)->Insert (new AllocaInst (unwrap (Ty), unwrap (ArraySize), alignment), Name));
281 mono_llvm_build_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
282 const char *Name, gboolean is_volatile)
284 return wrap(unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name));
288 mono_llvm_build_aligned_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
289 const char *Name, gboolean is_volatile, int alignment)
293 ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
294 ins->setAlignment (alignment);
300 mono_llvm_build_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal,
301 gboolean is_volatile)
303 return wrap(unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile));
307 mono_llvm_build_aligned_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal,
308 gboolean is_volatile, int alignment)
312 ins = unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile);
313 ins->setAlignment (alignment);
319 mono_llvm_replace_uses_of (LLVMValueRef var, LLVMValueRef v)
321 Value *V = ConstantExpr::getTruncOrBitCast (unwrap<Constant> (v), unwrap (var)->getType ());
322 unwrap (var)->replaceAllUsesWith (V);
325 static cl::list<const PassInfo*, bool, PassNameParser>
326 PassList(cl::desc("Optimizations available:"));
329 force_pass_linking (void)
331 // Make sure the rest is linked in, but never executed
332 if (getenv ("FOO") != (char*)-1)
335 // This is a subset of the passes in LinkAllPasses.h
336 // The utility passes and the interprocedural passes are commented out
338 (void) llvm::createAAEvalPass();
339 (void) llvm::createAggressiveDCEPass();
340 (void) llvm::createAliasAnalysisCounterPass();
341 (void) llvm::createAliasDebugger();
343 (void) llvm::createArgumentPromotionPass();
344 (void) llvm::createStructRetPromotionPass();
346 (void) llvm::createBasicAliasAnalysisPass();
347 (void) llvm::createLibCallAliasAnalysisPass(0);
348 (void) llvm::createScalarEvolutionAliasAnalysisPass();
349 (void) llvm::createBlockPlacementPass();
350 (void) llvm::createBreakCriticalEdgesPass();
351 (void) llvm::createCFGSimplificationPass();
353 (void) llvm::createConstantMergePass();
354 (void) llvm::createConstantPropagationPass();
357 (void) llvm::createDeadArgEliminationPass();
359 (void) llvm::createDeadCodeEliminationPass();
360 (void) llvm::createDeadInstEliminationPass();
361 (void) llvm::createDeadStoreEliminationPass();
363 (void) llvm::createDeadTypeEliminationPass();
364 (void) llvm::createDomOnlyPrinterPass();
365 (void) llvm::createDomPrinterPass();
366 (void) llvm::createDomOnlyViewerPass();
367 (void) llvm::createDomViewerPass();
368 (void) llvm::createEdgeProfilerPass();
369 (void) llvm::createOptimalEdgeProfilerPass();
370 (void) llvm::createFunctionInliningPass();
371 (void) llvm::createAlwaysInlinerPass();
372 (void) llvm::createGlobalDCEPass();
373 (void) llvm::createGlobalOptimizerPass();
374 (void) llvm::createGlobalsModRefPass();
375 (void) llvm::createIPConstantPropagationPass();
376 (void) llvm::createIPSCCPPass();
378 (void) llvm::createIndVarSimplifyPass();
379 (void) llvm::createInstructionCombiningPass();
381 (void) llvm::createInternalizePass(false);
383 (void) llvm::createLCSSAPass();
384 (void) llvm::createLICMPass();
385 (void) llvm::createLazyValueInfoPass();
386 (void) llvm::createLoopDependenceAnalysisPass();
388 (void) llvm::createLoopExtractorPass();
390 (void) llvm::createLoopSimplifyPass();
391 (void) llvm::createLoopStrengthReducePass();
392 (void) llvm::createLoopUnrollPass();
393 (void) llvm::createLoopUnswitchPass();
394 (void) llvm::createLoopRotatePass();
395 (void) llvm::createLowerInvokePass();
397 (void) llvm::createLowerSetJmpPass();
399 (void) llvm::createLowerSwitchPass();
400 (void) llvm::createNoAAPass();
402 (void) llvm::createNoProfileInfoPass();
403 (void) llvm::createProfileEstimatorPass();
404 (void) llvm::createProfileVerifierPass();
405 (void) llvm::createProfileLoaderPass();
407 (void) llvm::createPromoteMemoryToRegisterPass();
408 (void) llvm::createDemoteRegisterToMemoryPass();
410 (void) llvm::createPruneEHPass();
411 (void) llvm::createPostDomOnlyPrinterPass();
412 (void) llvm::createPostDomPrinterPass();
413 (void) llvm::createPostDomOnlyViewerPass();
414 (void) llvm::createPostDomViewerPass();
416 (void) llvm::createReassociatePass();
417 (void) llvm::createSCCPPass();
418 (void) llvm::createScalarReplAggregatesPass();
419 (void) llvm::createSimplifyLibCallsPass();
421 (void) llvm::createSingleLoopExtractorPass();
422 (void) llvm::createStripSymbolsPass();
423 (void) llvm::createStripNonDebugSymbolsPass();
424 (void) llvm::createStripDeadDebugInfoPass();
425 (void) llvm::createStripDeadPrototypesPass();
426 (void) llvm::createTailCallEliminationPass();
427 (void) llvm::createTailDuplicationPass();
428 (void) llvm::createJumpThreadingPass();
431 (void) llvm::createUnifyFunctionExitNodesPass();
433 (void) llvm::createInstCountPass();
434 (void) llvm::createCodeGenPreparePass();
435 (void) llvm::createGVNPass();
436 (void) llvm::createMemCpyOptPass();
437 (void) llvm::createLoopDeletionPass();
439 (void) llvm::createPostDomTree();
440 (void) llvm::createPostDomFrontier();
441 (void) llvm::createInstructionNamerPass();
442 (void) llvm::createPartialSpecializationPass();
443 (void) llvm::createFunctionAttrsPass();
444 (void) llvm::createMergeFunctionsPass();
445 (void) llvm::createPrintModulePass(0);
446 (void) llvm::createPrintFunctionPass("", 0);
447 (void) llvm::createDbgInfoPrinterPass();
448 (void) llvm::createModuleDebugInfoPrinterPass();
449 (void) llvm::createPartialInliningPass();
450 (void) llvm::createGEPSplitterPass();
451 (void) llvm::createLintPass();
453 (void) llvm::createSinkingPass();
456 LLVMExecutionEngineRef
457 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb)
461 force_pass_linking ();
463 LLVMInitializeX86Target ();
464 LLVMInitializeX86TargetInfo ();
466 mono_mm = new MonoJITMemoryManager ();
467 mono_mm->alloc_cb = alloc_cb;
469 #if LLVM_MAJOR_VERSION == 2 && LLVM_MINOR_VERSION < 8
470 DwarfExceptionHandling = true;
472 JITExceptionHandling = true;
474 // PrettyStackTrace installs signal handlers which trip up libgc
475 DisablePrettyStackTrace = true;
477 ExecutionEngine *EE = ExecutionEngine::createJIT (unwrap (MP), &Error, mono_mm, CodeGenOpt::Default);
479 errs () << "Unable to create LLVM ExecutionEngine: " << Error << "\n";
480 g_assert_not_reached ();
482 EE->InstallExceptionTableRegister (exception_cb);
483 mono_event_listener = new MonoJITEventListener (emitted_cb);
484 EE->RegisterJITEventListener (mono_event_listener);
486 fpm = new FunctionPassManager (unwrap (MP));
488 fpm->add(new TargetData(*EE->getTargetData()));
490 #if LLVM_CHECK_VERSION(2, 9)
491 PassRegistry &Registry = *PassRegistry::getPassRegistry();
492 initializeCore(Registry);
493 initializeScalarOpts(Registry);
494 //initializeIPO(Registry);
495 initializeAnalysis(Registry);
496 initializeIPA(Registry);
497 initializeTransformUtils(Registry);
498 initializeInstCombine(Registry);
499 //initializeInstrumentation(Registry);
500 initializeTarget(Registry);
503 llvm::cl::ParseEnvironmentOptions("mono", "MONO_LLVM", "", false);
505 if (PassList.size() > 0) {
506 /* Use the passes specified by the env variable */
507 /* Only the passes in force_pass_linking () can be used */
508 for (unsigned i = 0; i < PassList.size(); ++i) {
509 const PassInfo *PassInf = PassList[i];
512 if (PassInf->getNormalCtor())
513 P = PassInf->getNormalCtor()();
517 /* Use the same passes used by 'opt' by default, without the ipo passes */
518 const char *opts = "-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -basiccg -domtree -domfrontier -scalarrepl -simplify-libcalls -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 -preverify -domtree -verify";
522 args = g_strsplit (opts, " ", 1000);
523 for (i = 0; args [i]; i++)
525 llvm::cl::ParseCommandLineOptions (i, args, "", false);
528 for (unsigned i = 0; i < PassList.size(); ++i) {
529 const PassInfo *PassInf = PassList[i];
532 if (PassInf->getNormalCtor())
533 P = PassInf->getNormalCtor()();
538 fpm->add(createInstructionCombiningPass());
539 fpm->add(createReassociatePass());
540 fpm->add(createGVNPass());
541 fpm->add(createCFGSimplificationPass());
549 mono_llvm_dispose_ee (LLVMExecutionEngineRef ee)