[llvm] Add support for building with more recent versions of the mono llvm branch...
[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 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
7 //
8
9 //
10 // We need to override some stuff in LLVM, but this cannot be done using the C
11 // interface, so we have to use some C++ code here.
12 // The things which we override are:
13 // - the default JIT code manager used by LLVM doesn't allocate memory using
14 //   MAP_32BIT, we require it.
15 // - add some callbacks so we can obtain the size of methods and their exception
16 //   tables.
17 //
18
19 //
20 // Mono's internal header files are not C++ clean, so avoid including them if 
21 // possible
22 //
23
24 #include "config.h"
25
26 #include <stdint.h>
27
28 #include <llvm/Support/raw_ostream.h>
29 #include <llvm/IR/Function.h>
30 #include <llvm/IR/IRBuilder.h>
31 #include <llvm/IR/Module.h>
32 #include <llvm/IR/DIBuilder.h>
33 #include <llvm/IR/CallSite.h>
34
35 #include "mini-llvm-cpp.h"
36
37 using namespace llvm;
38
39 #if LLVM_API_VERSION > 100
40 // These are c++11 scoped enums in recent llvm versions
41 #define Acquire AtomicOrdering::Acquire
42 #define Release AtomicOrdering::Release
43 #define SequentiallyConsistent AtomicOrdering::SequentiallyConsistent
44 #endif
45
46 void
47 mono_llvm_dump_value (LLVMValueRef value)
48 {
49         /* Same as LLVMDumpValue (), but print to stdout */
50         fflush (stdout);
51         outs () << (*unwrap<Value> (value));
52 }
53
54 /* Missing overload for building an alloca with an alignment */
55 LLVMValueRef
56 mono_llvm_build_alloca (LLVMBuilderRef builder, LLVMTypeRef Ty, 
57                                                 LLVMValueRef ArraySize,
58                                                 int alignment, const char *Name)
59 {
60 #if LLVM_API_VERSION >= 500
61         return wrap (unwrap (builder)->Insert (new AllocaInst (unwrap (Ty), 0, unwrap (ArraySize), alignment), Name));
62 #else
63         return wrap (unwrap (builder)->Insert (new AllocaInst (unwrap (Ty), unwrap (ArraySize), alignment), Name));
64 #endif
65 }
66
67 LLVMValueRef 
68 mono_llvm_build_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
69                                           const char *Name, gboolean is_volatile)
70 {
71         LoadInst *ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
72
73         return wrap(ins);
74 }
75
76 LLVMValueRef
77 mono_llvm_build_atomic_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
78                                                          const char *Name, gboolean is_volatile, int alignment, BarrierKind barrier)
79 {
80         LoadInst *ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
81
82         ins->setAlignment (alignment);
83         switch (barrier) {
84         case LLVM_BARRIER_NONE:
85                 break;
86         case LLVM_BARRIER_ACQ:
87                 ins->setOrdering(Acquire);
88                 break;
89         case LLVM_BARRIER_SEQ:
90                 ins->setOrdering(SequentiallyConsistent);
91                 break;
92         default:
93                 g_assert_not_reached ();
94                 break;
95         }
96
97         return wrap(ins);
98 }
99
100 LLVMValueRef 
101 mono_llvm_build_aligned_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
102                                                           const char *Name, gboolean is_volatile, int alignment)
103 {
104         LoadInst *ins;
105
106         ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
107         ins->setAlignment (alignment);
108
109         return wrap(ins);
110 }
111
112 LLVMValueRef 
113 mono_llvm_build_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal,
114                                           gboolean is_volatile, BarrierKind barrier)
115 {
116         StoreInst *ins = unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile);
117
118         switch (barrier) {
119         case LLVM_BARRIER_NONE:
120                 break;
121         case LLVM_BARRIER_REL:
122                 ins->setOrdering(Release);
123                 break;
124         case LLVM_BARRIER_SEQ:
125                 ins->setOrdering(SequentiallyConsistent);
126                 break;
127         default:
128                 g_assert_not_reached ();
129                 break;
130         }
131
132         return wrap(ins);
133 }
134
135 LLVMValueRef 
136 mono_llvm_build_aligned_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal,
137                                                            gboolean is_volatile, int alignment)
138 {
139         StoreInst *ins;
140
141         ins = unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile);
142         ins->setAlignment (alignment);
143
144         return wrap (ins);
145 }
146
147 LLVMValueRef
148 mono_llvm_build_cmpxchg (LLVMBuilderRef builder, LLVMValueRef ptr, LLVMValueRef cmp, LLVMValueRef val)
149 {
150         AtomicCmpXchgInst *ins;
151
152         ins = unwrap(builder)->CreateAtomicCmpXchg (unwrap(ptr), unwrap (cmp), unwrap (val), SequentiallyConsistent, SequentiallyConsistent);
153         return wrap (ins);
154 }
155
156 LLVMValueRef
157 mono_llvm_build_atomic_rmw (LLVMBuilderRef builder, AtomicRMWOp op, LLVMValueRef ptr, LLVMValueRef val)
158 {
159         AtomicRMWInst::BinOp aop = AtomicRMWInst::Xchg;
160         AtomicRMWInst *ins;
161
162         switch (op) {
163         case LLVM_ATOMICRMW_OP_XCHG:
164                 aop = AtomicRMWInst::Xchg;
165                 break;
166         case LLVM_ATOMICRMW_OP_ADD:
167                 aop = AtomicRMWInst::Add;
168                 break;
169         default:
170                 g_assert_not_reached ();
171                 break;
172         }
173
174         ins = unwrap (builder)->CreateAtomicRMW (aop, unwrap (ptr), unwrap (val), SequentiallyConsistent);
175         return wrap (ins);
176 }
177
178 LLVMValueRef
179 mono_llvm_build_fence (LLVMBuilderRef builder, BarrierKind kind)
180 {
181         FenceInst *ins;
182         AtomicOrdering ordering;
183
184         g_assert (kind != LLVM_BARRIER_NONE);
185
186         switch (kind) {
187         case LLVM_BARRIER_ACQ:
188                 ordering = Acquire;
189                 break;
190         case LLVM_BARRIER_REL:
191                 ordering = Release;
192                 break;
193         case LLVM_BARRIER_SEQ:
194                 ordering = SequentiallyConsistent;
195                 break;
196         default:
197                 g_assert_not_reached ();
198                 break;
199         }
200
201         ins = unwrap (builder)->CreateFence (ordering);
202         return wrap (ins);
203 }
204
205 void
206 mono_llvm_set_must_tail (LLVMValueRef call_ins)
207 {
208         CallInst *ins = (CallInst*)unwrap (call_ins);
209
210         ins->setTailCallKind (CallInst::TailCallKind::TCK_MustTail);
211 }
212
213 void
214 mono_llvm_replace_uses_of (LLVMValueRef var, LLVMValueRef v)
215 {
216         Value *V = ConstantExpr::getTruncOrBitCast (unwrap<Constant> (v), unwrap (var)->getType ());
217         unwrap (var)->replaceAllUsesWith (V);
218 }
219
220 LLVMValueRef
221 mono_llvm_create_constant_data_array (const uint8_t *data, int len)
222 {
223         return wrap(ConstantDataArray::get (*unwrap(LLVMGetGlobalContext ()), makeArrayRef(data, len)));
224 }
225
226 void
227 mono_llvm_set_is_constant (LLVMValueRef global_var)
228 {
229         unwrap<GlobalVariable>(global_var)->setConstant (true);
230 }
231
232 void
233 mono_llvm_set_preserveall_cc (LLVMValueRef func)
234 {
235         unwrap<Function>(func)->setCallingConv (CallingConv::PreserveAll);
236 }
237
238 void
239 mono_llvm_set_call_preserveall_cc (LLVMValueRef func)
240 {
241         unwrap<CallInst>(func)->setCallingConv (CallingConv::PreserveAll);
242 }
243
244 void
245 mono_llvm_set_call_notail (LLVMValueRef func)
246 {
247 #if LLVM_API_VERSION > 100
248         unwrap<CallInst>(func)->setTailCallKind (CallInst::TailCallKind::TCK_NoTail);
249 #endif
250 }
251
252 static Attribute::AttrKind
253 convert_attr (AttrKind kind)
254 {
255         switch (kind) {
256         case LLVM_ATTR_NO_UNWIND:
257                 return Attribute::NoUnwind;
258         case LLVM_ATTR_NO_INLINE:
259                 return Attribute::NoInline;
260         case LLVM_ATTR_OPTIMIZE_FOR_SIZE:
261                 return Attribute::OptimizeForSize;
262         case LLVM_ATTR_IN_REG:
263                 return Attribute::InReg;
264         case LLVM_ATTR_STRUCT_RET:
265                 return Attribute::StructRet;
266         case LLVM_ATTR_NO_ALIAS:
267                 return Attribute::NoAlias;
268         case LLVM_ATTR_BY_VAL:
269                 return Attribute::ByVal;
270         case LLVM_ATTR_UW_TABLE:
271                 return Attribute::UWTable;
272         default:
273                 assert (0);
274                 return Attribute::NoUnwind;
275         }
276 }
277
278 void
279 mono_llvm_add_func_attr (LLVMValueRef func, AttrKind kind)
280 {
281 #if LLVM_API_VERSION > 100
282         unwrap<Function> (func)->addAttribute (AttributeList::FunctionIndex, convert_attr (kind));
283 #else
284         unwrap<Function> (func)->addFnAttr (convert_attr (kind));
285 #endif
286 }
287
288 void
289 mono_llvm_add_param_attr (LLVMValueRef param, AttrKind kind)
290 {
291 #if LLVM_API_VERSION > 100
292         Function *func = unwrap<Argument> (param)->getParent ();
293         int n = unwrap<Argument> (param)->getArgNo ();
294         func->addParamAttr (n, convert_attr (kind));
295 #else
296         Argument *A = unwrap<Argument>(param);
297         AttrBuilder B(convert_attr (kind));
298         A->addAttr(AttributeSet::get(A->getContext(), A->getArgNo() + 1,  B));
299 #endif
300 }
301
302 void
303 mono_llvm_add_instr_attr (LLVMValueRef val, int index, AttrKind kind)
304 {
305 #if LLVM_API_VERSION > 100
306         CallSite (unwrap<Instruction> (val)).addAttribute (index, convert_attr (kind));
307 #else
308   CallSite Call = CallSite(unwrap<Instruction>(val));
309   AttrBuilder B(convert_attr (kind));
310   Call.setAttributes(
311     Call.getAttributes().addAttributes(Call->getContext(), index,
312                                        AttributeSet::get(Call->getContext(),
313                                                          index, B)));
314 #endif
315 }
316
317 #if LLVM_API_VERSION > 100
318
319 void*
320 mono_llvm_create_di_builder (LLVMModuleRef module)
321 {
322         return new DIBuilder (*unwrap(module));
323 }
324
325 void*
326 mono_llvm_di_create_compile_unit (void *di_builder, const char *cu_name, const char *dir, const char *producer)
327 {
328         DIBuilder *builder = (DIBuilder*)di_builder;
329
330 #if LLVM_API_VERSION >= 500
331         DIFile *di_file;
332
333         di_file = builder->createFile (cu_name, dir);
334         return builder->createCompileUnit (dwarf::DW_LANG_C99, di_file, producer, true, "", 0);
335 #else
336         return builder->createCompileUnit (dwarf::DW_LANG_C99, cu_name, dir, producer, true, "", 0);
337 #endif
338 }
339
340 void*
341 mono_llvm_di_create_function (void *di_builder, void *cu, LLVMValueRef func, const char *name, const char *mangled_name, const char *dir, const char *file, int line)
342 {
343         DIBuilder *builder = (DIBuilder*)di_builder;
344         DIFile *di_file;
345         DISubroutineType *type;
346         DISubprogram *di_func;
347
348         // FIXME: Share DIFile
349         di_file = builder->createFile (file, dir);
350         type = builder->createSubroutineType (builder->getOrCreateTypeArray (ArrayRef<Metadata*> ()));
351         di_func = builder->createFunction (di_file, name, mangled_name, di_file, line, type, true, true, 0);
352
353         unwrap<Function>(func)->setMetadata ("dbg", di_func);
354
355         return di_func;
356 }
357
358 void*
359 mono_llvm_di_create_file (void *di_builder, const char *dir, const char *file)
360 {
361         DIBuilder *builder = (DIBuilder*)di_builder;
362
363         return builder->createFile (file, dir);
364 }
365
366 void*
367 mono_llvm_di_create_location (void *di_builder, void *scope, int row, int column)
368 {
369         return DILocation::get (*unwrap(LLVMGetGlobalContext ()), row, column, (Metadata*)scope);
370 }
371
372 void
373 mono_llvm_di_set_location (LLVMBuilderRef builder, void *loc_md)
374 {
375         unwrap(builder)->SetCurrentDebugLocation ((DILocation*)loc_md);
376 }
377
378 void
379 mono_llvm_di_builder_finalize (void *di_builder)
380 {
381         DIBuilder *builder = (DIBuilder*)di_builder;
382
383         builder->finalize ();
384 }
385
386 #endif /* #if LLVM_API_VERSION > 100 */