[runtime] Transition the trampoline code to use memory managers for memory allocation...
[mono-project.git] / mono / mini / mini-llvm-cpp.cpp
blobdd9138ef6c2888c8eebcb36524035e1d54ac3b12
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>
40 #include <llvm/IR/MDBuilder.h>
42 #include "mini-llvm-cpp.h"
44 using namespace llvm;
46 #define Acquire AtomicOrdering::Acquire
47 #define Release AtomicOrdering::Release
48 #define SequentiallyConsistent AtomicOrdering::SequentiallyConsistent
50 void
51 mono_llvm_dump_value (LLVMValueRef value)
53 /* Same as LLVMDumpValue (), but print to stdout */
54 fflush (stdout);
55 outs () << (*unwrap<Value> (value)) << "\n";
56 outs ().flush ();
59 void
60 mono_llvm_dump_module (LLVMModuleRef module)
62 /* Same as LLVMDumpModule (), but print to stdout */
63 fflush (stdout);
64 outs () << (*unwrap (module));
65 outs ().flush ();
68 /* Missing overload for building an alloca with an alignment */
69 LLVMValueRef
70 mono_llvm_build_alloca (LLVMBuilderRef builder, LLVMTypeRef Ty,
71 LLVMValueRef ArraySize,
72 int alignment, const char *Name)
74 return wrap (unwrap (builder)->Insert (new AllocaInst (unwrap (Ty), 0, unwrap (ArraySize), alignment), Name));
77 LLVMValueRef
78 mono_llvm_build_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
79 const char *Name, gboolean is_volatile)
81 LoadInst *ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
83 return wrap(ins);
86 LLVMValueRef
87 mono_llvm_build_atomic_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
88 const char *Name, gboolean is_volatile, int alignment, BarrierKind barrier)
90 LoadInst *ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
92 ins->setAlignment (alignment);
93 switch (barrier) {
94 case LLVM_BARRIER_NONE:
95 break;
96 case LLVM_BARRIER_ACQ:
97 ins->setOrdering(Acquire);
98 break;
99 case LLVM_BARRIER_SEQ:
100 ins->setOrdering(SequentiallyConsistent);
101 break;
102 default:
103 g_assert_not_reached ();
104 break;
107 return wrap(ins);
110 LLVMValueRef
111 mono_llvm_build_aligned_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
112 const char *Name, gboolean is_volatile, int alignment)
114 LoadInst *ins;
116 ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
117 ins->setAlignment (alignment);
119 return wrap(ins);
122 LLVMValueRef
123 mono_llvm_build_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal,
124 gboolean is_volatile, BarrierKind barrier)
126 StoreInst *ins = unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile);
128 switch (barrier) {
129 case LLVM_BARRIER_NONE:
130 break;
131 case LLVM_BARRIER_REL:
132 ins->setOrdering(Release);
133 break;
134 case LLVM_BARRIER_SEQ:
135 ins->setOrdering(SequentiallyConsistent);
136 break;
137 default:
138 g_assert_not_reached ();
139 break;
142 return wrap(ins);
145 LLVMValueRef
146 mono_llvm_build_aligned_store (LLVMBuilderRef builder, LLVMValueRef Val, LLVMValueRef PointerVal,
147 gboolean is_volatile, int alignment)
149 StoreInst *ins;
151 ins = unwrap(builder)->CreateStore(unwrap(Val), unwrap(PointerVal), is_volatile);
152 ins->setAlignment (alignment);
154 return wrap (ins);
157 LLVMValueRef
158 mono_llvm_build_cmpxchg (LLVMBuilderRef builder, LLVMValueRef ptr, LLVMValueRef cmp, LLVMValueRef val)
160 AtomicCmpXchgInst *ins;
162 ins = unwrap(builder)->CreateAtomicCmpXchg (unwrap(ptr), unwrap (cmp), unwrap (val), SequentiallyConsistent, SequentiallyConsistent);
163 return wrap (ins);
166 LLVMValueRef
167 mono_llvm_build_atomic_rmw (LLVMBuilderRef builder, AtomicRMWOp op, LLVMValueRef ptr, LLVMValueRef val)
169 AtomicRMWInst::BinOp aop = AtomicRMWInst::Xchg;
170 AtomicRMWInst *ins;
172 switch (op) {
173 case LLVM_ATOMICRMW_OP_XCHG:
174 aop = AtomicRMWInst::Xchg;
175 break;
176 case LLVM_ATOMICRMW_OP_ADD:
177 aop = AtomicRMWInst::Add;
178 break;
179 case LLVM_ATOMICRMW_OP_AND:
180 aop = AtomicRMWInst::And;
181 break;
182 case LLVM_ATOMICRMW_OP_OR:
183 aop = AtomicRMWInst::Or;
184 break;
185 default:
186 g_assert_not_reached ();
187 break;
190 ins = unwrap (builder)->CreateAtomicRMW (aop, unwrap (ptr), unwrap (val), SequentiallyConsistent);
191 return wrap (ins);
194 LLVMValueRef
195 mono_llvm_build_fence (LLVMBuilderRef builder, BarrierKind kind)
197 FenceInst *ins;
198 AtomicOrdering ordering;
200 g_assert (kind != LLVM_BARRIER_NONE);
202 switch (kind) {
203 case LLVM_BARRIER_ACQ:
204 ordering = Acquire;
205 break;
206 case LLVM_BARRIER_REL:
207 ordering = Release;
208 break;
209 case LLVM_BARRIER_SEQ:
210 ordering = SequentiallyConsistent;
211 break;
212 default:
213 g_assert_not_reached ();
214 break;
217 ins = unwrap (builder)->CreateFence (ordering);
218 return wrap (ins);
221 LLVMValueRef
222 mono_llvm_build_weighted_branch (LLVMBuilderRef builder, LLVMValueRef cond, LLVMBasicBlockRef t, LLVMBasicBlockRef f, uint32_t t_weight, uint32_t f_weight)
224 auto b = unwrap (builder);
225 auto &ctx = b->getContext ();
226 MDBuilder mdb{ctx};
227 auto weights = mdb.createBranchWeights (t_weight, f_weight);
228 auto ins = b->CreateCondBr (unwrap (cond), unwrap (t), unwrap (f), weights);
229 return wrap (ins);
232 LLVMValueRef
233 mono_llvm_build_exact_ashr (LLVMBuilderRef builder, LLVMValueRef lhs, LLVMValueRef rhs) {
234 auto b = unwrap (builder);
235 auto ins = b->CreateAShr (unwrap (lhs), unwrap (rhs), "", true);
236 return wrap (ins);
239 void
240 mono_llvm_add_string_metadata (LLVMValueRef insref, const char* label, const char* text)
242 auto ins = unwrap<Instruction> (insref);
243 auto &ctx = ins->getContext ();
244 ins->setMetadata (label, MDNode::get (ctx, MDString::get (ctx, text)));
247 void
248 mono_llvm_set_implicit_branch (LLVMBuilderRef builder, LLVMValueRef branch)
250 auto b = unwrap (builder);
251 auto &ctx = b->getContext ();
252 auto ins = unwrap<Instruction> (branch);
253 ins->setMetadata (LLVMContext::MD_make_implicit, MDNode::get (ctx, {}));
256 void
257 mono_llvm_set_must_tailcall (LLVMValueRef call_ins)
259 CallInst *ins = (CallInst*)unwrap (call_ins);
261 ins->setTailCallKind (CallInst::TailCallKind::TCK_MustTail);
264 void
265 mono_llvm_replace_uses_of (LLVMValueRef var, LLVMValueRef v)
267 Value *V = ConstantExpr::getTruncOrBitCast (unwrap<Constant> (v), unwrap (var)->getType ());
268 unwrap (var)->replaceAllUsesWith (V);
271 LLVMValueRef
272 mono_llvm_create_constant_data_array (const uint8_t *data, int len)
274 return wrap(ConstantDataArray::get (*unwrap(LLVMGetGlobalContext ()), makeArrayRef(data, len)));
277 void
278 mono_llvm_set_is_constant (LLVMValueRef global_var)
280 unwrap<GlobalVariable>(global_var)->setConstant (true);
283 // Note that in future versions of LLVM, CallInst and InvokeInst
284 // share a CallBase parent class that would make the below methods
285 // look much better
287 void
288 mono_llvm_set_call_nonnull_arg (LLVMValueRef wrapped_calli, int argNo)
290 Instruction *calli = unwrap<Instruction> (wrapped_calli);
292 if (isa<CallInst> (calli))
293 dyn_cast<CallInst>(calli)->addParamAttr (argNo, Attribute::NonNull);
294 else
295 dyn_cast<InvokeInst>(calli)->addParamAttr (argNo, Attribute::NonNull);
298 void
299 mono_llvm_set_call_nonnull_ret (LLVMValueRef wrapped_calli)
301 Instruction *calli = unwrap<Instruction> (wrapped_calli);
303 if (isa<CallInst> (calli))
304 dyn_cast<CallInst>(calli)->addAttribute (AttributeList::ReturnIndex, Attribute::NonNull);
305 else
306 dyn_cast<InvokeInst>(calli)->addAttribute (AttributeList::ReturnIndex, Attribute::NonNull);
309 void
310 mono_llvm_set_func_nonnull_arg (LLVMValueRef func, int argNo)
312 unwrap<Function>(func)->addParamAttr (argNo, Attribute::NonNull);
315 gboolean
316 mono_llvm_can_be_gep (LLVMValueRef base, LLVMValueRef* gep_base, LLVMValueRef* gep_offset)
318 #ifdef ENABLE_NETCORE
319 // Look for a pattern like this:
320 // %1 = ptrtoint i8* %gep_base to i64
321 // %2 = add i64 %1, %gep_offset
322 if (Instruction *base_inst = dyn_cast<Instruction> (unwrap (base))) {
323 if (base_inst->getOpcode () == Instruction::Add) {
324 if (Instruction *base_ptr_ins = dyn_cast<Instruction> (base_inst->getOperand (0))) {
325 if (base_ptr_ins->getOpcode () == Instruction::PtrToInt) {
326 *gep_base = wrap (base_ptr_ins->getOperand (0));
327 *gep_offset = wrap (base_inst->getOperand (1));
328 return TRUE;
333 #endif
334 return FALSE;
337 gboolean
338 mono_llvm_is_nonnull (LLVMValueRef wrapped)
340 // Argument to function
341 Value *val = unwrap (wrapped);
343 while (val) {
344 if (Argument *arg = dyn_cast<Argument> (val)) {
345 return arg->hasNonNullAttr ();
346 } else if (CallInst *calli = dyn_cast<CallInst> (val)) {
347 return calli->hasRetAttr (Attribute::NonNull);
348 } else if (InvokeInst *calli = dyn_cast<InvokeInst> (val)) {
349 return calli->hasRetAttr (Attribute::NonNull);
350 } else if (LoadInst *loadi = dyn_cast<LoadInst> (val)) {
351 return loadi->getMetadata("nonnull") != nullptr; // nonnull <index>
352 } else if (Instruction *inst = dyn_cast<Instruction> (val)) {
353 // If not a load or a function argument, the only case for us to
354 // consider is that it's a bitcast. If so, recurse on what was casted.
355 if (inst->getOpcode () == LLVMBitCast) {
356 val = inst->getOperand (0);
357 continue;
360 return FALSE;
361 } else {
362 return FALSE;
365 return FALSE;
368 GSList *
369 mono_llvm_calls_using (LLVMValueRef wrapped_local)
371 GSList *usages = NULL;
372 Value *local = unwrap (wrapped_local);
374 for (User *user : local->users ()) {
375 if (isa<CallInst> (user) || isa<InvokeInst> (user)) {
376 usages = g_slist_prepend (usages, wrap (user));
380 return usages;
383 LLVMValueRef *
384 mono_llvm_call_args (LLVMValueRef wrapped_calli)
386 Value *calli = unwrap(wrapped_calli);
387 CallInst *call = dyn_cast <CallInst> (calli);
388 InvokeInst *invoke = dyn_cast <InvokeInst> (calli);
389 g_assert (call || invoke);
391 unsigned int numOperands;
393 if (call)
394 numOperands = call->getNumArgOperands ();
395 else
396 numOperands = invoke->getNumArgOperands ();
398 LLVMValueRef *ret = g_malloc (sizeof (LLVMValueRef) * numOperands);
400 for (unsigned int i = 0; i < numOperands; i++) {
401 if (call)
402 ret [i] = wrap (call->getArgOperand (i));
403 else
404 ret [i] = wrap (invoke->getArgOperand (i));
407 return ret;
410 void
411 mono_llvm_set_call_notailcall (LLVMValueRef func)
413 unwrap<CallInst>(func)->setTailCallKind (CallInst::TailCallKind::TCK_NoTail);
416 void
417 mono_llvm_set_call_noalias_ret (LLVMValueRef wrapped_calli)
419 Instruction *calli = unwrap<Instruction> (wrapped_calli);
421 if (isa<CallInst> (calli))
422 dyn_cast<CallInst>(calli)->addAttribute (AttributeList::ReturnIndex, Attribute::NoAlias);
423 else
424 dyn_cast<InvokeInst>(calli)->addAttribute (AttributeList::ReturnIndex, Attribute::NoAlias);
427 void
428 mono_llvm_set_alignment_ret (LLVMValueRef call, int alignment)
430 Instruction *ins = unwrap<Instruction> (call);
431 auto &ctx = ins->getContext ();
432 if (isa<CallInst> (ins))
433 dyn_cast<CallInst>(ins)->addAttribute (AttributeList::ReturnIndex, Attribute::getWithAlignment(ctx, alignment));
434 else
435 dyn_cast<InvokeInst>(ins)->addAttribute (AttributeList::ReturnIndex, Attribute::getWithAlignment(ctx, alignment));
438 static Attribute::AttrKind
439 convert_attr (AttrKind kind)
441 switch (kind) {
442 case LLVM_ATTR_NO_UNWIND:
443 return Attribute::NoUnwind;
444 case LLVM_ATTR_NO_INLINE:
445 return Attribute::NoInline;
446 case LLVM_ATTR_OPTIMIZE_FOR_SIZE:
447 return Attribute::OptimizeForSize;
448 case LLVM_ATTR_OPTIMIZE_NONE:
449 return Attribute::OptimizeNone;
450 case LLVM_ATTR_IN_REG:
451 return Attribute::InReg;
452 case LLVM_ATTR_STRUCT_RET:
453 return Attribute::StructRet;
454 case LLVM_ATTR_NO_ALIAS:
455 return Attribute::NoAlias;
456 case LLVM_ATTR_BY_VAL:
457 return Attribute::ByVal;
458 case LLVM_ATTR_UW_TABLE:
459 return Attribute::UWTable;
460 default:
461 assert (0);
462 return Attribute::NoUnwind;
466 void
467 mono_llvm_add_func_attr (LLVMValueRef func, AttrKind kind)
469 unwrap<Function> (func)->addAttribute (AttributeList::FunctionIndex, convert_attr (kind));
472 void
473 mono_llvm_add_func_attr_nv (LLVMValueRef func, const char *attr_name, const char *attr_value)
475 AttrBuilder NewAttrs;
476 NewAttrs.addAttribute (attr_name, attr_value);
477 unwrap<Function> (func)->addAttributes (AttributeList::FunctionIndex, NewAttrs);
480 void
481 mono_llvm_add_param_attr (LLVMValueRef param, AttrKind kind)
483 Function *func = unwrap<Argument> (param)->getParent ();
484 int n = unwrap<Argument> (param)->getArgNo ();
485 func->addParamAttr (n, convert_attr (kind));
488 void
489 mono_llvm_add_instr_attr (LLVMValueRef val, int index, AttrKind kind)
491 CallSite (unwrap<Instruction> (val)).addAttribute (index, convert_attr (kind));
494 void*
495 mono_llvm_create_di_builder (LLVMModuleRef module)
497 return new DIBuilder (*unwrap(module));
500 void*
501 mono_llvm_di_create_compile_unit (void *di_builder, const char *cu_name, const char *dir, const char *producer)
503 DIBuilder *builder = (DIBuilder*)di_builder;
505 DIFile *di_file;
507 di_file = builder->createFile (cu_name, dir);
508 return builder->createCompileUnit (dwarf::DW_LANG_C99, di_file, producer, true, "", 0);
511 void*
512 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)
514 DIBuilder *builder = (DIBuilder*)di_builder;
515 DIFile *di_file;
516 DISubroutineType *type;
517 DISubprogram *di_func;
519 // FIXME: Share DIFile
520 di_file = builder->createFile (file, dir);
521 type = builder->createSubroutineType (builder->getOrCreateTypeArray (ArrayRef<Metadata*> ()));
522 #if LLVM_API_VERSION >= 900
523 di_func = builder->createFunction (
524 di_file, name, mangled_name, di_file, line, type, 0,
525 DINode::FlagZero, DISubprogram::SPFlagDefinition | DISubprogram::SPFlagLocalToUnit);
526 #else
527 di_func = builder->createFunction (di_file, name, mangled_name, di_file, line, type, true, true, 0);
528 #endif
530 unwrap<Function>(func)->setMetadata ("dbg", di_func);
532 return di_func;
535 void*
536 mono_llvm_di_create_file (void *di_builder, const char *dir, const char *file)
538 DIBuilder *builder = (DIBuilder*)di_builder;
540 return builder->createFile (file, dir);
543 void*
544 mono_llvm_di_create_location (void *di_builder, void *scope, int row, int column)
546 return DILocation::get (*unwrap(LLVMGetGlobalContext ()), row, column, (Metadata*)scope);
549 void
550 mono_llvm_set_fast_math (LLVMBuilderRef builder)
552 FastMathFlags flags;
553 flags.setFast ();
554 unwrap(builder)->setFastMathFlags (flags);
557 void
558 mono_llvm_di_set_location (LLVMBuilderRef builder, void *loc_md)
560 unwrap(builder)->SetCurrentDebugLocation ((DILocation*)loc_md);
563 void
564 mono_llvm_di_builder_finalize (void *di_builder)
566 DIBuilder *builder = (DIBuilder*)di_builder;
568 builder->finalize ();
571 LLVMValueRef
572 mono_llvm_get_or_insert_gc_safepoint_poll (LLVMModuleRef module)
574 #if LLVM_API_VERSION >= 900
576 llvm::FunctionCallee callee = unwrap(module)->getOrInsertFunction("gc.safepoint_poll", FunctionType::get(unwrap(LLVMVoidType()), false));
577 return wrap (dyn_cast<llvm::Function> (callee.getCallee ()));
578 #else
579 llvm::Function *SafepointPoll;
580 llvm::Constant *SafepointPollConstant;
582 SafepointPollConstant = unwrap(module)->getOrInsertFunction("gc.safepoint_poll", FunctionType::get(unwrap(LLVMVoidType()), false));
583 g_assert (SafepointPollConstant);
585 SafepointPoll = dyn_cast<llvm::Function>(SafepointPollConstant);
586 g_assert (SafepointPoll);
587 g_assert (SafepointPoll->empty());
589 return wrap(SafepointPoll);
590 #endif
593 gboolean
594 mono_llvm_remove_gc_safepoint_poll (LLVMModuleRef module)
596 llvm::Function *func = unwrap (module)->getFunction ("gc.safepoint_poll");
597 if (func == nullptr)
598 return FALSE;
599 func->eraseFromParent ();
600 return TRUE;
604 mono_llvm_check_cpu_features (const CpuFeatureAliasFlag *features, int length)
606 int flags = 0;
607 llvm::StringMap<bool> HostFeatures;
608 if (llvm::sys::getHostCPUFeatures (HostFeatures)) {
609 for (int i=0; i<length; i++) {
610 CpuFeatureAliasFlag feature = features [i];
611 if (HostFeatures [feature.alias])
612 flags |= feature.flag;
615 for (auto &F : HostFeatures)
616 if (F.second)
617 outs () << "X: " << F.first () << "\n";
620 return flags;
623 /* Map our intrinsic ID to the LLVM intrinsic id */
624 static Intrinsic::ID
625 get_intrins_id (IntrinsicId id)
627 Intrinsic::ID intrins_id = Intrinsic::ID::not_intrinsic;
628 switch (id) {
629 #define INTRINS(id, llvm_id) case INTRINS_ ## id: intrins_id = Intrinsic::ID::llvm_id; break;
630 #define INTRINS_OVR(id, llvm_id) case INTRINS_ ## id: intrins_id = Intrinsic::ID::llvm_id; break;
631 #include "llvm-intrinsics.h"
632 default:
633 break;
635 return intrins_id;
638 static bool
639 is_overloaded_intrins (IntrinsicId id)
641 switch (id) {
642 #define INTRINS(id, llvm_id)
643 #define INTRINS_OVR(id, llvm_id) case INTRINS_ ## id: return true;
644 #include "llvm-intrinsics.h"
645 default:
646 break;
648 return false;
652 * mono_llvm_register_intrinsic:
654 * Register an LLVM intrinsic identified by ID.
656 LLVMValueRef
657 mono_llvm_register_intrinsic (LLVMModuleRef module, IntrinsicId id)
659 if (is_overloaded_intrins (id))
660 return NULL;
662 auto intrins_id = get_intrins_id (id);
663 if (intrins_id != Intrinsic::ID::not_intrinsic) {
664 Function *f = Intrinsic::getDeclaration (unwrap (module), intrins_id);
665 if (!f) {
666 outs () << id << "\n";
667 g_assert_not_reached ();
669 return wrap (f);
670 } else {
671 return NULL;
676 * mono_llvm_register_intrinsic:
678 * Register an overloaded LLVM intrinsic identified by ID using the supplied types.
680 LLVMValueRef
681 mono_llvm_register_overloaded_intrinsic (LLVMModuleRef module, IntrinsicId id, LLVMTypeRef *types, int ntypes)
683 auto intrins_id = get_intrins_id (id);
685 const int max_types = 5;
686 g_assert (ntypes <= max_types);
687 Type *arr [max_types];
688 for (int i = 0; i < ntypes; ++i)
689 arr [i] = unwrap (types [i]);
690 auto f = Intrinsic::getDeclaration (unwrap (module), intrins_id, { arr, (size_t)ntypes });
691 return wrap (f);