Initialize LLVM's ARM target when compiling for it.
[mono.git] / mono / mini / mini-llvm-cpp.cpp
1 //
2 // mini-llvm-cpp.cpp: C++ support classes for the mono LLVM integration
3 //
4 // (C) 2009-2011 Novell, Inc.
5 // Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
6 //
7
8 //
9 // We need to override some stuff in LLVM, but this cannot be done using the C
10 // interface, so we have to use some C++ code here.
11 // The things which we override are:
12 // - the default JIT code manager used by LLVM doesn't allocate memory using
13 //   MAP_32BIT, we require it.
14 // - add some callbacks so we can obtain the size of methods and their exception
15 //   tables.
16 //
17
18 //
19 // Mono's internal header files are not C++ clean, so avoid including them if 
20 // possible
21 //
22
23 #include "config.h"
24 //undef those as llvm defines them on its own config.h as well.
25 #undef PACKAGE_BUGREPORT
26 #undef PACKAGE_NAME
27 #undef PACKAGE_STRING
28 #undef PACKAGE_TARNAME
29 #undef PACKAGE_VERSION
30
31 #include <stdint.h>
32
33 #include <llvm/Support/raw_ostream.h>
34 #include <llvm/PassManager.h>
35 #include <llvm/ExecutionEngine/ExecutionEngine.h>
36 #include <llvm/ExecutionEngine/JITMemoryManager.h>
37 #include <llvm/ExecutionEngine/JITEventListener.h>
38 #include <llvm/Target/TargetOptions.h>
39 #include <llvm/Target/TargetData.h>
40 #include <llvm/Target/TargetRegisterInfo.h>
41 #include <llvm/Analysis/Verifier.h>
42 #include <llvm/Analysis/Passes.h>
43 #include <llvm/Transforms/Scalar.h>
44 #include <llvm/Support/CommandLine.h>
45 #include "llvm/Support/PassNameParser.h"
46 #include "llvm/Support/PrettyStackTrace.h"
47 #include <llvm/CodeGen/Passes.h>
48 #include <llvm/CodeGen/MachineFunctionPass.h>
49 #include <llvm/CodeGen/MachineFunction.h>
50 #include <llvm/CodeGen/MachineFrameInfo.h>
51 //#include <llvm/LinkAllPasses.h>
52
53 #include "llvm-c/Core.h"
54 #include "llvm-c/ExecutionEngine.h"
55
56 #include "mini-llvm-cpp.h"
57
58 #define LLVM_CHECK_VERSION(major,minor) \
59         ((LLVM_MAJOR_VERSION > (major)) ||                                                                      \
60          ((LLVM_MAJOR_VERSION == (major)) && (LLVM_MINOR_VERSION >= (minor))))
61
62 // extern "C" void LLVMInitializeARMTargetInfo();
63 // extern "C" void LLVMInitializeARMTarget ();
64 // extern "C" void LLVMInitializeARMTargetMC ();
65
66 using namespace llvm;
67
68 class MonoJITMemoryManager : public JITMemoryManager
69 {
70 private:
71         JITMemoryManager *mm;
72
73 public:
74         /* Callbacks installed by mono */
75         AllocCodeMemoryCb *alloc_cb;
76         DlSymCb *dlsym_cb;
77
78         MonoJITMemoryManager ();
79         ~MonoJITMemoryManager ();
80
81         void setMemoryWritable (void);
82
83         void setMemoryExecutable (void);
84
85         void AllocateGOT();
86
87     unsigned char *getGOTBase() const {
88                 return mm->getGOTBase ();
89     }
90
91         void setPoisonMemory(bool) {
92         }
93
94         unsigned char *startFunctionBody(const Function *F, 
95                                                                          uintptr_t &ActualSize);
96   
97         unsigned char *allocateStub(const GlobalValue* F, unsigned StubSize,
98                                                                  unsigned Alignment);
99   
100         void endFunctionBody(const Function *F, unsigned char *FunctionStart,
101                                                  unsigned char *FunctionEnd);
102
103         unsigned char *allocateSpace(intptr_t Size, unsigned Alignment);
104
105         uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment);
106   
107         void deallocateMemForFunction(const Function *F);
108   
109         unsigned char*startExceptionTable(const Function* F,
110                                                                           uintptr_t &ActualSize);
111   
112         void endExceptionTable(const Function *F, unsigned char *TableStart,
113                                                    unsigned char *TableEnd, 
114                                                    unsigned char* FrameRegister);
115
116         virtual void deallocateFunctionBody(void*) {
117         }
118
119         virtual void deallocateExceptionTable(void*) {
120         }
121
122         virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
123                                                                                  unsigned SectionID) {
124                 // FIXME:
125                 assert(0);
126                 return NULL;
127         }
128
129         virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
130                                                                                  unsigned SectionID) {
131                 // FIXME:
132                 assert(0);
133                 return NULL;
134         }
135
136         virtual void* getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure) {
137                 if (!strcmp (Name.c_str (), "__bzero")) {
138                         return (void*)bzero;
139                 } else {
140                         void *res;
141                         char *err;
142
143                         err = dlsym_cb (Name.c_str (), &res);
144                         if (err) {
145                                 outs () << "Unable to resolve: " << Name << ": " << err << "\n";
146                                 assert(0);
147                                 return NULL;
148                         }
149                         return res;
150                 }
151         }
152 };
153
154 MonoJITMemoryManager::MonoJITMemoryManager ()
155 {
156         mm = JITMemoryManager::CreateDefaultMemManager ();
157 }
158
159 MonoJITMemoryManager::~MonoJITMemoryManager ()
160 {
161         delete mm;
162 }
163
164 void
165 MonoJITMemoryManager::setMemoryWritable (void)
166 {
167 }
168
169 void
170 MonoJITMemoryManager::setMemoryExecutable (void)
171 {
172 }
173
174 void
175 MonoJITMemoryManager::AllocateGOT()
176 {
177         mm->AllocateGOT ();
178 }
179
180 unsigned char *
181 MonoJITMemoryManager::startFunctionBody(const Function *F, 
182                                         uintptr_t &ActualSize)
183 {
184         // FIXME: This leaks memory
185         if (ActualSize == 0)
186                 ActualSize = 128;
187         return alloc_cb (wrap (F), ActualSize);
188 }
189   
190 unsigned char *
191 MonoJITMemoryManager::allocateStub(const GlobalValue* F, unsigned StubSize,
192                            unsigned Alignment)
193 {
194         return alloc_cb (wrap (F), StubSize);
195 }
196   
197 void
198 MonoJITMemoryManager::endFunctionBody(const Function *F, unsigned char *FunctionStart,
199                                   unsigned char *FunctionEnd)
200 {
201 }
202
203 unsigned char *
204 MonoJITMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment)
205 {
206         return new unsigned char [Size];
207 }
208
209 uint8_t *
210 MonoJITMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment)
211 {
212         return new unsigned char [Size];
213 }
214
215 void
216 MonoJITMemoryManager::deallocateMemForFunction(const Function *F)
217 {
218 }
219   
220 unsigned char*
221 MonoJITMemoryManager::startExceptionTable(const Function* F,
222                                           uintptr_t &ActualSize)
223 {
224         return startFunctionBody(F, ActualSize);
225 }
226   
227 void
228 MonoJITMemoryManager::endExceptionTable(const Function *F, unsigned char *TableStart,
229                                         unsigned char *TableEnd, 
230                                         unsigned char* FrameRegister)
231 {
232 }
233
234 class MonoJITEventListener : public JITEventListener {
235
236 public:
237         FunctionEmittedCb *emitted_cb;
238
239         MonoJITEventListener (FunctionEmittedCb *cb) {
240                 emitted_cb = cb;
241         }
242
243         virtual void NotifyFunctionEmitted(const Function &F,
244                                                                            void *Code, size_t Size,
245                                                                            const EmittedFunctionDetails &Details) {
246                 /*
247                  * X86TargetMachine::setCodeModelForJIT() sets the code model to Large on amd64,
248                  * which means the JIT will generate calls of the form
249                  * mov reg, <imm>
250                  * call *reg
251                  * Our trampoline code can't patch this. Passing CodeModel::Small to createJIT
252                  * doesn't seem to work, we need Default. A discussion is here:
253                  * http://lists.cs.uiuc.edu/pipermail/llvmdev/2009-December/027999.html
254                  * There seems to no way to get the TargeMachine used by an EE either, so we
255                  * install a profiler hook and reset the code model here.
256                  * This should be inside an ifdef, but we can't include our config.h either,
257                  * since its definitions conflict with LLVM's config.h.
258                  *
259                  */
260                 //#if defined(TARGET_X86) || defined(TARGET_AMD64)
261 #ifndef LLVM_MONO_BRANCH
262                 /* The LLVM mono branch contains a workaround, so this is not needed */
263                 if (Details.MF->getTarget ().getCodeModel () == CodeModel::Large) {
264                         Details.MF->getTarget ().setCodeModel (CodeModel::Default);
265                 }
266 #endif
267                 //#endif
268
269                 emitted_cb (wrap (&F), Code, (char*)Code + Size);
270         }
271 };
272
273 static MonoJITMemoryManager *mono_mm;
274 static MonoJITEventListener *mono_event_listener;
275
276 static FunctionPassManager *fpm;
277
278 void
279 mono_llvm_optimize_method (LLVMValueRef method)
280 {
281         verifyFunction (*(unwrap<Function> (method)));
282         fpm->run (*unwrap<Function> (method));
283 }
284
285 void
286 mono_llvm_dump_value (LLVMValueRef value)
287 {
288         /* Same as LLVMDumpValue (), but print to stdout */
289         fflush (stdout);
290         outs () << (*unwrap<Value> (value));
291 }
292
293 /* Missing overload for building an alloca with an alignment */
294 LLVMValueRef
295 mono_llvm_build_alloca (LLVMBuilderRef builder, LLVMTypeRef Ty, 
296                                                 LLVMValueRef ArraySize,
297                                                 int alignment, const char *Name)
298 {
299         return wrap (unwrap (builder)->Insert (new AllocaInst (unwrap (Ty), unwrap (ArraySize), alignment), Name));
300 }
301
302 LLVMValueRef 
303 mono_llvm_build_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
304                                           const char *Name, gboolean is_volatile)
305 {
306         return wrap(unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name));
307 }
308
309 LLVMValueRef 
310 mono_llvm_build_aligned_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
311                                                           const char *Name, gboolean is_volatile, int alignment)
312 {
313         LoadInst *ins;
314
315         ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
316         ins->setAlignment (alignment);
317
318         return wrap(ins);
319 }
320
321 LLVMValueRef 
322 mono_llvm_build_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal,
323                                           gboolean is_volatile)
324 {
325         return wrap(unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile));
326 }
327
328 LLVMValueRef 
329 mono_llvm_build_aligned_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal,
330                                                            gboolean is_volatile, int alignment)
331 {
332         StoreInst *ins;
333
334         ins = unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile);
335         ins->setAlignment (alignment);
336
337         return wrap (ins);
338 }
339
340 LLVMValueRef
341 mono_llvm_build_cmpxchg (LLVMBuilderRef builder, LLVMValueRef ptr, LLVMValueRef cmp, LLVMValueRef val)
342 {
343         AtomicCmpXchgInst *ins;
344
345         ins = unwrap(builder)->CreateAtomicCmpXchg (unwrap(ptr), unwrap (cmp), unwrap (val), SequentiallyConsistent);
346         return wrap (ins);
347 }
348
349 LLVMValueRef
350 mono_llvm_build_atomic_rmw (LLVMBuilderRef builder, AtomicRMWOp op, LLVMValueRef ptr, LLVMValueRef val)
351 {
352         AtomicRMWInst::BinOp aop = AtomicRMWInst::Xchg;
353         AtomicRMWInst *ins;
354
355         switch (op) {
356         case LLVM_ATOMICRMW_OP_XCHG:
357                 aop = AtomicRMWInst::Xchg;
358                 break;
359         case LLVM_ATOMICRMW_OP_ADD:
360                 aop = AtomicRMWInst::Add;
361                 break;
362         default:
363                 g_assert_not_reached ();
364                 break;
365         }
366
367         ins = unwrap (builder)->CreateAtomicRMW (aop, unwrap (ptr), unwrap (val), AcquireRelease);
368         return wrap (ins);
369 }
370
371 LLVMValueRef
372 mono_llvm_build_fence (LLVMBuilderRef builder)
373 {
374         FenceInst *ins;
375
376         ins = unwrap (builder)->CreateFence (AcquireRelease);
377         return wrap (ins);
378 }
379
380 void
381 mono_llvm_replace_uses_of (LLVMValueRef var, LLVMValueRef v)
382 {
383         Value *V = ConstantExpr::getTruncOrBitCast (unwrap<Constant> (v), unwrap (var)->getType ());
384         unwrap (var)->replaceAllUsesWith (V);
385 }
386
387 static cl::list<const PassInfo*, bool, PassNameParser>
388 PassList(cl::desc("Optimizations available:"));
389
390 static void
391 force_pass_linking (void)
392 {
393         // Make sure the rest is linked in, but never executed
394         if (getenv ("FOO") != (char*)-1)
395                 return;
396
397         // This is a subset of the passes in LinkAllPasses.h
398         // The utility passes and the interprocedural passes are commented out
399
400       (void) llvm::createAAEvalPass();
401       (void) llvm::createAggressiveDCEPass();
402       (void) llvm::createAliasAnalysisCounterPass();
403       (void) llvm::createAliasDebugger();
404           /*
405       (void) llvm::createArgumentPromotionPass();
406       (void) llvm::createStructRetPromotionPass();
407           */
408       (void) llvm::createBasicAliasAnalysisPass();
409       (void) llvm::createLibCallAliasAnalysisPass(0);
410       (void) llvm::createScalarEvolutionAliasAnalysisPass();
411       (void) llvm::createBlockPlacementPass();
412       (void) llvm::createBreakCriticalEdgesPass();
413       (void) llvm::createCFGSimplificationPass();
414           /*
415       (void) llvm::createConstantMergePass();
416       (void) llvm::createConstantPropagationPass();
417           */
418           /*
419       (void) llvm::createDeadArgEliminationPass();
420           */
421       (void) llvm::createDeadCodeEliminationPass();
422       (void) llvm::createDeadInstEliminationPass();
423       (void) llvm::createDeadStoreEliminationPass();
424           /*
425       (void) llvm::createDeadTypeEliminationPass();
426       (void) llvm::createDomOnlyPrinterPass();
427       (void) llvm::createDomPrinterPass();
428       (void) llvm::createDomOnlyViewerPass();
429       (void) llvm::createDomViewerPass();
430       (void) llvm::createEdgeProfilerPass();
431       (void) llvm::createOptimalEdgeProfilerPass();
432       (void) llvm::createFunctionInliningPass();
433       (void) llvm::createAlwaysInlinerPass();
434       (void) llvm::createGlobalDCEPass();
435       (void) llvm::createGlobalOptimizerPass();
436       (void) llvm::createGlobalsModRefPass();
437       (void) llvm::createIPConstantPropagationPass();
438       (void) llvm::createIPSCCPPass();
439           */
440       (void) llvm::createIndVarSimplifyPass();
441       (void) llvm::createInstructionCombiningPass();
442           /*
443       (void) llvm::createInternalizePass(false);
444           */
445       (void) llvm::createLCSSAPass();
446       (void) llvm::createLICMPass();
447       (void) llvm::createLazyValueInfoPass();
448       (void) llvm::createLoopDependenceAnalysisPass();
449           /*
450       (void) llvm::createLoopExtractorPass();
451           */
452       (void) llvm::createLoopSimplifyPass();
453       (void) llvm::createLoopStrengthReducePass();
454       (void) llvm::createLoopUnrollPass();
455       (void) llvm::createLoopUnswitchPass();
456       (void) llvm::createLoopRotatePass();
457       (void) llvm::createLowerInvokePass();
458           /*
459       (void) llvm::createLowerSetJmpPass();
460           */
461       (void) llvm::createLowerSwitchPass();
462       (void) llvm::createNoAAPass();
463           /*
464       (void) llvm::createNoProfileInfoPass();
465       (void) llvm::createProfileEstimatorPass();
466       (void) llvm::createProfileVerifierPass();
467       (void) llvm::createProfileLoaderPass();
468           */
469       (void) llvm::createPromoteMemoryToRegisterPass();
470       (void) llvm::createDemoteRegisterToMemoryPass();
471           /*
472       (void) llvm::createPruneEHPass();
473       (void) llvm::createPostDomOnlyPrinterPass();
474       (void) llvm::createPostDomPrinterPass();
475       (void) llvm::createPostDomOnlyViewerPass();
476       (void) llvm::createPostDomViewerPass();
477           */
478       (void) llvm::createReassociatePass();
479       (void) llvm::createSCCPPass();
480       (void) llvm::createScalarReplAggregatesPass();
481       (void) llvm::createSimplifyLibCallsPass();
482           /*
483       (void) llvm::createSingleLoopExtractorPass();
484       (void) llvm::createStripSymbolsPass();
485       (void) llvm::createStripNonDebugSymbolsPass();
486       (void) llvm::createStripDeadDebugInfoPass();
487       (void) llvm::createStripDeadPrototypesPass();
488       (void) llvm::createTailCallEliminationPass();
489       (void) llvm::createTailDuplicationPass();
490       (void) llvm::createJumpThreadingPass();
491           */
492           /*
493       (void) llvm::createUnifyFunctionExitNodesPass();
494           */
495       (void) llvm::createInstCountPass();
496       (void) llvm::createCodeGenPreparePass();
497       (void) llvm::createGVNPass();
498       (void) llvm::createMemCpyOptPass();
499       (void) llvm::createLoopDeletionPass();
500           /*
501       (void) llvm::createPostDomTree();
502       (void) llvm::createPostDomFrontier();
503       (void) llvm::createInstructionNamerPass();
504       (void) llvm::createPartialSpecializationPass();
505       (void) llvm::createFunctionAttrsPass();
506       (void) llvm::createMergeFunctionsPass();
507       (void) llvm::createPrintModulePass(0);
508       (void) llvm::createPrintFunctionPass("", 0);
509       (void) llvm::createDbgInfoPrinterPass();
510       (void) llvm::createModuleDebugInfoPrinterPass();
511       (void) llvm::createPartialInliningPass();
512       (void) llvm::createGEPSplitterPass();
513       (void) llvm::createLintPass();
514           */
515       (void) llvm::createSinkingPass();
516 }
517
518 LLVMExecutionEngineRef
519 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb)
520 {
521   std::string Error;
522
523   force_pass_linking ();
524
525 #ifdef TARGET_ARM
526   LLVMInitializeARMTarget ();
527   LLVMInitializeARMTargetInfo ();
528   LLVMInitializeARMTargetMC ();
529 #else
530   LLVMInitializeX86Target ();
531   LLVMInitializeX86TargetInfo ();
532   LLVMInitializeX86TargetMC ();
533 #endif
534
535   mono_mm = new MonoJITMemoryManager ();
536   mono_mm->alloc_cb = alloc_cb;
537   mono_mm->dlsym_cb = dlsym_cb;
538
539   //JITExceptionHandling = true;
540   // PrettyStackTrace installs signal handlers which trip up libgc
541   DisablePrettyStackTrace = true;
542
543   /*
544    * The Default code model doesn't seem to work on amd64,
545    * test_0_fields_with_big_offsets (among others) crashes, because LLVM tries to call
546    * memset using a normal pcrel code which is in 32bit memory, while memset isn't.
547    */
548
549   TargetOptions opts;
550   opts.JITExceptionHandling = 1;
551
552   EngineBuilder b (unwrap (MP));
553 #ifdef TARGET_AMD64
554   ExecutionEngine *EE = b.setJITMemoryManager (mono_mm).setTargetOptions (opts).setCodeModel (CodeModel::Large).setAllocateGVsWithCode (true).create ();
555 #else
556   ExecutionEngine *EE = b.setJITMemoryManager (mono_mm).setTargetOptions (opts).setAllocateGVsWithCode (true).create ();
557 #endif
558   g_assert (EE);
559
560 #if 0
561   ExecutionEngine *EE = ExecutionEngine::createJIT (unwrap (MP), &Error, mono_mm, CodeGenOpt::Default, true, Reloc::Default, CodeModel::Large);
562   if (!EE) {
563           errs () << "Unable to create LLVM ExecutionEngine: " << Error << "\n";
564           g_assert_not_reached ();
565   }
566 #endif
567
568   EE->InstallExceptionTableRegister (exception_cb);
569   mono_event_listener = new MonoJITEventListener (emitted_cb);
570   EE->RegisterJITEventListener (mono_event_listener);
571
572   fpm = new FunctionPassManager (unwrap (MP));
573
574   fpm->add(new TargetData(*EE->getTargetData()));
575
576   PassRegistry &Registry = *PassRegistry::getPassRegistry();
577   initializeCore(Registry);
578   initializeScalarOpts(Registry);
579   //initializeIPO(Registry);
580   initializeAnalysis(Registry);
581   initializeIPA(Registry);
582   initializeTransformUtils(Registry);
583   initializeInstCombine(Registry);
584   //initializeInstrumentation(Registry);
585   initializeTarget(Registry);
586
587   llvm::cl::ParseEnvironmentOptions("mono", "MONO_LLVM", "", false);
588
589   if (PassList.size() > 0) {
590           /* Use the passes specified by the env variable */
591           /* Only the passes in force_pass_linking () can be used */
592           for (unsigned i = 0; i < PassList.size(); ++i) {
593                   const PassInfo *PassInf = PassList[i];
594                   Pass *P = 0;
595
596                   if (PassInf->getNormalCtor())
597                           P = PassInf->getNormalCtor()();
598                   fpm->add (P);
599           }
600   } else {
601           /* Use the same passes used by 'opt' by default, without the ipo passes */
602           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";
603           char **args;
604           int i;
605
606           args = g_strsplit (opts, " ", 1000);
607           for (i = 0; args [i]; i++)
608                   ;
609           llvm::cl::ParseCommandLineOptions (i, args, "", false);
610           g_strfreev (args);
611
612           for (unsigned i = 0; i < PassList.size(); ++i) {
613                   const PassInfo *PassInf = PassList[i];
614                   Pass *P = 0;
615
616                   if (PassInf->getNormalCtor())
617                           P = PassInf->getNormalCtor()();
618                   fpm->add (P);
619           }
620
621           /*
622           fpm->add(createInstructionCombiningPass());
623           fpm->add(createReassociatePass());
624           fpm->add(createGVNPass());
625           fpm->add(createCFGSimplificationPass());
626           */
627   }
628
629   return wrap(EE);
630 }
631
632 void
633 mono_llvm_dispose_ee (LLVMExecutionEngineRef ee)
634 {
635         delete unwrap (ee);
636
637         delete fpm;
638 }