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