Merge pull request #1634 from StephenMcConnel/bug-28025
[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
25 #include <stdint.h>
26
27 #include <llvm/Support/raw_ostream.h>
28 #include <llvm/Support/Host.h>
29 #include <llvm/PassManager.h>
30 #include <llvm/ExecutionEngine/ExecutionEngine.h>
31 #include <llvm/ExecutionEngine/JITMemoryManager.h>
32 #include <llvm/ExecutionEngine/JITEventListener.h>
33 #include <llvm/Target/TargetOptions.h>
34 #include <llvm/Target/TargetRegisterInfo.h>
35 #include <llvm/IR/Verifier.h>
36 #include <llvm/Analysis/Passes.h>
37 #include <llvm/Transforms/Scalar.h>
38 #include <llvm/Support/CommandLine.h>
39 #include "llvm/IR/LegacyPassNameParser.h"
40 #include "llvm/Support/PrettyStackTrace.h"
41 #include <llvm/CodeGen/Passes.h>
42 #include <llvm/CodeGen/MachineFunctionPass.h>
43 #include <llvm/CodeGen/MachineFunction.h>
44 #include <llvm/CodeGen/MachineFrameInfo.h>
45 #include <llvm/IR/Function.h>
46 #include <llvm/IR/IRBuilder.h>
47 #include <llvm/IR/Module.h>
48 //#include <llvm/LinkAllPasses.h>
49
50 #include "llvm-c/Core.h"
51 #include "llvm-c/ExecutionEngine.h"
52
53 #include "mini-llvm-cpp.h"
54
55 // extern "C" void LLVMInitializeARMTargetInfo();
56 // extern "C" void LLVMInitializeARMTarget ();
57 // extern "C" void LLVMInitializeARMTargetMC ();
58
59 using namespace llvm;
60
61 #ifndef MONO_CROSS_COMPILE
62
63 class MonoJITMemoryManager : public JITMemoryManager
64 {
65 private:
66         JITMemoryManager *mm;
67
68 public:
69         /* Callbacks installed by mono */
70         AllocCodeMemoryCb *alloc_cb;
71         DlSymCb *dlsym_cb;
72
73         MonoJITMemoryManager ();
74         ~MonoJITMemoryManager ();
75
76         void setMemoryWritable (void);
77
78         void setMemoryExecutable (void);
79
80         void AllocateGOT();
81
82     unsigned char *getGOTBase() const {
83                 return mm->getGOTBase ();
84     }
85
86         void setPoisonMemory(bool) {
87         }
88
89         unsigned char *startFunctionBody(const Function *F, 
90                                                                          uintptr_t &ActualSize);
91   
92         unsigned char *allocateStub(const GlobalValue* F, unsigned StubSize,
93                                                                  unsigned Alignment);
94   
95         void endFunctionBody(const Function *F, unsigned char *FunctionStart,
96                                                  unsigned char *FunctionEnd);
97
98         unsigned char *allocateSpace(intptr_t Size, unsigned Alignment);
99
100         uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment);
101   
102         void deallocateMemForFunction(const Function *F);
103   
104         unsigned char*startExceptionTable(const Function* F,
105                                                                           uintptr_t &ActualSize);
106   
107         void endExceptionTable(const Function *F, unsigned char *TableStart,
108                                                    unsigned char *TableEnd, 
109                                                    unsigned char* FrameRegister);
110
111         virtual void deallocateFunctionBody(void*) {
112         }
113
114         virtual void deallocateExceptionTable(void*) {
115         }
116
117         virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
118                                                                                  StringRef SectionName) {
119                 // FIXME:
120                 assert(0);
121                 return NULL;
122         }
123
124         virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
125                                                                                  StringRef SectionName, bool IsReadOnly) {
126                 // FIXME:
127                 assert(0);
128                 return NULL;
129         }
130
131         virtual bool applyPermissions(std::string*) {
132                 // FIXME:
133                 assert(0);
134                 return false;
135         }
136
137         virtual bool finalizeMemory(std::string *ErrMsg = 0) {
138                 // FIXME:
139                 assert(0);
140                 return false;
141         }
142
143         virtual void* getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure) {
144                 void *res;
145                 char *err;
146
147                 err = dlsym_cb (Name.c_str (), &res);
148                 if (err) {
149                         outs () << "Unable to resolve: " << Name << ": " << err << "\n";
150                         assert(0);
151                         return NULL;
152                 }
153                 return res;
154         }
155 };
156
157 MonoJITMemoryManager::MonoJITMemoryManager ()
158 {
159         mm = JITMemoryManager::CreateDefaultMemManager ();
160 }
161
162 MonoJITMemoryManager::~MonoJITMemoryManager ()
163 {
164         delete mm;
165 }
166
167 void
168 MonoJITMemoryManager::setMemoryWritable (void)
169 {
170 }
171
172 void
173 MonoJITMemoryManager::setMemoryExecutable (void)
174 {
175 }
176
177 void
178 MonoJITMemoryManager::AllocateGOT()
179 {
180         mm->AllocateGOT ();
181 }
182
183 unsigned char *
184 MonoJITMemoryManager::startFunctionBody(const Function *F, 
185                                         uintptr_t &ActualSize)
186 {
187         // FIXME: This leaks memory
188         if (ActualSize == 0)
189                 ActualSize = 128;
190         return alloc_cb (wrap (F), ActualSize);
191 }
192   
193 unsigned char *
194 MonoJITMemoryManager::allocateStub(const GlobalValue* F, unsigned StubSize,
195                            unsigned Alignment)
196 {
197         return alloc_cb (wrap (F), StubSize);
198 }
199   
200 void
201 MonoJITMemoryManager::endFunctionBody(const Function *F, unsigned char *FunctionStart,
202                                   unsigned char *FunctionEnd)
203 {
204 }
205
206 unsigned char *
207 MonoJITMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment)
208 {
209         return new unsigned char [Size];
210 }
211
212 uint8_t *
213 MonoJITMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment)
214 {
215         return new unsigned char [Size];
216 }
217
218 void
219 MonoJITMemoryManager::deallocateMemForFunction(const Function *F)
220 {
221 }
222   
223 unsigned char*
224 MonoJITMemoryManager::startExceptionTable(const Function* F,
225                                           uintptr_t &ActualSize)
226 {
227         return startFunctionBody(F, ActualSize);
228 }
229   
230 void
231 MonoJITMemoryManager::endExceptionTable(const Function *F, unsigned char *TableStart,
232                                         unsigned char *TableEnd, 
233                                         unsigned char* FrameRegister)
234 {
235 }
236
237 #else
238
239 class MonoJITMemoryManager {
240 };
241
242 #endif /* !MONO_CROSS_COMPILE */
243
244 class MonoJITEventListener : public JITEventListener {
245
246 public:
247         FunctionEmittedCb *emitted_cb;
248
249         MonoJITEventListener (FunctionEmittedCb *cb) {
250                 emitted_cb = cb;
251         }
252
253         virtual void NotifyFunctionEmitted(const Function &F,
254                                                                            void *Code, size_t Size,
255                                                                            const EmittedFunctionDetails &Details) {
256                 /*
257                  * X86TargetMachine::setCodeModelForJIT() sets the code model to Large on amd64,
258                  * which means the JIT will generate calls of the form
259                  * mov reg, <imm>
260                  * call *reg
261                  * Our trampoline code can't patch this. Passing CodeModel::Small to createJIT
262                  * doesn't seem to work, we need Default. A discussion is here:
263                  * http://lists.cs.uiuc.edu/pipermail/llvmdev/2009-December/027999.html
264                  * There seems to no way to get the TargeMachine used by an EE either, so we
265                  * install a profiler hook and reset the code model here.
266                  * This should be inside an ifdef, but we can't include our config.h either,
267                  * since its definitions conflict with LLVM's config.h.
268                  * The LLVM mono branch contains a workaround.
269                  */
270                 emitted_cb (wrap (&F), Code, (char*)Code + Size);
271         }
272 };
273
274 class MonoEE {
275 public:
276         ExecutionEngine *EE;
277         MonoJITMemoryManager *mm;
278         MonoJITEventListener *listener;
279         FunctionPassManager *fpm;
280 };
281
282 void
283 mono_llvm_optimize_method (MonoEERef eeref, LLVMValueRef method)
284 {
285         MonoEE *mono_ee = (MonoEE*)eeref;
286
287         /*
288          * The verifier does some checks on the whole module, leading to quadratic behavior.
289          */
290         //verifyFunction (*(unwrap<Function> (method)));
291         mono_ee->fpm->run (*unwrap<Function> (method));
292 }
293
294 void
295 mono_llvm_dump_value (LLVMValueRef value)
296 {
297         /* Same as LLVMDumpValue (), but print to stdout */
298         fflush (stdout);
299         outs () << (*unwrap<Value> (value));
300 }
301
302 /* Missing overload for building an alloca with an alignment */
303 LLVMValueRef
304 mono_llvm_build_alloca (LLVMBuilderRef builder, LLVMTypeRef Ty, 
305                                                 LLVMValueRef ArraySize,
306                                                 int alignment, const char *Name)
307 {
308         return wrap (unwrap (builder)->Insert (new AllocaInst (unwrap (Ty), unwrap (ArraySize), alignment), Name));
309 }
310
311 LLVMValueRef 
312 mono_llvm_build_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
313                                           const char *Name, gboolean is_volatile, BarrierKind barrier)
314 {
315         LoadInst *ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
316
317         switch (barrier) {
318         case LLVM_BARRIER_NONE:
319                 break;
320         case LLVM_BARRIER_ACQ:
321                 ins->setOrdering(Acquire);
322                 break;
323         case LLVM_BARRIER_SEQ:
324                 ins->setOrdering(SequentiallyConsistent);
325                 break;
326         default:
327                 g_assert_not_reached ();
328                 break;
329         }
330
331         return wrap(ins);
332 }
333
334 LLVMValueRef 
335 mono_llvm_build_aligned_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
336                                                           const char *Name, gboolean is_volatile, int alignment)
337 {
338         LoadInst *ins;
339
340         ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
341         ins->setAlignment (alignment);
342
343         return wrap(ins);
344 }
345
346 LLVMValueRef 
347 mono_llvm_build_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal,
348                                           gboolean is_volatile, BarrierKind barrier)
349 {
350         StoreInst *ins = unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile);
351
352         switch (barrier) {
353         case LLVM_BARRIER_NONE:
354                 break;
355         case LLVM_BARRIER_REL:
356                 ins->setOrdering(Release);
357                 break;
358         case LLVM_BARRIER_SEQ:
359                 ins->setOrdering(SequentiallyConsistent);
360                 break;
361         default:
362                 g_assert_not_reached ();
363                 break;
364         }
365
366         return wrap(ins);
367 }
368
369 LLVMValueRef 
370 mono_llvm_build_aligned_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal,
371                                                            gboolean is_volatile, int alignment)
372 {
373         StoreInst *ins;
374
375         ins = unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile);
376         ins->setAlignment (alignment);
377
378         return wrap (ins);
379 }
380
381 LLVMValueRef
382 mono_llvm_build_cmpxchg (LLVMBuilderRef builder, LLVMValueRef ptr, LLVMValueRef cmp, LLVMValueRef val)
383 {
384         AtomicCmpXchgInst *ins;
385
386         ins = unwrap(builder)->CreateAtomicCmpXchg (unwrap(ptr), unwrap (cmp), unwrap (val), SequentiallyConsistent, SequentiallyConsistent);
387         return wrap (ins);
388 }
389
390 LLVMValueRef
391 mono_llvm_build_atomic_rmw (LLVMBuilderRef builder, AtomicRMWOp op, LLVMValueRef ptr, LLVMValueRef val)
392 {
393         AtomicRMWInst::BinOp aop = AtomicRMWInst::Xchg;
394         AtomicRMWInst *ins;
395
396         switch (op) {
397         case LLVM_ATOMICRMW_OP_XCHG:
398                 aop = AtomicRMWInst::Xchg;
399                 break;
400         case LLVM_ATOMICRMW_OP_ADD:
401                 aop = AtomicRMWInst::Add;
402                 break;
403         default:
404                 g_assert_not_reached ();
405                 break;
406         }
407
408         ins = unwrap (builder)->CreateAtomicRMW (aop, unwrap (ptr), unwrap (val), SequentiallyConsistent);
409         return wrap (ins);
410 }
411
412 LLVMValueRef
413 mono_llvm_build_fence (LLVMBuilderRef builder, BarrierKind kind)
414 {
415         FenceInst *ins;
416         AtomicOrdering ordering;
417
418         g_assert (kind != LLVM_BARRIER_NONE);
419
420         switch (kind) {
421         case LLVM_BARRIER_ACQ:
422                 ordering = Acquire;
423                 break;
424         case LLVM_BARRIER_REL:
425                 ordering = Release;
426                 break;
427         case LLVM_BARRIER_SEQ:
428                 ordering = SequentiallyConsistent;
429                 break;
430         default:
431                 g_assert_not_reached ();
432                 break;
433         }
434
435         ins = unwrap (builder)->CreateFence (ordering);
436         return wrap (ins);
437 }
438
439 void
440 mono_llvm_replace_uses_of (LLVMValueRef var, LLVMValueRef v)
441 {
442         Value *V = ConstantExpr::getTruncOrBitCast (unwrap<Constant> (v), unwrap (var)->getType ());
443         unwrap (var)->replaceAllUsesWith (V);
444 }
445
446 static cl::list<const PassInfo*, bool, PassNameParser>
447 PassList(cl::desc("Optimizations available:"));
448
449 static void
450 force_pass_linking (void)
451 {
452         // Make sure the rest is linked in, but never executed
453         if (g_getenv ("FOO") != (char*)-1)
454                 return;
455
456         // This is a subset of the passes in LinkAllPasses.h
457         // The utility passes and the interprocedural passes are commented out
458
459       (void) llvm::createAAEvalPass();
460       (void) llvm::createAggressiveDCEPass();
461       (void) llvm::createAliasAnalysisCounterPass();
462       (void) llvm::createAliasDebugger();
463           /*
464       (void) llvm::createArgumentPromotionPass();
465       (void) llvm::createStructRetPromotionPass();
466           */
467       (void) llvm::createBasicAliasAnalysisPass();
468       (void) llvm::createLibCallAliasAnalysisPass(0);
469       (void) llvm::createScalarEvolutionAliasAnalysisPass();
470       //(void) llvm::createBlockPlacementPass();
471       (void) llvm::createBreakCriticalEdgesPass();
472       (void) llvm::createCFGSimplificationPass();
473           /*
474       (void) llvm::createConstantMergePass();
475       (void) llvm::createConstantPropagationPass();
476           */
477           /*
478       (void) llvm::createDeadArgEliminationPass();
479           */
480       (void) llvm::createDeadCodeEliminationPass();
481       (void) llvm::createDeadInstEliminationPass();
482       (void) llvm::createDeadStoreEliminationPass();
483           /*
484       (void) llvm::createDeadTypeEliminationPass();
485       (void) llvm::createDomOnlyPrinterPass();
486       (void) llvm::createDomPrinterPass();
487       (void) llvm::createDomOnlyViewerPass();
488       (void) llvm::createDomViewerPass();
489       (void) llvm::createEdgeProfilerPass();
490       (void) llvm::createOptimalEdgeProfilerPass();
491       (void) llvm::createFunctionInliningPass();
492       (void) llvm::createAlwaysInlinerPass();
493       (void) llvm::createGlobalDCEPass();
494       (void) llvm::createGlobalOptimizerPass();
495       (void) llvm::createGlobalsModRefPass();
496       (void) llvm::createIPConstantPropagationPass();
497       (void) llvm::createIPSCCPPass();
498           */
499       (void) llvm::createIndVarSimplifyPass();
500       (void) llvm::createInstructionCombiningPass();
501           /*
502       (void) llvm::createInternalizePass(false);
503           */
504       (void) llvm::createLCSSAPass();
505       (void) llvm::createLICMPass();
506       (void) llvm::createLazyValueInfoPass();
507       //(void) llvm::createLoopDependenceAnalysisPass();
508           /*
509       (void) llvm::createLoopExtractorPass();
510           */
511       (void) llvm::createLoopSimplifyPass();
512       (void) llvm::createLoopStrengthReducePass();
513       (void) llvm::createLoopUnrollPass();
514       (void) llvm::createLoopUnswitchPass();
515       (void) llvm::createLoopRotatePass();
516       (void) llvm::createLowerInvokePass();
517           /*
518       (void) llvm::createLowerSetJmpPass();
519           */
520       (void) llvm::createLowerSwitchPass();
521       (void) llvm::createNoAAPass();
522           /*
523       (void) llvm::createNoProfileInfoPass();
524       (void) llvm::createProfileEstimatorPass();
525       (void) llvm::createProfileVerifierPass();
526       (void) llvm::createProfileLoaderPass();
527           */
528       (void) llvm::createPromoteMemoryToRegisterPass();
529       (void) llvm::createDemoteRegisterToMemoryPass();
530           /*
531       (void) llvm::createPruneEHPass();
532       (void) llvm::createPostDomOnlyPrinterPass();
533       (void) llvm::createPostDomPrinterPass();
534       (void) llvm::createPostDomOnlyViewerPass();
535       (void) llvm::createPostDomViewerPass();
536           */
537       (void) llvm::createReassociatePass();
538       (void) llvm::createSCCPPass();
539       (void) llvm::createScalarReplAggregatesPass();
540       //(void) llvm::createSimplifyLibCallsPass();
541           /*
542       (void) llvm::createSingleLoopExtractorPass();
543       (void) llvm::createStripSymbolsPass();
544       (void) llvm::createStripNonDebugSymbolsPass();
545       (void) llvm::createStripDeadDebugInfoPass();
546       (void) llvm::createStripDeadPrototypesPass();
547       (void) llvm::createTailCallEliminationPass();
548       (void) llvm::createTailDuplicationPass();
549       (void) llvm::createJumpThreadingPass();
550           */
551           /*
552       (void) llvm::createUnifyFunctionExitNodesPass();
553           */
554       (void) llvm::createInstCountPass();
555       (void) llvm::createCodeGenPreparePass();
556       (void) llvm::createGVNPass();
557       (void) llvm::createMemCpyOptPass();
558       (void) llvm::createLoopDeletionPass();
559           /*
560       (void) llvm::createPostDomTree();
561       (void) llvm::createPostDomFrontier();
562       (void) llvm::createInstructionNamerPass();
563       (void) llvm::createPartialSpecializationPass();
564       (void) llvm::createFunctionAttrsPass();
565       (void) llvm::createMergeFunctionsPass();
566       (void) llvm::createPrintModulePass(0);
567       (void) llvm::createPrintFunctionPass("", 0);
568       (void) llvm::createDbgInfoPrinterPass();
569       (void) llvm::createModuleDebugInfoPrinterPass();
570       (void) llvm::createPartialInliningPass();
571       (void) llvm::createGEPSplitterPass();
572       (void) llvm::createLintPass();
573           */
574       (void) llvm::createSinkingPass();
575 }
576
577 #ifndef MONO_CROSS_COMPILE
578
579 static gboolean inited;
580
581 static void
582 init_llvm (void)
583 {
584         if (inited)
585                 return;
586
587   force_pass_linking ();
588
589 #ifdef TARGET_ARM
590   LLVMInitializeARMTarget ();
591   LLVMInitializeARMTargetInfo ();
592   LLVMInitializeARMTargetMC ();
593 #else
594   LLVMInitializeX86Target ();
595   LLVMInitializeX86TargetInfo ();
596   LLVMInitializeX86TargetMC ();
597 #endif
598
599   PassRegistry &Registry = *PassRegistry::getPassRegistry();
600   initializeCore(Registry);
601   initializeScalarOpts(Registry);
602   initializeAnalysis(Registry);
603   initializeIPA(Registry);
604   initializeTransformUtils(Registry);
605   initializeInstCombine(Registry);
606   initializeTarget(Registry);
607
608   llvm::cl::ParseEnvironmentOptions("mono", "MONO_LLVM", "");
609
610   inited = true;
611 }
612
613 MonoEERef
614 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb, LLVMExecutionEngineRef *ee)
615 {
616   std::string Error;
617   MonoEE *mono_ee;
618
619   init_llvm ();
620
621   mono_ee = new MonoEE ();
622
623   MonoJITMemoryManager *mono_mm = new MonoJITMemoryManager ();
624   mono_mm->alloc_cb = alloc_cb;
625   mono_mm->dlsym_cb = dlsym_cb;
626   mono_ee->mm = mono_mm;
627
628   /*
629    * The Default code model doesn't seem to work on amd64,
630    * test_0_fields_with_big_offsets (among others) crashes, because LLVM tries to call
631    * memset using a normal pcrel code which is in 32bit memory, while memset isn't.
632    */
633
634   TargetOptions opts;
635   opts.JITExceptionHandling = 1;
636
637   StringRef cpu_name = sys::getHostCPUName ();
638
639   // EngineBuilder no longer has a copy assignment operator (?)
640   std::unique_ptr<Module> Owner(unwrap(MP));
641   EngineBuilder b (std::move(Owner));
642 #ifdef TARGET_AMD64
643   ExecutionEngine *EE = b.setJITMemoryManager (mono_mm).setTargetOptions (opts).setAllocateGVsWithCode (true).setMCPU (cpu_name).setCodeModel (CodeModel::Large).create ();
644 #else
645   ExecutionEngine *EE = b.setJITMemoryManager (mono_mm).setTargetOptions (opts).setAllocateGVsWithCode (true).setMCPU (cpu_name).create ();
646 #endif
647
648   g_assert (EE);
649   mono_ee->EE = EE;
650
651   EE->InstallExceptionTableRegister (exception_cb);
652   MonoJITEventListener *listener = new MonoJITEventListener (emitted_cb);
653   EE->RegisterJITEventListener (listener);
654   mono_ee->listener = listener;
655
656   FunctionPassManager *fpm = new FunctionPassManager (unwrap (MP));
657   mono_ee->fpm = fpm;
658
659   fpm->add(new DataLayoutPass(*EE->getDataLayout()));
660
661   if (PassList.size() > 0) {
662           /* Use the passes specified by the env variable */
663           /* Only the passes in force_pass_linking () can be used */
664           for (unsigned i = 0; i < PassList.size(); ++i) {
665                   const PassInfo *PassInf = PassList[i];
666                   Pass *P = 0;
667
668                   if (PassInf->getNormalCtor())
669                           P = PassInf->getNormalCtor()();
670                   fpm->add (P);
671           }
672   } else {
673           /* Use the same passes used by 'opt' by default, without the ipo passes */
674           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";
675           char **args;
676           int i;
677
678           args = g_strsplit (opts, " ", 1000);
679           for (i = 0; args [i]; i++)
680                   ;
681           llvm::cl::ParseCommandLineOptions (i, args, "");
682           g_strfreev (args);
683
684           for (unsigned i = 0; i < PassList.size(); ++i) {
685                   const PassInfo *PassInf = PassList[i];
686                   Pass *P = 0;
687
688                   if (PassInf->getNormalCtor())
689                           P = PassInf->getNormalCtor()();
690                   g_assert (P->getPassKind () == llvm::PT_Function || P->getPassKind () == llvm::PT_Loop);
691                   fpm->add (P);
692           }
693
694           /*
695           fpm->add(createInstructionCombiningPass());
696           fpm->add(createReassociatePass());
697           fpm->add(createGVNPass());
698           fpm->add(createCFGSimplificationPass());
699           */
700   }
701
702   *ee = wrap (EE);
703
704   return mono_ee;
705 }
706
707 void
708 mono_llvm_dispose_ee (MonoEERef *eeref)
709 {
710         MonoEE *mono_ee = (MonoEE*)eeref;
711
712         delete mono_ee->EE;
713         delete mono_ee->fpm;
714         //delete mono_ee->mm;
715         delete mono_ee->listener;
716         delete mono_ee;
717 }
718
719 #else
720
721 MonoEERef
722 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb, LLVMExecutionEngineRef *ee)
723 {
724         g_assert_not_reached ();
725         return NULL;
726 }
727
728 void
729 mono_llvm_dispose_ee (MonoEERef *eeref)
730 {
731         g_assert_not_reached ();
732 }
733
734 /* Not linked in */
735 void
736 LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global,
737                                          void* Addr)
738 {
739         g_assert_not_reached ();
740 }
741
742 void*
743 LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global)
744 {
745         g_assert_not_reached ();
746         return NULL;
747 }
748
749 #endif /* !MONO_CROSS_COMPILE */