Llvm optimizations (#16191)
[mono-project.git] / mono / mini / mini-llvm-cpp.cpp
blob768bd90e9c4fd27a3c9b44de473e80769e6c6f06
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 //
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.
20 // Mono's internal header files are not C++ clean, so avoid including them if
21 // possible
24 #ifdef _MSC_VER
25 // Disable warnings generated by LLVM headers.
26 #pragma warning(disable:4141) // modifier' : used more than once
27 #pragma warning(disable:4800) // type' : forcing value to bool 'true' or 'false' (performance warning)
28 #endif
30 #include "config.h"
32 #include <stdint.h>
34 #include <llvm/Support/raw_ostream.h>
35 #include <llvm/IR/Function.h>
36 #include <llvm/IR/IRBuilder.h>
37 #include <llvm/IR/Module.h>
38 #include <llvm/IR/DIBuilder.h>
39 #include <llvm/IR/CallSite.h>
41 #include "mini-llvm-cpp.h"
43 using namespace llvm;
45 #define Acquire AtomicOrdering::Acquire
46 #define Release AtomicOrdering::Release
47 #define SequentiallyConsistent AtomicOrdering::SequentiallyConsistent
49 void
50 mono_llvm_dump_value (LLVMValueRef value)
52 /* Same as LLVMDumpValue (), but print to stdout */
53 fflush (stdout);
54 outs () << (*unwrap<Value> (value));
57 /* Missing overload for building an alloca with an alignment */
58 LLVMValueRef
59 mono_llvm_build_alloca (LLVMBuilderRef builder, LLVMTypeRef Ty,
60 LLVMValueRef ArraySize,
61 int alignment, const char *Name)
63 return wrap (unwrap (builder)->Insert (new AllocaInst (unwrap (Ty), 0, unwrap (ArraySize), alignment), Name));
66 LLVMValueRef
67 mono_llvm_build_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
68 const char *Name, gboolean is_volatile)
70 LoadInst *ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
72 return wrap(ins);
75 LLVMValueRef
76 mono_llvm_build_atomic_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
77 const char *Name, gboolean is_volatile, int alignment, BarrierKind barrier)
79 LoadInst *ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
81 ins->setAlignment (alignment);
82 switch (barrier) {
83 case LLVM_BARRIER_NONE:
84 break;
85 case LLVM_BARRIER_ACQ:
86 ins->setOrdering(Acquire);
87 break;
88 case LLVM_BARRIER_SEQ:
89 ins->setOrdering(SequentiallyConsistent);
90 break;
91 default:
92 g_assert_not_reached ();
93 break;
96 return wrap(ins);
99 LLVMValueRef
100 mono_llvm_build_aligned_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
101 const char *Name, gboolean is_volatile, int alignment)
103 LoadInst *ins;
105 ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
106 ins->setAlignment (alignment);
108 return wrap(ins);
111 LLVMValueRef
112 mono_llvm_build_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal,
113 gboolean is_volatile, BarrierKind barrier)
115 StoreInst *ins = unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile);
117 switch (barrier) {
118 case LLVM_BARRIER_NONE:
119 break;
120 case LLVM_BARRIER_REL:
121 ins->setOrdering(Release);
122 break;
123 case LLVM_BARRIER_SEQ:
124 ins->setOrdering(SequentiallyConsistent);
125 break;
126 default:
127 g_assert_not_reached ();
128 break;
131 return wrap(ins);
134 LLVMValueRef
135 mono_llvm_build_aligned_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal,
136 gboolean is_volatile, int alignment)
138 StoreInst *ins;
140 ins = unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile);
141 ins->setAlignment (alignment);
143 return wrap (ins);
146 LLVMValueRef
147 mono_llvm_build_cmpxchg (LLVMBuilderRef builder, LLVMValueRef ptr, LLVMValueRef cmp, LLVMValueRef val)
149 AtomicCmpXchgInst *ins;
151 ins = unwrap(builder)->CreateAtomicCmpXchg (unwrap(ptr), unwrap (cmp), unwrap (val), SequentiallyConsistent, SequentiallyConsistent);
152 return wrap (ins);
155 LLVMValueRef
156 mono_llvm_build_atomic_rmw (LLVMBuilderRef builder, AtomicRMWOp op, LLVMValueRef ptr, LLVMValueRef val)
158 AtomicRMWInst::BinOp aop = AtomicRMWInst::Xchg;
159 AtomicRMWInst *ins;
161 switch (op) {
162 case LLVM_ATOMICRMW_OP_XCHG:
163 aop = AtomicRMWInst::Xchg;
164 break;
165 case LLVM_ATOMICRMW_OP_ADD:
166 aop = AtomicRMWInst::Add;
167 break;
168 default:
169 g_assert_not_reached ();
170 break;
173 ins = unwrap (builder)->CreateAtomicRMW (aop, unwrap (ptr), unwrap (val), SequentiallyConsistent);
174 return wrap (ins);
177 LLVMValueRef
178 mono_llvm_build_fence (LLVMBuilderRef builder, BarrierKind kind)
180 FenceInst *ins;
181 AtomicOrdering ordering;
183 g_assert (kind != LLVM_BARRIER_NONE);
185 switch (kind) {
186 case LLVM_BARRIER_ACQ:
187 ordering = Acquire;
188 break;
189 case LLVM_BARRIER_REL:
190 ordering = Release;
191 break;
192 case LLVM_BARRIER_SEQ:
193 ordering = SequentiallyConsistent;
194 break;
195 default:
196 g_assert_not_reached ();
197 break;
200 ins = unwrap (builder)->CreateFence (ordering);
201 return wrap (ins);
204 void
205 mono_llvm_set_must_tailcall (LLVMValueRef call_ins)
207 CallInst *ins = (CallInst*)unwrap (call_ins);
209 ins->setTailCallKind (CallInst::TailCallKind::TCK_MustTail);
212 void
213 mono_llvm_replace_uses_of (LLVMValueRef var, LLVMValueRef v)
215 Value *V = ConstantExpr::getTruncOrBitCast (unwrap<Constant> (v), unwrap (var)->getType ());
216 unwrap (var)->replaceAllUsesWith (V);
219 LLVMValueRef
220 mono_llvm_create_constant_data_array (const uint8_t *data, int len)
222 return wrap(ConstantDataArray::get (*unwrap(LLVMGetGlobalContext ()), makeArrayRef(data, len)));
225 void
226 mono_llvm_set_is_constant (LLVMValueRef global_var)
228 unwrap<GlobalVariable>(global_var)->setConstant (true);
231 // Note that in future versions of LLVM, CallInst and InvokeInst
232 // share a CallBase parent class that would make the below methods
233 // look much better
235 void
236 mono_llvm_set_call_nonnull_arg (LLVMValueRef wrapped_calli, int argNo)
238 Instruction *calli = unwrap<Instruction> (wrapped_calli);
240 if (isa<CallInst> (calli))
241 dyn_cast<CallInst>(calli)->addParamAttr (argNo, Attribute::NonNull);
242 else
243 dyn_cast<InvokeInst>(calli)->addParamAttr (argNo, Attribute::NonNull);
246 void
247 mono_llvm_set_call_nonnull_ret (LLVMValueRef wrapped_calli)
249 Instruction *calli = unwrap<Instruction> (wrapped_calli);
251 if (isa<CallInst> (calli))
252 dyn_cast<CallInst>(calli)->addAttribute (AttributeList::ReturnIndex, Attribute::NonNull);
253 else
254 dyn_cast<InvokeInst>(calli)->addAttribute (AttributeList::ReturnIndex, Attribute::NonNull);
257 void
258 mono_llvm_set_func_nonnull_arg (LLVMValueRef func, int argNo)
260 unwrap<Function>(func)->addParamAttr (argNo, Attribute::NonNull);
263 gboolean
264 mono_llvm_is_nonnull (LLVMValueRef wrapped)
266 // Argument to function
267 Value *val = unwrap (wrapped);
269 while (val) {
270 if (Argument *arg = dyn_cast<Argument> (val)) {
271 return arg->hasNonNullAttr ();
272 } else if (CallInst *calli = dyn_cast<CallInst> (val)) {
273 return calli->hasRetAttr (Attribute::NonNull);
274 } else if (InvokeInst *calli = dyn_cast<InvokeInst> (val)) {
275 return calli->hasRetAttr (Attribute::NonNull);
276 } else if (LoadInst *loadi = dyn_cast<LoadInst> (val)) {
277 return loadi->getMetadata("nonnull") != nullptr; // nonnull <index>
278 } else if (Instruction *inst = dyn_cast<Instruction> (val)) {
279 // If not a load or a function argument, the only case for us to
280 // consider is that it's a bitcast. If so, recurse on what was casted.
281 if (inst->getOpcode () == LLVMBitCast) {
282 val = inst->getOperand (0);
283 continue;
286 return FALSE;
287 } else {
288 return FALSE;
291 return FALSE;
294 GSList *
295 mono_llvm_calls_using (LLVMValueRef wrapped_local)
297 GSList *usages = NULL;
298 Value *local = unwrap (wrapped_local);
300 for (User *user : local->users ()) {
301 if (isa<CallInst> (user) || isa<InvokeInst> (user)) {
302 usages = g_slist_prepend (usages, wrap (user));
306 return usages;
309 LLVMValueRef *
310 mono_llvm_call_args (LLVMValueRef wrapped_calli)
312 Value *calli = unwrap(wrapped_calli);
313 CallInst *call = dyn_cast <CallInst> (calli);
314 InvokeInst *invoke = dyn_cast <InvokeInst> (calli);
315 g_assert (call || invoke);
317 unsigned int numOperands = 0;
319 if (call)
320 numOperands = call->getNumArgOperands ();
321 else
322 numOperands = invoke->getNumArgOperands ();
324 LLVMValueRef *ret = g_malloc (sizeof (LLVMValueRef) * numOperands);
326 for (int i=0; i < numOperands; i++) {
327 if (call)
328 ret [i] = wrap (call->getArgOperand (i));
329 else
330 ret [i] = wrap (invoke->getArgOperand (i));
333 return ret;
336 void
337 mono_llvm_set_call_notailcall (LLVMValueRef func)
339 unwrap<CallInst>(func)->setTailCallKind (CallInst::TailCallKind::TCK_NoTail);
342 void
343 mono_llvm_set_call_noalias_ret (LLVMValueRef wrapped_calli)
345 Instruction *calli = unwrap<Instruction> (wrapped_calli);
347 if (isa<CallInst> (calli))
348 dyn_cast<CallInst>(calli)->addAttribute (AttributeList::ReturnIndex, Attribute::NoAlias);
349 else
350 dyn_cast<InvokeInst>(calli)->addAttribute (AttributeList::ReturnIndex, Attribute::NoAlias);
353 static Attribute::AttrKind
354 convert_attr (AttrKind kind)
356 switch (kind) {
357 case LLVM_ATTR_NO_UNWIND:
358 return Attribute::NoUnwind;
359 case LLVM_ATTR_NO_INLINE:
360 return Attribute::NoInline;
361 case LLVM_ATTR_OPTIMIZE_FOR_SIZE:
362 return Attribute::OptimizeForSize;
363 case LLVM_ATTR_IN_REG:
364 return Attribute::InReg;
365 case LLVM_ATTR_STRUCT_RET:
366 return Attribute::StructRet;
367 case LLVM_ATTR_NO_ALIAS:
368 return Attribute::NoAlias;
369 case LLVM_ATTR_BY_VAL:
370 return Attribute::ByVal;
371 case LLVM_ATTR_UW_TABLE:
372 return Attribute::UWTable;
373 default:
374 assert (0);
375 return Attribute::NoUnwind;
379 void
380 mono_llvm_add_func_attr (LLVMValueRef func, AttrKind kind)
382 unwrap<Function> (func)->addAttribute (AttributeList::FunctionIndex, convert_attr (kind));
385 void
386 mono_llvm_add_param_attr (LLVMValueRef param, AttrKind kind)
388 Function *func = unwrap<Argument> (param)->getParent ();
389 int n = unwrap<Argument> (param)->getArgNo ();
390 func->addParamAttr (n, convert_attr (kind));
393 void
394 mono_llvm_add_instr_attr (LLVMValueRef val, int index, AttrKind kind)
396 CallSite (unwrap<Instruction> (val)).addAttribute (index, convert_attr (kind));
399 void*
400 mono_llvm_create_di_builder (LLVMModuleRef module)
402 return new DIBuilder (*unwrap(module));
405 void*
406 mono_llvm_di_create_compile_unit (void *di_builder, const char *cu_name, const char *dir, const char *producer)
408 DIBuilder *builder = (DIBuilder*)di_builder;
410 DIFile *di_file;
412 di_file = builder->createFile (cu_name, dir);
413 return builder->createCompileUnit (dwarf::DW_LANG_C99, di_file, producer, true, "", 0);
416 void*
417 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)
419 DIBuilder *builder = (DIBuilder*)di_builder;
420 DIFile *di_file;
421 DISubroutineType *type;
422 DISubprogram *di_func;
424 // FIXME: Share DIFile
425 di_file = builder->createFile (file, dir);
426 type = builder->createSubroutineType (builder->getOrCreateTypeArray (ArrayRef<Metadata*> ()));
427 #if LLVM_API_VERSION >= 900
428 di_func = builder->createFunction (di_file, name, mangled_name, di_file, line, type, 0);
429 #else
430 di_func = builder->createFunction (di_file, name, mangled_name, di_file, line, type, true, true, 0);
431 #endif
433 unwrap<Function>(func)->setMetadata ("dbg", di_func);
435 return di_func;
438 void*
439 mono_llvm_di_create_file (void *di_builder, const char *dir, const char *file)
441 DIBuilder *builder = (DIBuilder*)di_builder;
443 return builder->createFile (file, dir);
446 void*
447 mono_llvm_di_create_location (void *di_builder, void *scope, int row, int column)
449 return DILocation::get (*unwrap(LLVMGetGlobalContext ()), row, column, (Metadata*)scope);
452 void
453 mono_llvm_di_set_location (LLVMBuilderRef builder, void *loc_md)
455 unwrap(builder)->SetCurrentDebugLocation ((DILocation*)loc_md);
458 void
459 mono_llvm_di_builder_finalize (void *di_builder)
461 DIBuilder *builder = (DIBuilder*)di_builder;
463 builder->finalize ();
466 LLVMValueRef
467 mono_llvm_get_or_insert_gc_safepoint_poll (LLVMModuleRef module)
469 #if LLVM_API_VERSION >= 900
471 llvm::FunctionCallee callee = unwrap(module)->getOrInsertFunction("gc.safepoint_poll", FunctionType::get(unwrap(LLVMVoidType()), false));
472 return wrap (dyn_cast<llvm::Function> (callee.getCallee ()));
473 #else
474 llvm::Function *SafepointPoll;
475 llvm::Constant *SafepointPollConstant;
477 SafepointPollConstant = unwrap(module)->getOrInsertFunction("gc.safepoint_poll", FunctionType::get(unwrap(LLVMVoidType()), false));
478 g_assert (SafepointPollConstant);
480 SafepointPoll = dyn_cast<llvm::Function>(SafepointPollConstant);
481 g_assert (SafepointPoll);
482 g_assert (SafepointPoll->empty());
484 return wrap(SafepointPoll);
485 #endif