22ef4b284110184d10872aa1f3e81b71c45dba54
[mono.git] / mono / mini / llvm-jit.cpp
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
8 //
9 // Mono's internal header files are not C++ clean, so avoid including them if 
10 // possible
11 //
12
13 #include "config.h"
14
15 #include <llvm-c/Core.h>
16 #include <llvm-c/ExecutionEngine.h>
17
18 #include "mini-llvm-cpp.h"
19
20 #if !defined(MONO_CROSS_COMPILE) && LLVM_API_VERSION > 100
21
22 /*
23  * LLVM 3.9 uses the OrcJIT APIs
24  */
25
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"
36
37 using namespace llvm;
38 using namespace llvm::orc;
39
40 void
41 mono_llvm_set_unhandled_exception_handler (void)
42 {
43 }
44
45 static gboolean inited;
46
47 static void
48 init_llvm (void)
49 {
50         if (inited)
51                 return;
52
53         InitializeNativeTarget ();
54         InitializeNativeTargetAsmPrinter();
55 }
56
57 MonoEERef
58 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb, LLVMExecutionEngineRef *ee)
59 {
60         init_llvm ();
61
62         return NULL;
63 }
64
65 void
66 mono_llvm_optimize_method (MonoEERef eeref, LLVMValueRef method)
67 {
68         g_assert_not_reached ();
69 }
70
71 void
72 mono_llvm_dispose_ee (MonoEERef *eeref)
73 {
74 }
75
76 void
77 LLVMAddGlobalMapping (LLVMExecutionEngineRef EE, LLVMValueRef Global,
78                                           void* Addr)
79 {
80 }
81
82 void*
83 LLVMGetPointerToGlobal (LLVMExecutionEngineRef EE, LLVMValueRef Global)
84 {
85         g_assert_not_reached ();
86         return NULL;
87 }
88
89 #elif !defined(MONO_CROSS_COMPILE) && LLVM_API_VERSION < 100
90
91 #include <stdint.h>
92
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>
114
115 using namespace llvm;
116
117 static void (*unhandled_exception)() = default_mono_llvm_unhandled_exception;
118
119 void
120 mono_llvm_set_unhandled_exception_handler (void)
121 {
122         std::set_terminate (unhandled_exception);
123 }
124
125 class MonoJITMemoryManager : public JITMemoryManager
126 {
127 private:
128         JITMemoryManager *mm;
129
130 public:
131         /* Callbacks installed by mono */
132         AllocCodeMemoryCb *alloc_cb;
133         DlSymCb *dlsym_cb;
134         ExceptionTableCb *exception_cb;
135
136         MonoJITMemoryManager ();
137         ~MonoJITMemoryManager ();
138
139         void setMemoryWritable (void);
140
141         void setMemoryExecutable (void);
142
143         void AllocateGOT();
144
145     unsigned char *getGOTBase() const {
146                 return mm->getGOTBase ();
147     }
148
149         void setPoisonMemory(bool) {
150         }
151
152         unsigned char *startFunctionBody(const Function *F, 
153                                                                          uintptr_t &ActualSize);
154   
155         unsigned char *allocateStub(const GlobalValue* F, unsigned StubSize,
156                                                                  unsigned Alignment);
157   
158         void endFunctionBody(const Function *F, unsigned char *FunctionStart,
159                                                  unsigned char *FunctionEnd);
160
161         unsigned char *allocateSpace(intptr_t Size, unsigned Alignment);
162
163         uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment);
164   
165         void deallocateMemForFunction(const Function *F);
166   
167         unsigned char*startExceptionTable(const Function* F,
168                                                                           uintptr_t &ActualSize);
169   
170         void endExceptionTable(const Function *F, unsigned char *TableStart,
171                                                    unsigned char *TableEnd, 
172                                                    unsigned char* FrameRegister);
173
174         virtual void deallocateFunctionBody(void*) {
175         }
176
177         virtual void deallocateExceptionTable(void*) {
178         }
179
180         virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
181                                                                                  StringRef SectionName) {
182                 // FIXME:
183                 assert(0);
184                 return NULL;
185         }
186
187         virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
188                                                                                  StringRef SectionName, bool IsReadOnly) {
189                 // FIXME:
190                 assert(0);
191                 return NULL;
192         }
193
194         virtual bool applyPermissions(std::string*) {
195                 // FIXME:
196                 assert(0);
197                 return false;
198         }
199
200         virtual bool finalizeMemory(std::string *ErrMsg = 0) {
201                 // FIXME:
202                 assert(0);
203                 return false;
204         }
205
206         virtual void* getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure) {
207                 void *res;
208                 char *err;
209
210                 err = dlsym_cb (Name.c_str (), &res);
211                 if (err) {
212                         outs () << "Unable to resolve: " << Name << ": " << err << "\n";
213                         assert(0);
214                         return NULL;
215                 }
216                 return res;
217         }
218 };
219
220 MonoJITMemoryManager::MonoJITMemoryManager ()
221 {
222         mm = JITMemoryManager::CreateDefaultMemManager ();
223 }
224
225 MonoJITMemoryManager::~MonoJITMemoryManager ()
226 {
227         delete mm;
228 }
229
230 void
231 MonoJITMemoryManager::setMemoryWritable (void)
232 {
233 }
234
235 void
236 MonoJITMemoryManager::setMemoryExecutable (void)
237 {
238 }
239
240 void
241 MonoJITMemoryManager::AllocateGOT()
242 {
243         mm->AllocateGOT ();
244 }
245
246 unsigned char *
247 MonoJITMemoryManager::startFunctionBody(const Function *F, 
248                                         uintptr_t &ActualSize)
249 {
250         // FIXME: This leaks memory
251         if (ActualSize == 0)
252                 ActualSize = 128;
253         return alloc_cb (wrap (F), ActualSize);
254 }
255   
256 unsigned char *
257 MonoJITMemoryManager::allocateStub(const GlobalValue* F, unsigned StubSize,
258                            unsigned Alignment)
259 {
260         return alloc_cb (wrap (F), StubSize);
261 }
262   
263 void
264 MonoJITMemoryManager::endFunctionBody(const Function *F, unsigned char *FunctionStart,
265                                   unsigned char *FunctionEnd)
266 {
267 }
268
269 unsigned char *
270 MonoJITMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment)
271 {
272         return new unsigned char [Size];
273 }
274
275 uint8_t *
276 MonoJITMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment)
277 {
278         return new unsigned char [Size];
279 }
280
281 void
282 MonoJITMemoryManager::deallocateMemForFunction(const Function *F)
283 {
284 }
285   
286 unsigned char*
287 MonoJITMemoryManager::startExceptionTable(const Function* F,
288                                           uintptr_t &ActualSize)
289 {
290         return startFunctionBody(F, ActualSize);
291 }
292   
293 void
294 MonoJITMemoryManager::endExceptionTable(const Function *F, unsigned char *TableStart,
295                                         unsigned char *TableEnd, 
296                                         unsigned char* FrameRegister)
297 {
298         exception_cb (FrameRegister);
299 }
300
301 class MonoJITEventListener : public JITEventListener {
302
303 public:
304         FunctionEmittedCb *emitted_cb;
305
306         MonoJITEventListener (FunctionEmittedCb *cb) {
307                 emitted_cb = cb;
308         }
309
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);
314         }
315 };
316
317 class MonoEE {
318 public:
319         ExecutionEngine *EE;
320         MonoJITMemoryManager *mm;
321         MonoJITEventListener *listener;
322         FunctionPassManager *fpm;
323 };
324
325 void
326 mono_llvm_optimize_method (MonoEERef eeref, LLVMValueRef method)
327 {
328         MonoEE *mono_ee = (MonoEE*)eeref;
329
330         /*
331          * The verifier does some checks on the whole module, leading to quadratic behavior.
332          */
333         //verifyFunction (*(unwrap<Function> (method)));
334         mono_ee->fpm->run (*unwrap<Function> (method));
335 }
336
337 static cl::list<const PassInfo*, bool, PassNameParser>
338 PassList(cl::desc("Optimizations available:"));
339
340 static void
341 force_pass_linking (void)
342 {
343         // Make sure the rest is linked in, but never executed
344         if (g_getenv ("FOO") != (char*)-1)
345                 return;
346
347         // This is a subset of the passes in LinkAllPasses.h
348         // The utility passes and the interprocedural passes are commented out
349
350       (void) llvm::createAAEvalPass();
351       (void) llvm::createAggressiveDCEPass();
352       (void) llvm::createAliasAnalysisCounterPass();
353       (void) llvm::createAliasDebugger();
354           /*
355       (void) llvm::createArgumentPromotionPass();
356       (void) llvm::createStructRetPromotionPass();
357           */
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();
364           /*
365       (void) llvm::createConstantMergePass();
366       (void) llvm::createConstantPropagationPass();
367           */
368           /*
369       (void) llvm::createDeadArgEliminationPass();
370           */
371       (void) llvm::createDeadCodeEliminationPass();
372       (void) llvm::createDeadInstEliminationPass();
373       (void) llvm::createDeadStoreEliminationPass();
374           /*
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();
389           */
390       (void) llvm::createIndVarSimplifyPass();
391       (void) llvm::createInstructionCombiningPass();
392           /*
393       (void) llvm::createInternalizePass(false);
394           */
395       (void) llvm::createLCSSAPass();
396       (void) llvm::createLICMPass();
397       (void) llvm::createLazyValueInfoPass();
398       //(void) llvm::createLoopDependenceAnalysisPass();
399           /*
400       (void) llvm::createLoopExtractorPass();
401           */
402       (void) llvm::createLoopSimplifyPass();
403       (void) llvm::createLoopStrengthReducePass();
404       (void) llvm::createLoopUnrollPass();
405       (void) llvm::createLoopUnswitchPass();
406       (void) llvm::createLoopRotatePass();
407       (void) llvm::createLowerInvokePass();
408           /*
409       (void) llvm::createLowerSetJmpPass();
410           */
411       (void) llvm::createLowerSwitchPass();
412       (void) llvm::createNoAAPass();
413           /*
414       (void) llvm::createNoProfileInfoPass();
415       (void) llvm::createProfileEstimatorPass();
416       (void) llvm::createProfileVerifierPass();
417       (void) llvm::createProfileLoaderPass();
418           */
419       (void) llvm::createPromoteMemoryToRegisterPass();
420       (void) llvm::createDemoteRegisterToMemoryPass();
421           /*
422       (void) llvm::createPruneEHPass();
423       (void) llvm::createPostDomOnlyPrinterPass();
424       (void) llvm::createPostDomPrinterPass();
425       (void) llvm::createPostDomOnlyViewerPass();
426       (void) llvm::createPostDomViewerPass();
427           */
428       (void) llvm::createReassociatePass();
429       (void) llvm::createSCCPPass();
430       (void) llvm::createScalarReplAggregatesPass();
431       //(void) llvm::createSimplifyLibCallsPass();
432           /*
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();
441           */
442           /*
443       (void) llvm::createUnifyFunctionExitNodesPass();
444           */
445       (void) llvm::createInstCountPass();
446       (void) llvm::createCodeGenPreparePass();
447       (void) llvm::createGVNPass();
448       (void) llvm::createMemCpyOptPass();
449       (void) llvm::createLoopDeletionPass();
450           /*
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();
464           */
465       (void) llvm::createSinkingPass();
466 }
467
468 static gboolean inited;
469
470 static void
471 init_llvm (void)
472 {
473         if (inited)
474                 return;
475
476   force_pass_linking ();
477
478 #ifdef TARGET_ARM
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 ();
490 #else
491   #error Unsupported mono-llvm target
492 #endif
493
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);
502
503   llvm::cl::ParseEnvironmentOptions("mono", "MONO_LLVM", "");
504
505   inited = true;
506 }
507
508 MonoEERef
509 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb, LLVMExecutionEngineRef *ee)
510 {
511   std::string Error;
512   MonoEE *mono_ee;
513
514   init_llvm ();
515
516   mono_ee = new MonoEE ();
517
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;
523
524   /*
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.
528    */
529
530   TargetOptions opts;
531   opts.JITExceptionHandling = 1;
532
533   StringRef cpu_name = sys::getHostCPUName ();
534
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 ();
539
540   g_assert (EE);
541   mono_ee->EE = EE;
542
543   MonoJITEventListener *listener = new MonoJITEventListener (emitted_cb);
544   EE->RegisterJITEventListener (listener);
545   mono_ee->listener = listener;
546
547   FunctionPassManager *fpm = new FunctionPassManager (unwrap (MP));
548   mono_ee->fpm = fpm;
549
550   fpm->add(new DataLayoutPass(*EE->getDataLayout()));
551
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];
557                   Pass *P = 0;
558
559                   if (PassInf->getNormalCtor())
560                           P = PassInf->getNormalCtor()();
561                   fpm->add (P);
562           }
563   } else {
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";
566           char **args;
567           int i;
568
569           args = g_strsplit (opts, " ", 1000);
570           for (i = 0; args [i]; i++)
571                   ;
572           llvm::cl::ParseCommandLineOptions (i, args, "");
573           g_strfreev (args);
574
575           for (unsigned i = 0; i < PassList.size(); ++i) {
576                   const PassInfo *PassInf = PassList[i];
577                   Pass *P = 0;
578
579                   if (PassInf->getNormalCtor())
580                           P = PassInf->getNormalCtor()();
581                   g_assert (P->getPassKind () == llvm::PT_Function || P->getPassKind () == llvm::PT_Loop);
582                   fpm->add (P);
583           }
584
585           /*
586           fpm->add(createInstructionCombiningPass());
587           fpm->add(createReassociatePass());
588           fpm->add(createGVNPass());
589           fpm->add(createCFGSimplificationPass());
590           */
591   }
592
593   *ee = wrap (EE);
594
595   return mono_ee;
596 }
597
598 void
599 mono_llvm_dispose_ee (MonoEERef *eeref)
600 {
601         MonoEE *mono_ee = (MonoEE*)eeref;
602
603         delete mono_ee->EE;
604         delete mono_ee->fpm;
605         //delete mono_ee->mm;
606         delete mono_ee->listener;
607         delete mono_ee;
608 }
609
610 #else /* MONO_CROSS_COMPILE */
611
612 void
613 mono_llvm_set_unhandled_exception_handler (void)
614 {
615 }
616
617 MonoEERef
618 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb, LLVMExecutionEngineRef *ee)
619 {
620         g_assert_not_reached ();
621         return NULL;
622 }
623
624 void
625 mono_llvm_optimize_method (MonoEERef eeref, LLVMValueRef method)
626 {
627         g_assert_not_reached ();
628 }
629
630 void
631 mono_llvm_dispose_ee (MonoEERef *eeref)
632 {
633         g_assert_not_reached ();
634 }
635
636 /* Not linked in */
637 void
638 LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global,
639                                          void* Addr)
640 {
641         g_assert_not_reached ();
642 }
643
644 void*
645 LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global)
646 {
647         g_assert_not_reached ();
648         return NULL;
649 }
650
651 #endif /* !MONO_CROSS_COMPILE */