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
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)
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"
46 #define Acquire AtomicOrdering::Acquire
47 #define Release AtomicOrdering::Release
48 #define SequentiallyConsistent AtomicOrdering::SequentiallyConsistent
51 mono_llvm_dump_value (LLVMValueRef value
)
53 /* Same as LLVMDumpValue (), but print to stdout */
55 outs () << (*unwrap
<Value
> (value
)) << "\n";
60 mono_llvm_dump_module (LLVMModuleRef module
)
62 /* Same as LLVMDumpModule (), but print to stdout */
64 outs () << (*unwrap (module
));
68 /* Missing overload for building an alloca with an alignment */
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
));
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
);
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
);
94 case LLVM_BARRIER_NONE
:
96 case LLVM_BARRIER_ACQ
:
97 ins
->setOrdering(Acquire
);
99 case LLVM_BARRIER_SEQ
:
100 ins
->setOrdering(SequentiallyConsistent
);
103 g_assert_not_reached ();
111 mono_llvm_build_aligned_load (LLVMBuilderRef builder
, LLVMValueRef PointerVal
,
112 const char *Name
, gboolean is_volatile
, int alignment
)
116 ins
= unwrap(builder
)->CreateLoad(unwrap(PointerVal
), is_volatile
, Name
);
117 ins
->setAlignment (alignment
);
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
);
129 case LLVM_BARRIER_NONE
:
131 case LLVM_BARRIER_REL
:
132 ins
->setOrdering(Release
);
134 case LLVM_BARRIER_SEQ
:
135 ins
->setOrdering(SequentiallyConsistent
);
138 g_assert_not_reached ();
146 mono_llvm_build_aligned_store (LLVMBuilderRef builder
, LLVMValueRef Val
, LLVMValueRef PointerVal
,
147 gboolean is_volatile
, int alignment
)
151 ins
= unwrap(builder
)->CreateStore(unwrap(Val
), unwrap(PointerVal
), is_volatile
);
152 ins
->setAlignment (alignment
);
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
);
167 mono_llvm_build_atomic_rmw (LLVMBuilderRef builder
, AtomicRMWOp op
, LLVMValueRef ptr
, LLVMValueRef val
)
169 AtomicRMWInst::BinOp aop
= AtomicRMWInst::Xchg
;
173 case LLVM_ATOMICRMW_OP_XCHG
:
174 aop
= AtomicRMWInst::Xchg
;
176 case LLVM_ATOMICRMW_OP_ADD
:
177 aop
= AtomicRMWInst::Add
;
179 case LLVM_ATOMICRMW_OP_AND
:
180 aop
= AtomicRMWInst::And
;
182 case LLVM_ATOMICRMW_OP_OR
:
183 aop
= AtomicRMWInst::Or
;
186 g_assert_not_reached ();
190 ins
= unwrap (builder
)->CreateAtomicRMW (aop
, unwrap (ptr
), unwrap (val
), SequentiallyConsistent
);
195 mono_llvm_build_fence (LLVMBuilderRef builder
, BarrierKind kind
)
198 AtomicOrdering ordering
;
200 g_assert (kind
!= LLVM_BARRIER_NONE
);
203 case LLVM_BARRIER_ACQ
:
206 case LLVM_BARRIER_REL
:
209 case LLVM_BARRIER_SEQ
:
210 ordering
= SequentiallyConsistent
;
213 g_assert_not_reached ();
217 ins
= unwrap (builder
)->CreateFence (ordering
);
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 ();
227 auto weights
= mdb
.createBranchWeights (t_weight
, f_weight
);
228 auto ins
= b
->CreateCondBr (unwrap (cond
), unwrap (t
), unwrap (f
), weights
);
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);
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
)));
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
, {}));
257 mono_llvm_set_must_tailcall (LLVMValueRef call_ins
)
259 CallInst
*ins
= (CallInst
*)unwrap (call_ins
);
261 ins
->setTailCallKind (CallInst::TailCallKind::TCK_MustTail
);
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
);
272 mono_llvm_create_constant_data_array (const uint8_t *data
, int len
)
274 return wrap(ConstantDataArray::get (*unwrap(LLVMGetGlobalContext ()), makeArrayRef(data
, len
)));
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
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
);
295 dyn_cast
<InvokeInst
>(calli
)->addParamAttr (argNo
, Attribute::NonNull
);
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
);
306 dyn_cast
<InvokeInst
>(calli
)->addAttribute (AttributeList::ReturnIndex
, Attribute::NonNull
);
310 mono_llvm_set_func_nonnull_arg (LLVMValueRef func
, int argNo
)
312 unwrap
<Function
>(func
)->addParamAttr (argNo
, Attribute::NonNull
);
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));
338 mono_llvm_is_nonnull (LLVMValueRef wrapped
)
340 // Argument to function
341 Value
*val
= unwrap (wrapped
);
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);
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
));
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
;
394 numOperands
= call
->getNumArgOperands ();
396 numOperands
= invoke
->getNumArgOperands ();
398 LLVMValueRef
*ret
= g_malloc (sizeof (LLVMValueRef
) * numOperands
);
400 for (unsigned int i
= 0; i
< numOperands
; i
++) {
402 ret
[i
] = wrap (call
->getArgOperand (i
));
404 ret
[i
] = wrap (invoke
->getArgOperand (i
));
411 mono_llvm_set_call_notailcall (LLVMValueRef func
)
413 unwrap
<CallInst
>(func
)->setTailCallKind (CallInst::TailCallKind::TCK_NoTail
);
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
);
424 dyn_cast
<InvokeInst
>(calli
)->addAttribute (AttributeList::ReturnIndex
, Attribute::NoAlias
);
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
));
435 dyn_cast
<InvokeInst
>(ins
)->addAttribute (AttributeList::ReturnIndex
, Attribute::getWithAlignment(ctx
, alignment
));
438 static Attribute::AttrKind
439 convert_attr (AttrKind 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
;
462 return Attribute::NoUnwind
;
467 mono_llvm_add_func_attr (LLVMValueRef func
, AttrKind kind
)
469 unwrap
<Function
> (func
)->addAttribute (AttributeList::FunctionIndex
, convert_attr (kind
));
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
);
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
));
489 mono_llvm_add_instr_attr (LLVMValueRef val
, int index
, AttrKind kind
)
491 CallSite (unwrap
<Instruction
> (val
)).addAttribute (index
, convert_attr (kind
));
495 mono_llvm_create_di_builder (LLVMModuleRef module
)
497 return new DIBuilder (*unwrap(module
));
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
;
507 di_file
= builder
->createFile (cu_name
, dir
);
508 return builder
->createCompileUnit (dwarf::DW_LANG_C99
, di_file
, producer
, true, "", 0);
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
;
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
);
527 di_func
= builder
->createFunction (di_file
, name
, mangled_name
, di_file
, line
, type
, true, true, 0);
530 unwrap
<Function
>(func
)->setMetadata ("dbg", di_func
);
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
);
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
);
550 mono_llvm_set_fast_math (LLVMBuilderRef builder
)
554 unwrap(builder
)->setFastMathFlags (flags
);
558 mono_llvm_di_set_location (LLVMBuilderRef builder
, void *loc_md
)
560 unwrap(builder
)->SetCurrentDebugLocation ((DILocation
*)loc_md
);
564 mono_llvm_di_builder_finalize (void *di_builder
)
566 DIBuilder
*builder
= (DIBuilder
*)di_builder
;
568 builder
->finalize ();
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 ()));
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
);
594 mono_llvm_remove_gc_safepoint_poll (LLVMModuleRef module
)
596 llvm::Function
*func
= unwrap (module
)->getFunction ("gc.safepoint_poll");
599 func
->eraseFromParent ();
604 mono_llvm_check_cpu_features (const CpuFeatureAliasFlag
*features
, int length
)
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)
617 outs () << "X: " << F.first () << "\n";
623 /* Map our intrinsic ID to the LLVM intrinsic id */
625 get_intrins_id (IntrinsicId id
)
627 Intrinsic::ID intrins_id
= Intrinsic::ID::not_intrinsic
;
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"
639 is_overloaded_intrins (IntrinsicId id
)
642 #define INTRINS(id, llvm_id)
643 #define INTRINS_OVR(id, llvm_id) case INTRINS_ ## id: return true;
644 #include "llvm-intrinsics.h"
652 * mono_llvm_register_intrinsic:
654 * Register an LLVM intrinsic identified by ID.
657 mono_llvm_register_intrinsic (LLVMModuleRef module
, IntrinsicId id
)
659 if (is_overloaded_intrins (id
))
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
);
666 outs () << id
<< "\n";
667 g_assert_not_reached ();
676 * mono_llvm_register_intrinsic:
678 * Register an overloaded LLVM intrinsic identified by ID using the supplied types.
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
});