2 // mini-llvm-cpp.cpp: C++ support classes for the mono LLVM integration
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.
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
20 // Mono's internal header files are not C++ clean, so avoid including them if
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>
34 #include "mini-llvm-cpp.h"
39 mono_llvm_dump_value (LLVMValueRef value)
41 /* Same as LLVMDumpValue (), but print to stdout */
43 outs () << (*unwrap<Value> (value));
46 /* Missing overload for building an alloca with an alignment */
48 mono_llvm_build_alloca (LLVMBuilderRef builder, LLVMTypeRef Ty,
49 LLVMValueRef ArraySize,
50 int alignment, const char *Name)
52 return wrap (unwrap (builder)->Insert (new AllocaInst (unwrap (Ty), unwrap (ArraySize), alignment), Name));
56 mono_llvm_build_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
57 const char *Name, gboolean is_volatile, BarrierKind barrier)
59 LoadInst *ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
62 case LLVM_BARRIER_NONE:
64 case LLVM_BARRIER_ACQ:
65 ins->setOrdering(Acquire);
67 case LLVM_BARRIER_SEQ:
68 ins->setOrdering(SequentiallyConsistent);
71 g_assert_not_reached ();
79 mono_llvm_build_aligned_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
80 const char *Name, gboolean is_volatile, int alignment)
84 ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
85 ins->setAlignment (alignment);
91 mono_llvm_build_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal,
92 gboolean is_volatile, BarrierKind barrier)
94 StoreInst *ins = unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile);
97 case LLVM_BARRIER_NONE:
99 case LLVM_BARRIER_REL:
100 ins->setOrdering(Release);
102 case LLVM_BARRIER_SEQ:
103 ins->setOrdering(SequentiallyConsistent);
106 g_assert_not_reached ();
114 mono_llvm_build_aligned_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal,
115 gboolean is_volatile, int alignment)
119 ins = unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile);
120 ins->setAlignment (alignment);
126 mono_llvm_build_cmpxchg (LLVMBuilderRef builder, LLVMValueRef ptr, LLVMValueRef cmp, LLVMValueRef val)
128 AtomicCmpXchgInst *ins;
130 ins = unwrap(builder)->CreateAtomicCmpXchg (unwrap(ptr), unwrap (cmp), unwrap (val), SequentiallyConsistent, SequentiallyConsistent);
135 mono_llvm_build_atomic_rmw (LLVMBuilderRef builder, AtomicRMWOp op, LLVMValueRef ptr, LLVMValueRef val)
137 AtomicRMWInst::BinOp aop = AtomicRMWInst::Xchg;
141 case LLVM_ATOMICRMW_OP_XCHG:
142 aop = AtomicRMWInst::Xchg;
144 case LLVM_ATOMICRMW_OP_ADD:
145 aop = AtomicRMWInst::Add;
148 g_assert_not_reached ();
152 ins = unwrap (builder)->CreateAtomicRMW (aop, unwrap (ptr), unwrap (val), SequentiallyConsistent);
157 mono_llvm_build_fence (LLVMBuilderRef builder, BarrierKind kind)
160 AtomicOrdering ordering;
162 g_assert (kind != LLVM_BARRIER_NONE);
165 case LLVM_BARRIER_ACQ:
168 case LLVM_BARRIER_REL:
171 case LLVM_BARRIER_SEQ:
172 ordering = SequentiallyConsistent;
175 g_assert_not_reached ();
179 ins = unwrap (builder)->CreateFence (ordering);
184 mono_llvm_set_must_tail (LLVMValueRef call_ins)
186 CallInst *ins = (CallInst*)unwrap (call_ins);
188 ins->setTailCallKind (CallInst::TailCallKind::TCK_MustTail);
192 mono_llvm_replace_uses_of (LLVMValueRef var, LLVMValueRef v)
194 Value *V = ConstantExpr::getTruncOrBitCast (unwrap<Constant> (v), unwrap (var)->getType ());
195 unwrap (var)->replaceAllUsesWith (V);
199 mono_llvm_create_constant_data_array (const uint8_t *data, int len)
201 return wrap(ConstantDataArray::get (*unwrap(LLVMGetGlobalContext ()), makeArrayRef(data, len)));
205 mono_llvm_set_is_constant (LLVMValueRef global_var)
207 unwrap<GlobalVariable>(global_var)->setConstant (true);
211 mono_llvm_set_preserveall_cc (LLVMValueRef func)
213 unwrap<Function>(func)->setCallingConv (CallingConv::PreserveAll);
217 mono_llvm_set_call_preserveall_cc (LLVMValueRef func)
219 unwrap<CallInst>(func)->setCallingConv (CallingConv::PreserveAll);
222 #if LLVM_API_VERSION > 100
225 mono_llvm_create_di_builder (LLVMModuleRef module)
227 return new DIBuilder (*unwrap(module));
231 mono_llvm_di_create_compile_unit (void *di_builder, const char *cu_name, const char *dir, const char *producer)
233 DIBuilder *builder = (DIBuilder*)di_builder;
235 return builder->createCompileUnit (dwarf::DW_LANG_C99, cu_name, dir, producer, true, "", 0);
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)
241 DIBuilder *builder = (DIBuilder*)di_builder;
243 DISubroutineType *type;
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);
252 mono_llvm_di_create_file (void *di_builder, const char *dir, const char *file)
254 DIBuilder *builder = (DIBuilder*)di_builder;
256 return builder->createFile (file, dir);
260 mono_llvm_di_create_location (void *di_builder, void *scope, int row, int column)
262 return DILocation::get (*unwrap(LLVMGetGlobalContext ()), row, column, (Metadata*)scope);
266 mono_llvm_di_set_location (LLVMBuilderRef builder, void *loc_md)
268 unwrap(builder)->SetCurrentDebugLocation ((DILocation*)loc_md);
272 mono_llvm_di_builder_finalize (void *di_builder)
274 DIBuilder *builder = (DIBuilder*)di_builder;
276 builder->finalize ();
279 #endif /* #if LLVM_API_VERSION > 100 */