8122365cab91355de3aada21aef334d32c2b4dc8
[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/IR/Function.h>
29 #include <llvm/IR/IRBuilder.h>
30 #include <llvm/IR/Module.h>
31 #include <llvm/IR/DIBuilder.h>
32
33 #include "mini-llvm-cpp.h"
34
35 using namespace llvm;
36
37 void
38 mono_llvm_dump_value (LLVMValueRef value)
39 {
40         /* Same as LLVMDumpValue (), but print to stdout */
41         fflush (stdout);
42         outs () << (*unwrap<Value> (value));
43 }
44
45 /* Missing overload for building an alloca with an alignment */
46 LLVMValueRef
47 mono_llvm_build_alloca (LLVMBuilderRef builder, LLVMTypeRef Ty, 
48                                                 LLVMValueRef ArraySize,
49                                                 int alignment, const char *Name)
50 {
51         return wrap (unwrap (builder)->Insert (new AllocaInst (unwrap (Ty), unwrap (ArraySize), alignment), Name));
52 }
53
54 LLVMValueRef 
55 mono_llvm_build_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
56                                           const char *Name, gboolean is_volatile, BarrierKind barrier)
57 {
58         LoadInst *ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
59
60         switch (barrier) {
61         case LLVM_BARRIER_NONE:
62                 break;
63         case LLVM_BARRIER_ACQ:
64                 ins->setOrdering(Acquire);
65                 break;
66         case LLVM_BARRIER_SEQ:
67                 ins->setOrdering(SequentiallyConsistent);
68                 break;
69         default:
70                 g_assert_not_reached ();
71                 break;
72         }
73
74         return wrap(ins);
75 }
76
77 LLVMValueRef 
78 mono_llvm_build_aligned_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
79                                                           const char *Name, gboolean is_volatile, int alignment)
80 {
81         LoadInst *ins;
82
83         ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
84         ins->setAlignment (alignment);
85
86         return wrap(ins);
87 }
88
89 LLVMValueRef 
90 mono_llvm_build_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal,
91                                           gboolean is_volatile, BarrierKind barrier)
92 {
93         StoreInst *ins = unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile);
94
95         switch (barrier) {
96         case LLVM_BARRIER_NONE:
97                 break;
98         case LLVM_BARRIER_REL:
99                 ins->setOrdering(Release);
100                 break;
101         case LLVM_BARRIER_SEQ:
102                 ins->setOrdering(SequentiallyConsistent);
103                 break;
104         default:
105                 g_assert_not_reached ();
106                 break;
107         }
108
109         return wrap(ins);
110 }
111
112 LLVMValueRef 
113 mono_llvm_build_aligned_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal,
114                                                            gboolean is_volatile, int alignment)
115 {
116         StoreInst *ins;
117
118         ins = unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile);
119         ins->setAlignment (alignment);
120
121         return wrap (ins);
122 }
123
124 LLVMValueRef
125 mono_llvm_build_cmpxchg (LLVMBuilderRef builder, LLVMValueRef ptr, LLVMValueRef cmp, LLVMValueRef val)
126 {
127         AtomicCmpXchgInst *ins;
128
129         ins = unwrap(builder)->CreateAtomicCmpXchg (unwrap(ptr), unwrap (cmp), unwrap (val), SequentiallyConsistent, SequentiallyConsistent);
130         return wrap (ins);
131 }
132
133 LLVMValueRef
134 mono_llvm_build_atomic_rmw (LLVMBuilderRef builder, AtomicRMWOp op, LLVMValueRef ptr, LLVMValueRef val)
135 {
136         AtomicRMWInst::BinOp aop = AtomicRMWInst::Xchg;
137         AtomicRMWInst *ins;
138
139         switch (op) {
140         case LLVM_ATOMICRMW_OP_XCHG:
141                 aop = AtomicRMWInst::Xchg;
142                 break;
143         case LLVM_ATOMICRMW_OP_ADD:
144                 aop = AtomicRMWInst::Add;
145                 break;
146         default:
147                 g_assert_not_reached ();
148                 break;
149         }
150
151         ins = unwrap (builder)->CreateAtomicRMW (aop, unwrap (ptr), unwrap (val), SequentiallyConsistent);
152         return wrap (ins);
153 }
154
155 LLVMValueRef
156 mono_llvm_build_fence (LLVMBuilderRef builder, BarrierKind kind)
157 {
158         FenceInst *ins;
159         AtomicOrdering ordering;
160
161         g_assert (kind != LLVM_BARRIER_NONE);
162
163         switch (kind) {
164         case LLVM_BARRIER_ACQ:
165                 ordering = Acquire;
166                 break;
167         case LLVM_BARRIER_REL:
168                 ordering = Release;
169                 break;
170         case LLVM_BARRIER_SEQ:
171                 ordering = SequentiallyConsistent;
172                 break;
173         default:
174                 g_assert_not_reached ();
175                 break;
176         }
177
178         ins = unwrap (builder)->CreateFence (ordering);
179         return wrap (ins);
180 }
181
182 void
183 mono_llvm_set_must_tail (LLVMValueRef call_ins)
184 {
185         CallInst *ins = (CallInst*)unwrap (call_ins);
186
187         ins->setTailCallKind (CallInst::TailCallKind::TCK_MustTail);
188 }
189
190 void
191 mono_llvm_replace_uses_of (LLVMValueRef var, LLVMValueRef v)
192 {
193         Value *V = ConstantExpr::getTruncOrBitCast (unwrap<Constant> (v), unwrap (var)->getType ());
194         unwrap (var)->replaceAllUsesWith (V);
195 }
196
197 LLVMValueRef
198 mono_llvm_create_constant_data_array (const uint8_t *data, int len)
199 {
200         return wrap(ConstantDataArray::get (*unwrap(LLVMGetGlobalContext ()), makeArrayRef(data, len)));
201 }
202
203 void
204 mono_llvm_set_is_constant (LLVMValueRef global_var)
205 {
206         unwrap<GlobalVariable>(global_var)->setConstant (true);
207 }
208
209 void
210 mono_llvm_set_preserveall_cc (LLVMValueRef func)
211 {
212         unwrap<Function>(func)->setCallingConv (CallingConv::PreserveAll);
213 }
214
215 void
216 mono_llvm_set_call_preserveall_cc (LLVMValueRef func)
217 {
218         unwrap<CallInst>(func)->setCallingConv (CallingConv::PreserveAll);
219 }
220
221 #if LLVM_API_VERSION > 100
222
223 void*
224 mono_llvm_create_di_builder (LLVMModuleRef module)
225 {
226         return new DIBuilder (*unwrap(module));
227 }
228
229 void*
230 mono_llvm_di_create_compile_unit (void *di_builder, const char *cu_name, const char *dir, const char *producer)
231 {
232         DIBuilder *builder = (DIBuilder*)di_builder;
233
234         return builder->createCompileUnit (dwarf::DW_LANG_C99, cu_name, dir, producer, true, "", 0);
235 }
236
237 void*
238 mono_llvm_di_create_function (void *di_builder, void *cu, const char *name, const char *mangled_name, const char *dir, const char *file, int line)
239 {
240         DIBuilder *builder = (DIBuilder*)di_builder;
241         DIFile *di_file;
242         DISubroutineType *type;
243
244         // FIXME: Share DIFile
245         di_file = builder->createFile (file, dir);
246         type = builder->createSubroutineType (builder->getOrCreateTypeArray (ArrayRef<Metadata*> ()));
247         return builder->createFunction (di_file, name, mangled_name, di_file, line, type, true, true, 0);
248 }
249
250 void*
251 mono_llvm_di_create_file (void *di_builder, const char *dir, const char *file)
252 {
253         DIBuilder *builder = (DIBuilder*)di_builder;
254
255         return builder->createFile (file, dir);
256 }
257
258 void*
259 mono_llvm_di_create_location (void *di_builder, void *scope, int row, int column)
260 {
261         return DILocation::get (*unwrap(LLVMGetGlobalContext ()), row, column, (Metadata*)scope);
262 }
263
264 void
265 mono_llvm_di_set_location (LLVMBuilderRef builder, void *loc_md)
266 {
267         unwrap(builder)->SetCurrentDebugLocation ((DILocation*)loc_md);
268 }
269
270 void
271 mono_llvm_di_builder_finalize (void *di_builder)
272 {
273         DIBuilder *builder = (DIBuilder*)di_builder;
274
275         builder->finalize ();
276 }
277
278 #endif /* #if LLVM_API_VERSION > 100 */