2009-08-15 Zoltan Varga <vargaz@gmail.com>
[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 Novell, Inc.
5 //
6
7 //
8 // We need to override some stuff in LLVM, but this cannot be done using the C
9 // interface, so we have to use some C++ code here.
10 // The things which we override are:
11 // - the default JIT code manager used by LLVM doesn't allocate memory using
12 //   MAP_32BIT, we require it.
13 // - add some callbacks so we can obtain the size of methods and their exception
14 //   tables.
15 //
16
17 //
18 // Mono's internal header files are not C++ clean, so avoid including them if 
19 // possible
20 //
21
22 #include <stdint.h>
23
24 #include <llvm/PassManager.h>
25 #include <llvm/ExecutionEngine/ExecutionEngine.h>
26 #include <llvm/ExecutionEngine/JITMemoryManager.h>
27 #include <llvm/Target/TargetOptions.h>
28 #include <llvm/Target/TargetData.h>
29 #include <llvm/Analysis/Verifier.h>
30 #include <llvm/Transforms/Scalar.h>
31 #include <llvm/Support/CommandLine.h>
32 #include "llvm/Support/PassNameParser.h"
33 #include "llvm/Support/PrettyStackTrace.h"
34 #include <llvm/CodeGen/Passes.h>
35 #include <llvm/CodeGen/MachineFunctionPass.h>
36 //#include <llvm/LinkAllPasses.h>
37
38 #include "llvm-c/Core.h"
39 #include "llvm-c/ExecutionEngine.h"
40
41 #include "mini-llvm-cpp.h"
42
43 extern "C" void LLVMInitializeX86TargetInfo();
44
45 using namespace llvm;
46
47 class MonoJITMemoryManager : public JITMemoryManager
48 {
49 private:
50         JITMemoryManager *mm;
51
52 public:
53         /* Callbacks installed by mono */
54         AllocCodeMemoryCb *alloc_cb;
55         FunctionEmittedCb *emitted_cb;
56
57         MonoJITMemoryManager ();
58         ~MonoJITMemoryManager ();
59
60         void setMemoryWritable (void);
61
62         void setMemoryExecutable (void);
63
64         void AllocateGOT();
65
66     unsigned char *getGOTBase() const {
67                 return mm->getGOTBase ();
68     }
69     
70     void *getDlsymTable() const {
71                 return mm->getDlsymTable ();
72     }
73
74         void setPoisonMemory(bool) {
75         }
76       
77         void SetDlsymTable(void *ptr);
78   
79         unsigned char *startFunctionBody(const Function *F, 
80                                                                          uintptr_t &ActualSize);
81   
82         unsigned char *allocateStub(const GlobalValue* F, unsigned StubSize,
83                                                                  unsigned Alignment);
84   
85         void endFunctionBody(const Function *F, unsigned char *FunctionStart,
86                                                  unsigned char *FunctionEnd);
87
88         unsigned char *allocateSpace(intptr_t Size, unsigned Alignment);
89
90         uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment);
91   
92         void deallocateMemForFunction(const Function *F);
93   
94         unsigned char*startExceptionTable(const Function* F,
95                                                                           uintptr_t &ActualSize);
96   
97         void endExceptionTable(const Function *F, unsigned char *TableStart,
98                                                    unsigned char *TableEnd, 
99                                                    unsigned char* FrameRegister);
100 };
101
102 MonoJITMemoryManager::MonoJITMemoryManager ()
103 {
104         SizeRequired = true;
105         mm = JITMemoryManager::CreateDefaultMemManager ();
106 }
107
108 MonoJITMemoryManager::~MonoJITMemoryManager ()
109 {
110 }
111
112 void
113 MonoJITMemoryManager::setMemoryWritable (void)
114 {
115 }
116
117 void
118 MonoJITMemoryManager::setMemoryExecutable (void)
119 {
120 }
121
122 void
123 MonoJITMemoryManager::AllocateGOT()
124 {
125         mm->AllocateGOT ();
126 }
127   
128 void
129 MonoJITMemoryManager::SetDlsymTable(void *ptr)
130 {
131         mm->SetDlsymTable (ptr);
132 }
133   
134 unsigned char *
135 MonoJITMemoryManager::startFunctionBody(const Function *F, 
136                                         uintptr_t &ActualSize)
137 {
138         return alloc_cb (wrap (F), ActualSize);
139 }
140   
141 unsigned char *
142 MonoJITMemoryManager::allocateStub(const GlobalValue* F, unsigned StubSize,
143                            unsigned Alignment)
144 {
145         return alloc_cb (wrap (F), StubSize);
146 }
147   
148 void
149 MonoJITMemoryManager::endFunctionBody(const Function *F, unsigned char *FunctionStart,
150                                   unsigned char *FunctionEnd)
151 {
152         emitted_cb (wrap (F), FunctionStart, FunctionEnd);
153 }
154
155 unsigned char *
156 MonoJITMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment)
157 {
158         return new unsigned char [Size];
159 }
160
161 uint8_t *
162 MonoJITMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment)
163 {
164         return new unsigned char [Size];
165 }
166
167 void
168 MonoJITMemoryManager::deallocateMemForFunction(const Function *F)
169 {
170 }
171   
172 unsigned char*
173 MonoJITMemoryManager::startExceptionTable(const Function* F,
174                                           uintptr_t &ActualSize)
175 {
176         return alloc_cb (wrap (F), ActualSize);
177 }
178   
179 void
180 MonoJITMemoryManager::endExceptionTable(const Function *F, unsigned char *TableStart,
181                                         unsigned char *TableEnd, 
182                                         unsigned char* FrameRegister)
183 {
184 }
185
186 static MonoJITMemoryManager *mono_mm;
187
188 static FunctionPassManager *fpm;
189
190 static LLVMContext ctx;
191
192 void
193 mono_llvm_optimize_method (LLVMValueRef method)
194 {
195         verifyFunction (*(unwrap<Function> (method)));
196         fpm->run (*unwrap<Function> (method));
197 }
198
199 void
200 mono_llvm_dump_value (LLVMValueRef value)
201 {
202         /* Same as LLVMDumpValue (), but print to stdout */
203         cout << (*unwrap<Value> (value));
204 }
205
206 /* Missing overload for building an alloca with an alignment */
207 LLVMValueRef
208 mono_llvm_build_alloca (LLVMBuilderRef builder, LLVMTypeRef Ty, 
209                                                 LLVMValueRef ArraySize,
210                                                 int alignment, const char *Name)
211 {
212         return wrap (unwrap (builder)->Insert (new AllocaInst (unwrap (Ty), unwrap (ArraySize), alignment), Name));
213 }
214
215 LLVMValueRef 
216 mono_llvm_build_volatile_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
217                                                            const char *Name)
218 {
219         return wrap(unwrap(builder)->CreateLoad(unwrap(PointerVal), true, Name));
220 }
221
222 static cl::list<const PassInfo*, bool, PassNameParser>
223 PassList(cl::desc("Optimizations available:"));
224
225 LLVMExecutionEngineRef
226 mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb)
227 {
228   std::string Error;
229
230   LLVMInitializeX86Target ();
231   LLVMInitializeX86TargetInfo ();
232
233   llvm::cl::ParseEnvironmentOptions("mono", "MONO_LLVM", "", false);
234
235   mono_mm = new MonoJITMemoryManager ();
236   mono_mm->alloc_cb = alloc_cb;
237   mono_mm->emitted_cb = emitted_cb;
238
239   ExceptionHandling = true;
240   // PrettyStackTrace installs signal handlers which trip up libgc
241   DisablePrettyStackTrace = true;
242
243   ExecutionEngine *EE = ExecutionEngine::createJIT (unwrap (MP), &Error, mono_mm, CodeGenOpt::Default);
244   if (!EE) {
245           cerr << "Unable to create LLVM ExecutionEngine: " << Error << "\n";
246           g_assert_not_reached ();
247   }
248   EE->InstallExceptionTableRegister (exception_cb);
249
250   fpm = new FunctionPassManager (unwrap (MP));
251
252   fpm->add(new TargetData(*EE->getTargetData()));
253   /* Add a random set of passes */
254   /* Make this run-time configurable */
255   fpm->add(createInstructionCombiningPass());
256   fpm->add(createReassociatePass());
257   fpm->add(createGVNPass());
258   fpm->add(createCFGSimplificationPass());
259
260   /* Add passes specified by the env variable */
261   /* FIXME: This can only add passes which are linked in, thus are already used */
262   for (unsigned i = 0; i < PassList.size(); ++i) {
263       const PassInfo *PassInf = PassList[i];
264       Pass *P = 0;
265
266       if (PassInf->getNormalCtor())
267                   P = PassInf->getNormalCtor()();
268           if (dynamic_cast<MachineFunctionPass*>(P) != 0) {
269                   cerr << PassInf->getPassName () << " is a machine function pass.\n";
270           } else {
271                   fpm->add (P);
272           }
273   }
274
275   return wrap(EE);
276 }
277
278 void
279 mono_llvm_dispose_ee (LLVMExecutionEngineRef ee)
280 {
281         delete unwrap (ee);
282
283         delete fpm;
284 }