Merge pull request #5714 from alexischr/update_bockbuild
[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 #if LLVM_API_VERSION > 500
253 static Attribute::AttrKind
254 convert_attr (AttrKind kind)
255 {
256         switch (kind) {
257         case LLVM_ATTR_NO_UNWIND:
258                 return Attribute::NoUnwind;
259         case LLVM_ATTR_NO_INLINE:
260                 return Attribute::NoInline;
261         case LLVM_ATTR_OPTIMIZE_FOR_SIZE:
262                 return Attribute::OptimizeForSize;
263         case LLVM_ATTR_IN_REG:
264                 return Attribute::InReg;
265         case LLVM_ATTR_STRUCT_RET:
266                 return Attribute::StructRet;
267         case LLVM_ATTR_NO_ALIAS:
268                 return Attribute::NoAlias;
269         case LLVM_ATTR_BY_VAL:
270                 return Attribute::ByVal;
271         case LLVM_ATTR_UW_TABLE:
272                 return Attribute::UWTable;
273         default:
274                 assert (0);
275                 return Attribute::NoUnwind;
276         }
277 }
278 #else
279 static LLVMAttribute
280 convert_attr (AttrKind kind)
281 {
282         switch (kind) {
283         case LLVM_ATTR_NO_UNWIND:
284                 return LLVMNoUnwindAttribute;
285         case LLVM_ATTR_NO_INLINE:
286                 return LLVMNoInlineAttribute;
287         case LLVM_ATTR_OPTIMIZE_FOR_SIZE:
288                 return LLVMOptimizeForSizeAttribute;
289         case LLVM_ATTR_IN_REG:
290                 return LLVMInRegAttribute;
291         case LLVM_ATTR_STRUCT_RET:
292                 return LLVMStructRetAttribute;
293         case LLVM_ATTR_NO_ALIAS:
294                 return LLVMNoAliasAttribute;
295         case LLVM_ATTR_BY_VAL:
296                 return LLVMByValAttribute;
297         case LLVM_ATTR_UW_TABLE:
298                 return LLVMUWTable;
299         default:
300                 assert (0);
301                 return LLVMNoUnwindAttribute;
302         }
303 }
304 #endif
305
306 void
307 mono_llvm_add_func_attr (LLVMValueRef func, AttrKind kind)
308 {
309 #if LLVM_API_VERSION > 100
310         unwrap<Function> (func)->addAttribute (AttributeList::FunctionIndex, convert_attr (kind));
311 #else
312         Function *Func = unwrap<Function>(func);
313         const AttributeSet PAL = Func->getAttributes();
314         AttrBuilder B(convert_attr (kind));
315         const AttributeSet PALnew =
316                 PAL.addAttributes(Func->getContext(), AttributeSet::FunctionIndex,
317                                                   AttributeSet::get(Func->getContext(),
318                                                                                         AttributeSet::FunctionIndex, B));
319         Func->setAttributes(PALnew);
320 #endif
321 }
322
323 void
324 mono_llvm_add_param_attr (LLVMValueRef param, AttrKind kind)
325 {
326 #if LLVM_API_VERSION > 100
327         Function *func = unwrap<Argument> (param)->getParent ();
328         int n = unwrap<Argument> (param)->getArgNo ();
329         func->addParamAttr (n, convert_attr (kind));
330 #else
331         Argument *A = unwrap<Argument>(param);
332         AttrBuilder B(convert_attr (kind));
333         A->addAttr(AttributeSet::get(A->getContext(), A->getArgNo() + 1,  B));
334 #endif
335 }
336
337 void
338 mono_llvm_add_instr_attr (LLVMValueRef val, int index, AttrKind kind)
339 {
340 #if LLVM_API_VERSION > 100
341         CallSite (unwrap<Instruction> (val)).addAttribute (index, convert_attr (kind));
342 #else
343   CallSite Call = CallSite(unwrap<Instruction>(val));
344   AttrBuilder B(convert_attr (kind));
345   Call.setAttributes(
346     Call.getAttributes().addAttributes(Call->getContext(), index,
347                                        AttributeSet::get(Call->getContext(),
348                                                          index, B)));
349 #endif
350 }
351
352 #if LLVM_API_VERSION > 100
353
354 void*
355 mono_llvm_create_di_builder (LLVMModuleRef module)
356 {
357         return new DIBuilder (*unwrap(module));
358 }
359
360 void*
361 mono_llvm_di_create_compile_unit (void *di_builder, const char *cu_name, const char *dir, const char *producer)
362 {
363         DIBuilder *builder = (DIBuilder*)di_builder;
364
365 #if LLVM_API_VERSION >= 500
366         DIFile *di_file;
367
368         di_file = builder->createFile (cu_name, dir);
369         return builder->createCompileUnit (dwarf::DW_LANG_C99, di_file, producer, true, "", 0);
370 #else
371         return builder->createCompileUnit (dwarf::DW_LANG_C99, cu_name, dir, producer, true, "", 0);
372 #endif
373 }
374
375 void*
376 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)
377 {
378         DIBuilder *builder = (DIBuilder*)di_builder;
379         DIFile *di_file;
380         DISubroutineType *type;
381         DISubprogram *di_func;
382
383         // FIXME: Share DIFile
384         di_file = builder->createFile (file, dir);
385         type = builder->createSubroutineType (builder->getOrCreateTypeArray (ArrayRef<Metadata*> ()));
386         di_func = builder->createFunction (di_file, name, mangled_name, di_file, line, type, true, true, 0);
387
388         unwrap<Function>(func)->setMetadata ("dbg", di_func);
389
390         return di_func;
391 }
392
393 void*
394 mono_llvm_di_create_file (void *di_builder, const char *dir, const char *file)
395 {
396         DIBuilder *builder = (DIBuilder*)di_builder;
397
398         return builder->createFile (file, dir);
399 }
400
401 void*
402 mono_llvm_di_create_location (void *di_builder, void *scope, int row, int column)
403 {
404         return DILocation::get (*unwrap(LLVMGetGlobalContext ()), row, column, (Metadata*)scope);
405 }
406
407 void
408 mono_llvm_di_set_location (LLVMBuilderRef builder, void *loc_md)
409 {
410         unwrap(builder)->SetCurrentDebugLocation ((DILocation*)loc_md);
411 }
412
413 void
414 mono_llvm_di_builder_finalize (void *di_builder)
415 {
416         DIBuilder *builder = (DIBuilder*)di_builder;
417
418         builder->finalize ();
419 }
420
421 #endif /* #if LLVM_API_VERSION > 100 */