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 */
54 outs () << (*unwrap
<Value
> (value
)) << "\n";
59 mono_llvm_dump_module (LLVMModuleRef module
)
61 /* Same as LLVMDumpModule (), but print to stdout */
62 outs () << (*unwrap (module
));
66 /* Missing overload for building an alloca with an alignment */
68 mono_llvm_build_alloca (LLVMBuilderRef builder
, LLVMTypeRef Ty
,
69 LLVMValueRef ArraySize
,
70 int alignment
, const char *Name
)
72 return wrap (unwrap (builder
)->Insert (new AllocaInst (unwrap (Ty
), 0, unwrap (ArraySize
), alignment
), Name
));
76 mono_llvm_build_load (LLVMBuilderRef builder
, LLVMValueRef PointerVal
,
77 const char *Name
, gboolean is_volatile
)
79 LoadInst
*ins
= unwrap(builder
)->CreateLoad(unwrap(PointerVal
), is_volatile
, Name
);
85 mono_llvm_build_atomic_load (LLVMBuilderRef builder
, LLVMValueRef PointerVal
,
86 const char *Name
, gboolean is_volatile
, int alignment
, BarrierKind barrier
)
88 LoadInst
*ins
= unwrap(builder
)->CreateLoad(unwrap(PointerVal
), is_volatile
, Name
);
90 ins
->setAlignment (alignment
);
92 case LLVM_BARRIER_NONE
:
94 case LLVM_BARRIER_ACQ
:
95 ins
->setOrdering(Acquire
);
97 case LLVM_BARRIER_SEQ
:
98 ins
->setOrdering(SequentiallyConsistent
);
101 g_assert_not_reached ();
109 mono_llvm_build_aligned_load (LLVMBuilderRef builder
, LLVMValueRef PointerVal
,
110 const char *Name
, gboolean is_volatile
, int alignment
)
114 ins
= unwrap(builder
)->CreateLoad(unwrap(PointerVal
), is_volatile
, Name
);
115 ins
->setAlignment (alignment
);
121 mono_llvm_build_store (LLVMBuilderRef builder
, LLVMValueRef Val
, LLVMValueRef PointerVal
,
122 gboolean is_volatile
, BarrierKind barrier
)
124 StoreInst
*ins
= unwrap(builder
)->CreateStore(unwrap(Val
), unwrap(PointerVal
), is_volatile
);
127 case LLVM_BARRIER_NONE
:
129 case LLVM_BARRIER_REL
:
130 ins
->setOrdering(Release
);
132 case LLVM_BARRIER_SEQ
:
133 ins
->setOrdering(SequentiallyConsistent
);
136 g_assert_not_reached ();
144 mono_llvm_build_aligned_store (LLVMBuilderRef builder
, LLVMValueRef Val
, LLVMValueRef PointerVal
,
145 gboolean is_volatile
, int alignment
)
149 ins
= unwrap(builder
)->CreateStore(unwrap(Val
), unwrap(PointerVal
), is_volatile
);
150 ins
->setAlignment (alignment
);
156 mono_llvm_build_cmpxchg (LLVMBuilderRef builder
, LLVMValueRef ptr
, LLVMValueRef cmp
, LLVMValueRef val
)
158 AtomicCmpXchgInst
*ins
;
160 ins
= unwrap(builder
)->CreateAtomicCmpXchg (unwrap(ptr
), unwrap (cmp
), unwrap (val
), SequentiallyConsistent
, SequentiallyConsistent
);
165 mono_llvm_build_atomic_rmw (LLVMBuilderRef builder
, AtomicRMWOp op
, LLVMValueRef ptr
, LLVMValueRef val
)
167 AtomicRMWInst::BinOp aop
= AtomicRMWInst::Xchg
;
171 case LLVM_ATOMICRMW_OP_XCHG
:
172 aop
= AtomicRMWInst::Xchg
;
174 case LLVM_ATOMICRMW_OP_ADD
:
175 aop
= AtomicRMWInst::Add
;
178 g_assert_not_reached ();
182 ins
= unwrap (builder
)->CreateAtomicRMW (aop
, unwrap (ptr
), unwrap (val
), SequentiallyConsistent
);
187 mono_llvm_build_fence (LLVMBuilderRef builder
, BarrierKind kind
)
190 AtomicOrdering ordering
;
192 g_assert (kind
!= LLVM_BARRIER_NONE
);
195 case LLVM_BARRIER_ACQ
:
198 case LLVM_BARRIER_REL
:
201 case LLVM_BARRIER_SEQ
:
202 ordering
= SequentiallyConsistent
;
205 g_assert_not_reached ();
209 ins
= unwrap (builder
)->CreateFence (ordering
);
214 mono_llvm_build_weighted_branch (LLVMBuilderRef builder
, LLVMValueRef cond
, LLVMBasicBlockRef t
, LLVMBasicBlockRef f
, uint32_t t_weight
, uint32_t f_weight
)
216 auto b
= unwrap (builder
);
217 auto &ctx
= b
->getContext ();
219 auto weights
= mdb
.createBranchWeights (t_weight
, f_weight
);
220 auto ins
= b
->CreateCondBr (unwrap (cond
), unwrap (t
), unwrap (f
), weights
);
225 mono_llvm_add_string_metadata (LLVMValueRef insref
, const char* label
, const char* text
)
227 auto ins
= unwrap
<Instruction
> (insref
);
228 auto &ctx
= ins
->getContext ();
229 ins
->setMetadata (label
, MDNode::get (ctx
, MDString::get (ctx
, text
)));
233 mono_llvm_set_implicit_branch (LLVMBuilderRef builder
, LLVMValueRef branch
)
235 auto b
= unwrap (builder
);
236 auto &ctx
= b
->getContext ();
237 auto ins
= unwrap
<Instruction
> (branch
);
238 ins
->setMetadata (LLVMContext::MD_make_implicit
, MDNode::get (ctx
, {}));
242 mono_llvm_set_must_tailcall (LLVMValueRef call_ins
)
244 CallInst
*ins
= (CallInst
*)unwrap (call_ins
);
246 ins
->setTailCallKind (CallInst::TailCallKind::TCK_MustTail
);
250 mono_llvm_replace_uses_of (LLVMValueRef var
, LLVMValueRef v
)
252 Value
*V
= ConstantExpr::getTruncOrBitCast (unwrap
<Constant
> (v
), unwrap (var
)->getType ());
253 unwrap (var
)->replaceAllUsesWith (V
);
257 mono_llvm_create_constant_data_array (const uint8_t *data
, int len
)
259 return wrap(ConstantDataArray::get (*unwrap(LLVMGetGlobalContext ()), makeArrayRef(data
, len
)));
263 mono_llvm_set_is_constant (LLVMValueRef global_var
)
265 unwrap
<GlobalVariable
>(global_var
)->setConstant (true);
268 // Note that in future versions of LLVM, CallInst and InvokeInst
269 // share a CallBase parent class that would make the below methods
273 mono_llvm_set_call_nonnull_arg (LLVMValueRef wrapped_calli
, int argNo
)
275 Instruction
*calli
= unwrap
<Instruction
> (wrapped_calli
);
277 if (isa
<CallInst
> (calli
))
278 dyn_cast
<CallInst
>(calli
)->addParamAttr (argNo
, Attribute::NonNull
);
280 dyn_cast
<InvokeInst
>(calli
)->addParamAttr (argNo
, Attribute::NonNull
);
284 mono_llvm_set_call_nonnull_ret (LLVMValueRef wrapped_calli
)
286 Instruction
*calli
= unwrap
<Instruction
> (wrapped_calli
);
288 if (isa
<CallInst
> (calli
))
289 dyn_cast
<CallInst
>(calli
)->addAttribute (AttributeList::ReturnIndex
, Attribute::NonNull
);
291 dyn_cast
<InvokeInst
>(calli
)->addAttribute (AttributeList::ReturnIndex
, Attribute::NonNull
);
295 mono_llvm_set_func_nonnull_arg (LLVMValueRef func
, int argNo
)
297 unwrap
<Function
>(func
)->addParamAttr (argNo
, Attribute::NonNull
);
301 mono_llvm_can_be_gep (LLVMValueRef base
, LLVMValueRef
* gep_base
, LLVMValueRef
* gep_offset
)
303 #ifdef ENABLE_NETCORE
304 // Look for a pattern like this:
305 // %1 = ptrtoint i8* %gep_base to i64
306 // %2 = add i64 %1, %gep_offset
307 if (Instruction
*base_inst
= dyn_cast
<Instruction
> (unwrap (base
))) {
308 if (base_inst
->getOpcode () == Instruction::Add
) {
309 if (Instruction
*base_ptr_ins
= dyn_cast
<Instruction
> (base_inst
->getOperand (0))) {
310 if (base_ptr_ins
->getOpcode () == Instruction::PtrToInt
) {
311 *gep_base
= wrap (base_ptr_ins
->getOperand (0));
312 *gep_offset
= wrap (base_inst
->getOperand (1));
323 mono_llvm_is_nonnull (LLVMValueRef wrapped
)
325 // Argument to function
326 Value
*val
= unwrap (wrapped
);
329 if (Argument
*arg
= dyn_cast
<Argument
> (val
)) {
330 return arg
->hasNonNullAttr ();
331 } else if (CallInst
*calli
= dyn_cast
<CallInst
> (val
)) {
332 return calli
->hasRetAttr (Attribute::NonNull
);
333 } else if (InvokeInst
*calli
= dyn_cast
<InvokeInst
> (val
)) {
334 return calli
->hasRetAttr (Attribute::NonNull
);
335 } else if (LoadInst
*loadi
= dyn_cast
<LoadInst
> (val
)) {
336 return loadi
->getMetadata("nonnull") != nullptr; // nonnull <index>
337 } else if (Instruction
*inst
= dyn_cast
<Instruction
> (val
)) {
338 // If not a load or a function argument, the only case for us to
339 // consider is that it's a bitcast. If so, recurse on what was casted.
340 if (inst
->getOpcode () == LLVMBitCast
) {
341 val
= inst
->getOperand (0);
354 mono_llvm_calls_using (LLVMValueRef wrapped_local
)
356 GSList
*usages
= NULL
;
357 Value
*local
= unwrap (wrapped_local
);
359 for (User
*user
: local
->users ()) {
360 if (isa
<CallInst
> (user
) || isa
<InvokeInst
> (user
)) {
361 usages
= g_slist_prepend (usages
, wrap (user
));
369 mono_llvm_call_args (LLVMValueRef wrapped_calli
)
371 Value
*calli
= unwrap(wrapped_calli
);
372 CallInst
*call
= dyn_cast
<CallInst
> (calli
);
373 InvokeInst
*invoke
= dyn_cast
<InvokeInst
> (calli
);
374 g_assert (call
|| invoke
);
376 unsigned int numOperands
= 0;
379 numOperands
= call
->getNumArgOperands ();
381 numOperands
= invoke
->getNumArgOperands ();
383 LLVMValueRef
*ret
= g_malloc (sizeof (LLVMValueRef
) * numOperands
);
385 for (int i
=0; i
< numOperands
; i
++) {
387 ret
[i
] = wrap (call
->getArgOperand (i
));
389 ret
[i
] = wrap (invoke
->getArgOperand (i
));
396 mono_llvm_set_call_notailcall (LLVMValueRef func
)
398 unwrap
<CallInst
>(func
)->setTailCallKind (CallInst::TailCallKind::TCK_NoTail
);
402 mono_llvm_set_call_noalias_ret (LLVMValueRef wrapped_calli
)
404 Instruction
*calli
= unwrap
<Instruction
> (wrapped_calli
);
406 if (isa
<CallInst
> (calli
))
407 dyn_cast
<CallInst
>(calli
)->addAttribute (AttributeList::ReturnIndex
, Attribute::NoAlias
);
409 dyn_cast
<InvokeInst
>(calli
)->addAttribute (AttributeList::ReturnIndex
, Attribute::NoAlias
);
413 mono_llvm_set_alignment_ret (LLVMValueRef call
, int alignment
)
415 Instruction
*ins
= unwrap
<Instruction
> (call
);
416 auto &ctx
= ins
->getContext ();
417 if (isa
<CallInst
> (ins
))
418 dyn_cast
<CallInst
>(ins
)->addAttribute (AttributeList::ReturnIndex
, Attribute::getWithAlignment(ctx
, alignment
));
420 dyn_cast
<InvokeInst
>(ins
)->addAttribute (AttributeList::ReturnIndex
, Attribute::getWithAlignment(ctx
, alignment
));
423 static Attribute::AttrKind
424 convert_attr (AttrKind kind
)
427 case LLVM_ATTR_NO_UNWIND
:
428 return Attribute::NoUnwind
;
429 case LLVM_ATTR_NO_INLINE
:
430 return Attribute::NoInline
;
431 case LLVM_ATTR_OPTIMIZE_FOR_SIZE
:
432 return Attribute::OptimizeForSize
;
433 case LLVM_ATTR_OPTIMIZE_NONE
:
434 return Attribute::OptimizeNone
;
435 case LLVM_ATTR_IN_REG
:
436 return Attribute::InReg
;
437 case LLVM_ATTR_STRUCT_RET
:
438 return Attribute::StructRet
;
439 case LLVM_ATTR_NO_ALIAS
:
440 return Attribute::NoAlias
;
441 case LLVM_ATTR_BY_VAL
:
442 return Attribute::ByVal
;
443 case LLVM_ATTR_UW_TABLE
:
444 return Attribute::UWTable
;
447 return Attribute::NoUnwind
;
452 mono_llvm_add_func_attr (LLVMValueRef func
, AttrKind kind
)
454 unwrap
<Function
> (func
)->addAttribute (AttributeList::FunctionIndex
, convert_attr (kind
));
458 mono_llvm_add_param_attr (LLVMValueRef param
, AttrKind kind
)
460 Function
*func
= unwrap
<Argument
> (param
)->getParent ();
461 int n
= unwrap
<Argument
> (param
)->getArgNo ();
462 func
->addParamAttr (n
, convert_attr (kind
));
466 mono_llvm_add_instr_attr (LLVMValueRef val
, int index
, AttrKind kind
)
468 CallSite (unwrap
<Instruction
> (val
)).addAttribute (index
, convert_attr (kind
));
472 mono_llvm_create_di_builder (LLVMModuleRef module
)
474 return new DIBuilder (*unwrap(module
));
478 mono_llvm_di_create_compile_unit (void *di_builder
, const char *cu_name
, const char *dir
, const char *producer
)
480 DIBuilder
*builder
= (DIBuilder
*)di_builder
;
484 di_file
= builder
->createFile (cu_name
, dir
);
485 return builder
->createCompileUnit (dwarf::DW_LANG_C99
, di_file
, producer
, true, "", 0);
489 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
)
491 DIBuilder
*builder
= (DIBuilder
*)di_builder
;
493 DISubroutineType
*type
;
494 DISubprogram
*di_func
;
496 // FIXME: Share DIFile
497 di_file
= builder
->createFile (file
, dir
);
498 type
= builder
->createSubroutineType (builder
->getOrCreateTypeArray (ArrayRef
<Metadata
*> ()));
499 #if LLVM_API_VERSION >= 900
500 di_func
= builder
->createFunction (di_file
, name
, mangled_name
, di_file
, line
, type
, 0);
502 di_func
= builder
->createFunction (di_file
, name
, mangled_name
, di_file
, line
, type
, true, true, 0);
505 unwrap
<Function
>(func
)->setMetadata ("dbg", di_func
);
511 mono_llvm_di_create_file (void *di_builder
, const char *dir
, const char *file
)
513 DIBuilder
*builder
= (DIBuilder
*)di_builder
;
515 return builder
->createFile (file
, dir
);
519 mono_llvm_di_create_location (void *di_builder
, void *scope
, int row
, int column
)
521 return DILocation::get (*unwrap(LLVMGetGlobalContext ()), row
, column
, (Metadata
*)scope
);
525 mono_llvm_set_fast_math (LLVMBuilderRef builder
)
529 unwrap(builder
)->setFastMathFlags (flags
);
533 mono_llvm_di_set_location (LLVMBuilderRef builder
, void *loc_md
)
535 unwrap(builder
)->SetCurrentDebugLocation ((DILocation
*)loc_md
);
539 mono_llvm_di_builder_finalize (void *di_builder
)
541 DIBuilder
*builder
= (DIBuilder
*)di_builder
;
543 builder
->finalize ();
547 mono_llvm_get_or_insert_gc_safepoint_poll (LLVMModuleRef module
)
549 #if LLVM_API_VERSION >= 900
551 llvm::FunctionCallee callee
= unwrap(module
)->getOrInsertFunction("gc.safepoint_poll", FunctionType::get(unwrap(LLVMVoidType()), false));
552 return wrap (dyn_cast
<llvm::Function
> (callee
.getCallee ()));
554 llvm::Function
*SafepointPoll
;
555 llvm::Constant
*SafepointPollConstant
;
557 SafepointPollConstant
= unwrap(module
)->getOrInsertFunction("gc.safepoint_poll", FunctionType::get(unwrap(LLVMVoidType()), false));
558 g_assert (SafepointPollConstant
);
560 SafepointPoll
= dyn_cast
<llvm::Function
>(SafepointPollConstant
);
561 g_assert (SafepointPoll
);
562 g_assert (SafepointPoll
->empty());
564 return wrap(SafepointPoll
);
569 mono_llvm_remove_gc_safepoint_poll (LLVMModuleRef module
)
571 llvm::Function
*func
= unwrap (module
)->getFunction ("gc.safepoint_poll");
574 func
->eraseFromParent ();
579 mono_llvm_check_cpu_features (const CpuFeatureAliasFlag
*features
, int length
)
582 llvm::StringMap
<bool> HostFeatures
;
583 if (llvm::sys::getHostCPUFeatures (HostFeatures
)) {
584 for (int i
=0; i
<length
; i
++) {
585 CpuFeatureAliasFlag feature
= features
[i
];
586 if (HostFeatures
[feature
.alias
])
587 flags
|= feature
.flag
;
590 for (auto &F : HostFeatures)
592 outs () << "X: " << F.first () << "\n";