Merge pull request #2646 from ludovic-henry/fix-processwatch-dispose
[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 #include <stdint.h>
23
24 #include <llvm/Support/raw_ostream.h>
25 #include <llvm/Support/Host.h>
26 #include <llvm/PassManager.h>
27 #include <llvm/ExecutionEngine/ExecutionEngine.h>
28 #include <llvm/ExecutionEngine/JITMemoryManager.h>
29 #include <llvm/ExecutionEngine/JITEventListener.h>
30 #include <llvm/Target/TargetOptions.h>
31 #include <llvm/Target/TargetRegisterInfo.h>
32 #include <llvm/IR/Verifier.h>
33 #include <llvm/Analysis/Passes.h>
34 #include <llvm/Transforms/Scalar.h>
35 #include <llvm/Support/CommandLine.h>
36 #include <llvm/IR/LegacyPassNameParser.h>
37 #include <llvm/Support/PrettyStackTrace.h>
38 #include <llvm/CodeGen/Passes.h>
39 #include <llvm/CodeGen/MachineFunctionPass.h>
40 #include <llvm/CodeGen/MachineFunction.h>
41 #include <llvm/CodeGen/MachineFrameInfo.h>
42 #include <llvm/IR/Function.h>
43 #include <llvm/IR/IRBuilder.h>
44 #include <llvm/IR/Module.h>
45
46 using namespace llvm;
47
48 static void (*unhandled_exception)() = default_mono_llvm_unhandled_exception;
49
50 void
51 mono_llvm_set_unhandled_exception_handler (void)
52 {
53         std::set_terminate (unhandled_exception);
54 }
55
56 class MonoJITMemoryManager : public JITMemoryManager
57 {
58 private:
59         JITMemoryManager *mm;
60
61 public:
62         /* Callbacks installed by mono */
63         AllocCodeMemoryCb *alloc_cb;
64         DlSymCb *dlsym_cb;
65         ExceptionTableCb *exception_cb;
66
67         MonoJITMemoryManager ();
68         ~MonoJITMemoryManager ();
69
70         void setMemoryWritable (void);
71
72         void setMemoryExecutable (void);
73
74         void AllocateGOT();
75
76     unsigned char *getGOTBase() const {
77                 return mm->getGOTBase ();
78     }
79
80         void setPoisonMemory(bool) {
81         }
82
83         unsigned char *startFunctionBody(const Function *F, 
84                                                                          uintptr_t &ActualSize);
85   
86         unsigned char *allocateStub(const GlobalValue* F, unsigned StubSize,
87                                                                  unsigned Alignment);
88   
89         void endFunctionBody(const Function *F, unsigned char *FunctionStart,
90                                                  unsigned char *FunctionEnd);
91
92         unsigned char *allocateSpace(intptr_t Size, unsigned Alignment);
93
94         uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment);
95   
96         void deallocateMemForFunction(const Function *F);
97   
98         unsigned char*startExceptionTable(const Function* F,
99                                                                           uintptr_t &ActualSize);
100   
101         void endExceptionTable(const Function *F, unsigned char *TableStart,
102                                                    unsigned char *TableEnd, 
103                                                    unsigned char* FrameRegister);
104
105         virtual void deallocateFunctionBody(void*) {
106         }
107
108         virtual void deallocateExceptionTable(void*) {
109         }
110
111         virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
112                                                                                  StringRef SectionName) {
113                 // FIXME:
114                 assert(0);
115                 return NULL;
116         }
117
118         virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
119                                                                                  StringRef SectionName, bool IsReadOnly) {
120                 // FIXME:
121                 assert(0);
122                 return NULL;
123         }
124
125         virtual bool applyPermissions(std::string*) {
126                 // FIXME:
127                 assert(0);
128                 return false;
129         }
130
131         virtual bool finalizeMemory(std::string *ErrMsg = 0) {
132                 // FIXME:
133                 assert(0);
134                 return false;
135         }
136
137         virtual void* getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure) {
138                 void *res;
139                 char *err;
140
141                 err = dlsym_cb (Name.c_str (), &res);
142                 if (err) {
143                         outs () << "Unable to resolve: " << Name << ": " << err << "\n";
144                         assert(0);
145                         return NULL;
146                 }
147                 return res;
148         }
149 };
150
151 MonoJITMemoryManager::MonoJITMemoryManager ()
152 {
153         mm = JITMemoryManager::CreateDefaultMemManager ();
154 }
155
156 MonoJITMemoryManager::~MonoJITMemoryManager ()
157 {
158         delete mm;
159 }
160
161 void
162 MonoJITMemoryManager::setMemoryWritable (void)
163 {
164 }
165
166 void
167 MonoJITMemoryManager::setMemoryExecutable (void)
168 {
169 }
170
171 void
172 MonoJITMemoryManager::AllocateGOT()
173 {
174         mm->AllocateGOT ();
175 }
176
177 unsigned char *
178 MonoJITMemoryManager::startFunctionBody(const Function *F, 
179                                         uintptr_t &ActualSize)
180 {
181         // FIXME: This leaks memory
182         if (ActualSize == 0)
183                 ActualSize = 128;
184         return alloc_cb (wrap (F), ActualSize);
185 }
186   
187 unsigned char *
188 MonoJITMemoryManager::allocateStub(const GlobalValue* F, unsigned StubSize,
189                            unsigned Alignment)
190 {
191         return alloc_cb (wrap (F), StubSize);
192 }
193   
194 void
195 MonoJITMemoryManager::endFunctionBody(const Function *F, unsigned char *FunctionStart,
196                                   unsigned char *FunctionEnd)
197 {
198 }
199
200 unsigned char *
201 MonoJITMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment)
202 {
203         return new unsigned char [Size];
204 }
205
206 uint8_t *
207 MonoJITMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment)
208 {
209         return new unsigned char [Size];
210 }
211
212 void
213 MonoJITMemoryManager::deallocateMemForFunction(const Function *F)
214 {
215 }
216   
217 unsigned char*
218 MonoJITMemoryManager::startExceptionTable(const Function* F,
219                                           uintptr_t &ActualSize)
220 {
221         return startFunctionBody(F, ActualSize);
222 }
223   
224 void
225 MonoJITMemoryManager::endExceptionTable(const Function *F, unsigned char *TableStart,
226                                         unsigned char *TableEnd, 
227                                         unsigned char* FrameRegister)
228 {
229         exception_cb (FrameRegister);
230 }
231
232 class MonoJITEventListener : public JITEventListener {
233
234 public:
235         FunctionEmittedCb *emitted_cb;
236
237         MonoJITEventListener (FunctionEmittedCb *cb) {
238                 emitted_cb = cb;
239         }
240
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);
245         }
246 };
247
248 class MonoEE {
249 public:
250         ExecutionEngine *EE;
251         MonoJITMemoryManager *mm;
252         MonoJITEventListener *listener;
253         FunctionPassManager *fpm;
254 };
255
256 void
257 mono_llvm_optimize_method (MonoEERef eeref, LLVMValueRef method)
258 {
259         MonoEE *mono_ee = (MonoEE*)eeref;
260
261         /*
262          * The verifier does some checks on the whole module, leading to quadratic behavior.
263          */
264         //verifyFunction (*(unwrap<Function> (method)));
265         mono_ee->fpm->run (*unwrap<Function> (method));
266 }
267
268 static cl::list<const PassInfo*, bool, PassNameParser>
269 PassList(cl::desc("Optimizations available:"));
270
271 static void
272 force_pass_linking (void)
273 {
274         // Make sure the rest is linked in, but never executed
275         if (g_getenv ("FOO") != (char*)-1)
276                 return;
277
278         // This is a subset of the passes in LinkAllPasses.h
279         // The utility passes and the interprocedural passes are commented out
280
281       (void) llvm::createAAEvalPass();
282       (void) llvm::createAggressiveDCEPass();
283       (void) llvm::createAliasAnalysisCounterPass();
284       (void) llvm::createAliasDebugger();
285           /*
286       (void) llvm::createArgumentPromotionPass();
287       (void) llvm::createStructRetPromotionPass();
288           */
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();
295           /*
296       (void) llvm::createConstantMergePass();
297       (void) llvm::createConstantPropagationPass();
298           */
299           /*
300       (void) llvm::createDeadArgEliminationPass();
301           */
302       (void) llvm::createDeadCodeEliminationPass();
303       (void) llvm::createDeadInstEliminationPass();
304       (void) llvm::createDeadStoreEliminationPass();
305           /*
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();
320           */
321       (void) llvm::createIndVarSimplifyPass();
322       (void) llvm::createInstructionCombiningPass();
323           /*
324       (void) llvm::createInternalizePass(false);
325           */
326       (void) llvm::createLCSSAPass();
327       (void) llvm::createLICMPass();
328       (void) llvm::createLazyValueInfoPass();
329       //(void) llvm::createLoopDependenceAnalysisPass();
330           /*
331       (void) llvm::createLoopExtractorPass();
332           */
333       (void) llvm::createLoopSimplifyPass();
334       (void) llvm::createLoopStrengthReducePass();
335       (void) llvm::createLoopUnrollPass();
336       (void) llvm::createLoopUnswitchPass();
337       (void) llvm::createLoopRotatePass();
338       (void) llvm::createLowerInvokePass();
339           /*
340       (void) llvm::createLowerSetJmpPass();
341           */
342       (void) llvm::createLowerSwitchPass();
343       (void) llvm::createNoAAPass();
344           /*
345       (void) llvm::createNoProfileInfoPass();
346       (void) llvm::createProfileEstimatorPass();
347       (void) llvm::createProfileVerifierPass();
348       (void) llvm::createProfileLoaderPass();
349           */
350       (void) llvm::createPromoteMemoryToRegisterPass();
351       (void) llvm::createDemoteRegisterToMemoryPass();
352           /*
353       (void) llvm::createPruneEHPass();
354       (void) llvm::createPostDomOnlyPrinterPass();
355       (void) llvm::createPostDomPrinterPass();
356       (void) llvm::createPostDomOnlyViewerPass();
357       (void) llvm::createPostDomViewerPass();
358           */
359       (void) llvm::createReassociatePass();
360       (void) llvm::createSCCPPass();
361       (void) llvm::createScalarReplAggregatesPass();
362       //(void) llvm::createSimplifyLibCallsPass();
363           /*
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();
372           */
373           /*
374       (void) llvm::createUnifyFunctionExitNodesPass();
375           */
376       (void) llvm::createInstCountPass();
377       (void) llvm::createCodeGenPreparePass();
378       (void) llvm::createGVNPass();
379       (void) llvm::createMemCpyOptPass();
380       (void) llvm::createLoopDeletionPass();
381           /*
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();
395           */
396       (void) llvm::createSinkingPass();
397 }
398
399 static gboolean inited;
400
401 static void
402 init_llvm (void)
403 {
404         if (inited)
405                 return;
406
407   force_pass_linking ();
408
409 #ifdef TARGET_ARM
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 ();
421 #else
422   #error Unsupported mono-llvm target
423 #endif
424
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);
433
434   llvm::cl::ParseEnvironmentOptions("mono", "MONO_LLVM", "");
435
436   inited = true;
437 }
438
439 MonoEERef
440 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb, LLVMExecutionEngineRef *ee)
441 {
442   std::string Error;
443   MonoEE *mono_ee;
444
445   init_llvm ();
446
447   mono_ee = new MonoEE ();
448
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;
454
455   /*
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.
459    */
460
461   TargetOptions opts;
462   opts.JITExceptionHandling = 1;
463
464   StringRef cpu_name = sys::getHostCPUName ();
465
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 ();
470
471   g_assert (EE);
472   mono_ee->EE = EE;
473
474   MonoJITEventListener *listener = new MonoJITEventListener (emitted_cb);
475   EE->RegisterJITEventListener (listener);
476   mono_ee->listener = listener;
477
478   FunctionPassManager *fpm = new FunctionPassManager (unwrap (MP));
479   mono_ee->fpm = fpm;
480
481   fpm->add(new DataLayoutPass(*EE->getDataLayout()));
482
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];
488                   Pass *P = 0;
489
490                   if (PassInf->getNormalCtor())
491                           P = PassInf->getNormalCtor()();
492                   fpm->add (P);
493           }
494   } else {
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";
497           char **args;
498           int i;
499
500           args = g_strsplit (opts, " ", 1000);
501           for (i = 0; args [i]; i++)
502                   ;
503           llvm::cl::ParseCommandLineOptions (i, args, "");
504           g_strfreev (args);
505
506           for (unsigned i = 0; i < PassList.size(); ++i) {
507                   const PassInfo *PassInf = PassList[i];
508                   Pass *P = 0;
509
510                   if (PassInf->getNormalCtor())
511                           P = PassInf->getNormalCtor()();
512                   g_assert (P->getPassKind () == llvm::PT_Function || P->getPassKind () == llvm::PT_Loop);
513                   fpm->add (P);
514           }
515
516           /*
517           fpm->add(createInstructionCombiningPass());
518           fpm->add(createReassociatePass());
519           fpm->add(createGVNPass());
520           fpm->add(createCFGSimplificationPass());
521           */
522   }
523
524   *ee = wrap (EE);
525
526   return mono_ee;
527 }
528
529 void
530 mono_llvm_dispose_ee (MonoEERef *eeref)
531 {
532         MonoEE *mono_ee = (MonoEE*)eeref;
533
534         delete mono_ee->EE;
535         delete mono_ee->fpm;
536         //delete mono_ee->mm;
537         delete mono_ee->listener;
538         delete mono_ee;
539 }
540
541 #else /* MONO_CROSS_COMPILE */
542
543 void
544 mono_llvm_set_unhandled_exception_handler (void)
545 {
546 }
547
548 MonoEERef
549 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb, LLVMExecutionEngineRef *ee)
550 {
551         g_assert_not_reached ();
552         return NULL;
553 }
554
555 void
556 mono_llvm_optimize_method (MonoEERef eeref, LLVMValueRef method)
557 {
558 }
559
560 void
561 mono_llvm_dispose_ee (MonoEERef *eeref)
562 {
563         g_assert_not_reached ();
564 }
565
566 /* Not linked in */
567 void
568 LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global,
569                                          void* Addr)
570 {
571         g_assert_not_reached ();
572 }
573
574 void*
575 LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global)
576 {
577         g_assert_not_reached ();
578         return NULL;
579 }
580
581 #endif /* !MONO_CROSS_COMPILE */