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>
33 #include <llvm/IR/CallSite.h>
35 #include "mini-llvm-cpp.h"
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
47 mono_llvm_dump_value (LLVMValueRef value)
49 /* Same as LLVMDumpValue (), but print to stdout */
51 outs () << (*unwrap<Value> (value));
54 /* Missing overload for building an alloca with an alignment */
56 mono_llvm_build_alloca (LLVMBuilderRef builder, LLVMTypeRef Ty,
57 LLVMValueRef ArraySize,
58 int alignment, const char *Name)
60 #if LLVM_API_VERSION >= 500
61 return wrap (unwrap (builder)->Insert (new AllocaInst (unwrap (Ty), 0, unwrap (ArraySize), alignment), Name));
63 return wrap (unwrap (builder)->Insert (new AllocaInst (unwrap (Ty), unwrap (ArraySize), alignment), Name));
68 mono_llvm_build_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
69 const char *Name, gboolean is_volatile)
71 LoadInst *ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
77 mono_llvm_build_atomic_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
78 const char *Name, gboolean is_volatile, int alignment, BarrierKind barrier)
80 LoadInst *ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
82 ins->setAlignment (alignment);
84 case LLVM_BARRIER_NONE:
86 case LLVM_BARRIER_ACQ:
87 ins->setOrdering(Acquire);
89 case LLVM_BARRIER_SEQ:
90 ins->setOrdering(SequentiallyConsistent);
93 g_assert_not_reached ();
101 mono_llvm_build_aligned_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
102 const char *Name, gboolean is_volatile, int alignment)
106 ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
107 ins->setAlignment (alignment);
113 mono_llvm_build_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal,
114 gboolean is_volatile, BarrierKind barrier)
116 StoreInst *ins = unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile);
119 case LLVM_BARRIER_NONE:
121 case LLVM_BARRIER_REL:
122 ins->setOrdering(Release);
124 case LLVM_BARRIER_SEQ:
125 ins->setOrdering(SequentiallyConsistent);
128 g_assert_not_reached ();
136 mono_llvm_build_aligned_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal,
137 gboolean is_volatile, int alignment)
141 ins = unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile);
142 ins->setAlignment (alignment);
148 mono_llvm_build_cmpxchg (LLVMBuilderRef builder, LLVMValueRef ptr, LLVMValueRef cmp, LLVMValueRef val)
150 AtomicCmpXchgInst *ins;
152 ins = unwrap(builder)->CreateAtomicCmpXchg (unwrap(ptr), unwrap (cmp), unwrap (val), SequentiallyConsistent, SequentiallyConsistent);
157 mono_llvm_build_atomic_rmw (LLVMBuilderRef builder, AtomicRMWOp op, LLVMValueRef ptr, LLVMValueRef val)
159 AtomicRMWInst::BinOp aop = AtomicRMWInst::Xchg;
163 case LLVM_ATOMICRMW_OP_XCHG:
164 aop = AtomicRMWInst::Xchg;
166 case LLVM_ATOMICRMW_OP_ADD:
167 aop = AtomicRMWInst::Add;
170 g_assert_not_reached ();
174 ins = unwrap (builder)->CreateAtomicRMW (aop, unwrap (ptr), unwrap (val), SequentiallyConsistent);
179 mono_llvm_build_fence (LLVMBuilderRef builder, BarrierKind kind)
182 AtomicOrdering ordering;
184 g_assert (kind != LLVM_BARRIER_NONE);
187 case LLVM_BARRIER_ACQ:
190 case LLVM_BARRIER_REL:
193 case LLVM_BARRIER_SEQ:
194 ordering = SequentiallyConsistent;
197 g_assert_not_reached ();
201 ins = unwrap (builder)->CreateFence (ordering);
206 mono_llvm_set_must_tail (LLVMValueRef call_ins)
208 CallInst *ins = (CallInst*)unwrap (call_ins);
210 ins->setTailCallKind (CallInst::TailCallKind::TCK_MustTail);
214 mono_llvm_replace_uses_of (LLVMValueRef var, LLVMValueRef v)
216 Value *V = ConstantExpr::getTruncOrBitCast (unwrap<Constant> (v), unwrap (var)->getType ());
217 unwrap (var)->replaceAllUsesWith (V);
221 mono_llvm_create_constant_data_array (const uint8_t *data, int len)
223 return wrap(ConstantDataArray::get (*unwrap(LLVMGetGlobalContext ()), makeArrayRef(data, len)));
227 mono_llvm_set_is_constant (LLVMValueRef global_var)
229 unwrap<GlobalVariable>(global_var)->setConstant (true);
233 mono_llvm_set_preserveall_cc (LLVMValueRef func)
235 unwrap<Function>(func)->setCallingConv (CallingConv::PreserveAll);
239 mono_llvm_set_call_preserveall_cc (LLVMValueRef func)
241 unwrap<CallInst>(func)->setCallingConv (CallingConv::PreserveAll);
245 mono_llvm_set_call_notail (LLVMValueRef func)
247 #if LLVM_API_VERSION > 100
248 unwrap<CallInst>(func)->setTailCallKind (CallInst::TailCallKind::TCK_NoTail);
252 #if LLVM_API_VERSION > 500
253 static Attribute::AttrKind
254 convert_attr (AttrKind 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;
275 return Attribute::NoUnwind;
280 convert_attr (AttrKind 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:
301 return LLVMNoUnwindAttribute;
307 mono_llvm_add_func_attr (LLVMValueRef func, AttrKind kind)
309 #if LLVM_API_VERSION > 100
310 unwrap<Function> (func)->addAttribute (AttributeList::FunctionIndex, convert_attr (kind));
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);
324 mono_llvm_add_param_attr (LLVMValueRef param, AttrKind kind)
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));
331 Argument *A = unwrap<Argument>(param);
332 AttrBuilder B(convert_attr (kind));
333 A->addAttr(AttributeSet::get(A->getContext(), A->getArgNo() + 1, B));
338 mono_llvm_add_instr_attr (LLVMValueRef val, int index, AttrKind kind)
340 #if LLVM_API_VERSION > 100
341 CallSite (unwrap<Instruction> (val)).addAttribute (index, convert_attr (kind));
343 CallSite Call = CallSite(unwrap<Instruction>(val));
344 AttrBuilder B(convert_attr (kind));
346 Call.getAttributes().addAttributes(Call->getContext(), index,
347 AttributeSet::get(Call->getContext(),
352 #if LLVM_API_VERSION > 100
355 mono_llvm_create_di_builder (LLVMModuleRef module)
357 return new DIBuilder (*unwrap(module));
361 mono_llvm_di_create_compile_unit (void *di_builder, const char *cu_name, const char *dir, const char *producer)
363 DIBuilder *builder = (DIBuilder*)di_builder;
365 #if LLVM_API_VERSION >= 500
368 di_file = builder->createFile (cu_name, dir);
369 return builder->createCompileUnit (dwarf::DW_LANG_C99, di_file, producer, true, "", 0);
371 return builder->createCompileUnit (dwarf::DW_LANG_C99, cu_name, dir, producer, true, "", 0);
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)
378 DIBuilder *builder = (DIBuilder*)di_builder;
380 DISubroutineType *type;
381 DISubprogram *di_func;
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);
388 unwrap<Function>(func)->setMetadata ("dbg", di_func);
394 mono_llvm_di_create_file (void *di_builder, const char *dir, const char *file)
396 DIBuilder *builder = (DIBuilder*)di_builder;
398 return builder->createFile (file, dir);
402 mono_llvm_di_create_location (void *di_builder, void *scope, int row, int column)
404 return DILocation::get (*unwrap(LLVMGetGlobalContext ()), row, column, (Metadata*)scope);
408 mono_llvm_di_set_location (LLVMBuilderRef builder, void *loc_md)
410 unwrap(builder)->SetCurrentDebugLocation ((DILocation*)loc_md);
414 mono_llvm_di_builder_finalize (void *di_builder)
416 DIBuilder *builder = (DIBuilder*)di_builder;
418 builder->finalize ();
421 #endif /* #if LLVM_API_VERSION > 100 */