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_MAJOR_VERSION == 2 && LLVM_MINOR_VERSION >= 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_replace_uses_of (LLVMValueRef var, LLVMValueRef v)
309 Value *V = ConstantExpr::getTruncOrBitCast (unwrap<Constant> (v), unwrap (var)->getType ());
310 unwrap (var)->replaceAllUsesWith (V);
313 static cl::list<const PassInfo*, bool, PassNameParser>
314 PassList(cl::desc("Optimizations available:"));
317 force_pass_linking (void)
319 // Make sure the rest is linked in, but never executed
320 if (getenv ("FOO") != (char*)-1)
323 // This is a subset of the passes in LinkAllPasses.h
324 // The utility passes and the interprocedural passes are commented out
326 (void) llvm::createAAEvalPass();
327 (void) llvm::createAggressiveDCEPass();
328 (void) llvm::createAliasAnalysisCounterPass();
329 (void) llvm::createAliasDebugger();
331 (void) llvm::createArgumentPromotionPass();
332 (void) llvm::createStructRetPromotionPass();
334 (void) llvm::createBasicAliasAnalysisPass();
335 (void) llvm::createLibCallAliasAnalysisPass(0);
336 (void) llvm::createScalarEvolutionAliasAnalysisPass();
337 (void) llvm::createBlockPlacementPass();
338 (void) llvm::createBreakCriticalEdgesPass();
339 (void) llvm::createCFGSimplificationPass();
341 (void) llvm::createConstantMergePass();
342 (void) llvm::createConstantPropagationPass();
345 (void) llvm::createDeadArgEliminationPass();
347 (void) llvm::createDeadCodeEliminationPass();
348 (void) llvm::createDeadInstEliminationPass();
349 (void) llvm::createDeadStoreEliminationPass();
351 (void) llvm::createDeadTypeEliminationPass();
352 (void) llvm::createDomOnlyPrinterPass();
353 (void) llvm::createDomPrinterPass();
354 (void) llvm::createDomOnlyViewerPass();
355 (void) llvm::createDomViewerPass();
356 (void) llvm::createEdgeProfilerPass();
357 (void) llvm::createOptimalEdgeProfilerPass();
358 (void) llvm::createFunctionInliningPass();
359 (void) llvm::createAlwaysInlinerPass();
360 (void) llvm::createGlobalDCEPass();
361 (void) llvm::createGlobalOptimizerPass();
362 (void) llvm::createGlobalsModRefPass();
363 (void) llvm::createIPConstantPropagationPass();
364 (void) llvm::createIPSCCPPass();
366 (void) llvm::createIndVarSimplifyPass();
367 (void) llvm::createInstructionCombiningPass();
369 (void) llvm::createInternalizePass(false);
371 (void) llvm::createLCSSAPass();
372 (void) llvm::createLICMPass();
373 (void) llvm::createLazyValueInfoPass();
374 (void) llvm::createLiveValuesPass();
375 (void) llvm::createLoopDependenceAnalysisPass();
377 (void) llvm::createLoopExtractorPass();
379 (void) llvm::createLoopSimplifyPass();
380 (void) llvm::createLoopStrengthReducePass();
381 (void) llvm::createLoopUnrollPass();
382 (void) llvm::createLoopUnswitchPass();
383 (void) llvm::createLoopRotatePass();
384 (void) llvm::createLowerInvokePass();
386 (void) llvm::createLowerSetJmpPass();
388 (void) llvm::createLowerSwitchPass();
389 (void) llvm::createNoAAPass();
391 (void) llvm::createNoProfileInfoPass();
392 (void) llvm::createProfileEstimatorPass();
393 (void) llvm::createProfileVerifierPass();
394 (void) llvm::createProfileLoaderPass();
396 (void) llvm::createPromoteMemoryToRegisterPass();
397 (void) llvm::createDemoteRegisterToMemoryPass();
399 (void) llvm::createPruneEHPass();
400 (void) llvm::createPostDomOnlyPrinterPass();
401 (void) llvm::createPostDomPrinterPass();
402 (void) llvm::createPostDomOnlyViewerPass();
403 (void) llvm::createPostDomViewerPass();
405 (void) llvm::createReassociatePass();
406 (void) llvm::createSCCPPass();
407 (void) llvm::createScalarReplAggregatesPass();
408 (void) llvm::createSimplifyLibCallsPass();
409 (void) llvm::createSimplifyHalfPowrLibCallsPass();
411 (void) llvm::createSingleLoopExtractorPass();
412 (void) llvm::createStripSymbolsPass();
413 (void) llvm::createStripNonDebugSymbolsPass();
414 (void) llvm::createStripDeadDebugInfoPass();
415 (void) llvm::createStripDeadPrototypesPass();
416 (void) llvm::createTailCallEliminationPass();
417 (void) llvm::createTailDuplicationPass();
418 (void) llvm::createJumpThreadingPass();
421 (void) llvm::createUnifyFunctionExitNodesPass();
423 (void) llvm::createInstCountPass();
424 (void) llvm::createCodeGenPreparePass();
425 (void) llvm::createGVNPass();
426 (void) llvm::createMemCpyOptPass();
427 (void) llvm::createLoopDeletionPass();
429 (void) llvm::createPostDomTree();
430 (void) llvm::createPostDomFrontier();
431 (void) llvm::createInstructionNamerPass();
432 (void) llvm::createPartialSpecializationPass();
433 (void) llvm::createFunctionAttrsPass();
434 (void) llvm::createMergeFunctionsPass();
435 (void) llvm::createPrintModulePass(0);
436 (void) llvm::createPrintFunctionPass("", 0);
437 (void) llvm::createDbgInfoPrinterPass();
438 (void) llvm::createModuleDebugInfoPrinterPass();
439 (void) llvm::createPartialInliningPass();
440 (void) llvm::createGEPSplitterPass();
441 (void) llvm::createLintPass();
443 (void) llvm::createSinkingPass();
446 LLVMExecutionEngineRef
447 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb)
451 force_pass_linking ();
453 LLVMInitializeX86Target ();
454 LLVMInitializeX86TargetInfo ();
456 mono_mm = new MonoJITMemoryManager ();
457 mono_mm->alloc_cb = alloc_cb;
459 #if LLVM_MAJOR_VERSION == 2 && LLVM_MINOR_VERSION < 8
460 DwarfExceptionHandling = true;
462 JITExceptionHandling = true;
464 // PrettyStackTrace installs signal handlers which trip up libgc
465 DisablePrettyStackTrace = true;
467 ExecutionEngine *EE = ExecutionEngine::createJIT (unwrap (MP), &Error, mono_mm, CodeGenOpt::Default);
469 errs () << "Unable to create LLVM ExecutionEngine: " << Error << "\n";
470 g_assert_not_reached ();
472 EE->InstallExceptionTableRegister (exception_cb);
473 mono_event_listener = new MonoJITEventListener (emitted_cb);
474 EE->RegisterJITEventListener (mono_event_listener);
476 fpm = new FunctionPassManager (unwrap (MP));
478 fpm->add(new TargetData(*EE->getTargetData()));
480 #if LLVM_CHECK_VERSION(2, 9)
481 PassRegistry &Registry = *PassRegistry::getPassRegistry();
482 initializeCore(Registry);
483 initializeScalarOpts(Registry);
484 //initializeIPO(Registry);
485 initializeAnalysis(Registry);
486 initializeIPA(Registry);
487 initializeTransformUtils(Registry);
488 initializeInstCombine(Registry);
489 //initializeInstrumentation(Registry);
490 initializeTarget(Registry);
493 llvm::cl::ParseEnvironmentOptions("mono", "MONO_LLVM", "", false);
495 if (PassList.size() > 0) {
496 /* Use the passes specified by the env variable */
497 /* Only the passes in force_pass_linking () can be used */
498 for (unsigned i = 0; i < PassList.size(); ++i) {
499 const PassInfo *PassInf = PassList[i];
502 if (PassInf->getNormalCtor())
503 P = PassInf->getNormalCtor()();
507 /* Use the same passes used by 'opt' by default, without the ipo passes */
508 const char *opts = "-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -basiccg -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loopsimplify -domfrontier -loopsimplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loopsimplify -lcssa -iv-users -indvars -loop-deletion -loopsimplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -gvn -simplifycfg -preverify -domtree -verify";
512 args = g_strsplit (opts, " ", 1000);
513 for (i = 0; args [i]; i++)
515 llvm::cl::ParseCommandLineOptions (i, args, "", false);
518 for (unsigned i = 0; i < PassList.size(); ++i) {
519 const PassInfo *PassInf = PassList[i];
522 if (PassInf->getNormalCtor())
523 P = PassInf->getNormalCtor()();
528 fpm->add(createInstructionCombiningPass());
529 fpm->add(createReassociatePass());
530 fpm->add(createGVNPass());
531 fpm->add(createCFGSimplificationPass());
539 mono_llvm_dispose_ee (LLVMExecutionEngineRef ee)