Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / mini / mini-llvm-cpp.cpp
index 6fab934f479b6d7503dffc9e043e367814bc9db2..253cd42ff81b93f61cfa49d1a40eac51737e1a82 100644 (file)
@@ -3,6 +3,7 @@
 //
 // (C) 2009-2011 Novell, Inc.
 // Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
 //
 
 //
 #include <llvm/IR/IRBuilder.h>
 #include <llvm/IR/Module.h>
 #include <llvm/IR/DIBuilder.h>
+#include <llvm/IR/CallSite.h>
 
 #include "mini-llvm-cpp.h"
 
 using namespace llvm;
 
+#if LLVM_API_VERSION > 100
+// These are c++11 scoped enums in recent llvm versions
+#define Acquire AtomicOrdering::Acquire
+#define Release AtomicOrdering::Release
+#define SequentiallyConsistent AtomicOrdering::SequentiallyConsistent
+#endif
+
 void
 mono_llvm_dump_value (LLVMValueRef value)
 {
@@ -48,15 +57,29 @@ mono_llvm_build_alloca (LLVMBuilderRef builder, LLVMTypeRef Ty,
                                                LLVMValueRef ArraySize,
                                                int alignment, const char *Name)
 {
+#if LLVM_API_VERSION >= 500
+       return wrap (unwrap (builder)->Insert (new AllocaInst (unwrap (Ty), 0, unwrap (ArraySize), alignment), Name));
+#else
        return wrap (unwrap (builder)->Insert (new AllocaInst (unwrap (Ty), unwrap (ArraySize), alignment), Name));
+#endif
 }
 
 LLVMValueRef 
 mono_llvm_build_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
-                                         const char *Name, gboolean is_volatile, BarrierKind barrier)
+                                         const char *Name, gboolean is_volatile)
+{
+       LoadInst *ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
+
+       return wrap(ins);
+}
+
+LLVMValueRef
+mono_llvm_build_atomic_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
+                                                        const char *Name, gboolean is_volatile, int alignment, BarrierKind barrier)
 {
        LoadInst *ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
 
+       ins->setAlignment (alignment);
        switch (barrier) {
        case LLVM_BARRIER_NONE:
                break;
@@ -219,9 +242,180 @@ mono_llvm_set_call_preserveall_cc (LLVMValueRef func)
 }
 
 void
-mono_llvm_create_di_compile_unit (LLVMModuleRef module)
+mono_llvm_set_call_notail (LLVMValueRef func)
+{
+#if LLVM_API_VERSION > 100
+       unwrap<CallInst>(func)->setTailCallKind (CallInst::TailCallKind::TCK_NoTail);
+#endif
+}
+
+#if LLVM_API_VERSION > 500
+static Attribute::AttrKind
+convert_attr (AttrKind kind)
+{
+       switch (kind) {
+       case LLVM_ATTR_NO_UNWIND:
+               return Attribute::NoUnwind;
+       case LLVM_ATTR_NO_INLINE:
+               return Attribute::NoInline;
+       case LLVM_ATTR_OPTIMIZE_FOR_SIZE:
+               return Attribute::OptimizeForSize;
+       case LLVM_ATTR_IN_REG:
+               return Attribute::InReg;
+       case LLVM_ATTR_STRUCT_RET:
+               return Attribute::StructRet;
+       case LLVM_ATTR_NO_ALIAS:
+               return Attribute::NoAlias;
+       case LLVM_ATTR_BY_VAL:
+               return Attribute::ByVal;
+       case LLVM_ATTR_UW_TABLE:
+               return Attribute::UWTable;
+       default:
+               assert (0);
+               return Attribute::NoUnwind;
+       }
+}
+#else
+static LLVMAttribute
+convert_attr (AttrKind kind)
+{
+       switch (kind) {
+       case LLVM_ATTR_NO_UNWIND:
+               return LLVMNoUnwindAttribute;
+       case LLVM_ATTR_NO_INLINE:
+               return LLVMNoInlineAttribute;
+       case LLVM_ATTR_OPTIMIZE_FOR_SIZE:
+               return LLVMOptimizeForSizeAttribute;
+       case LLVM_ATTR_IN_REG:
+               return LLVMInRegAttribute;
+       case LLVM_ATTR_STRUCT_RET:
+               return LLVMStructRetAttribute;
+       case LLVM_ATTR_NO_ALIAS:
+               return LLVMNoAliasAttribute;
+       case LLVM_ATTR_BY_VAL:
+               return LLVMByValAttribute;
+       case LLVM_ATTR_UW_TABLE:
+               return LLVMUWTable;
+       default:
+               assert (0);
+               return LLVMNoUnwindAttribute;
+       }
+}
+#endif
+
+void
+mono_llvm_add_func_attr (LLVMValueRef func, AttrKind kind)
 {
-       DIBuilder d(*unwrap(module));
+#if LLVM_API_VERSION > 100
+       unwrap<Function> (func)->addAttribute (AttributeList::FunctionIndex, convert_attr (kind));
+#else
+       Function *Func = unwrap<Function>(func);
+       const AttributeSet PAL = Func->getAttributes();
+       AttrBuilder B(convert_attr (kind));
+       const AttributeSet PALnew =
+               PAL.addAttributes(Func->getContext(), AttributeSet::FunctionIndex,
+                                                 AttributeSet::get(Func->getContext(),
+                                                                                       AttributeSet::FunctionIndex, B));
+       Func->setAttributes(PALnew);
+#endif
+}
+
+void
+mono_llvm_add_param_attr (LLVMValueRef param, AttrKind kind)
+{
+#if LLVM_API_VERSION > 100
+       Function *func = unwrap<Argument> (param)->getParent ();
+       int n = unwrap<Argument> (param)->getArgNo ();
+       func->addParamAttr (n, convert_attr (kind));
+#else
+       Argument *A = unwrap<Argument>(param);
+       AttrBuilder B(convert_attr (kind));
+       A->addAttr(AttributeSet::get(A->getContext(), A->getArgNo() + 1,  B));
+#endif
+}
 
-       d.createCompileUnit (0, "X", "Y", "Z", false, "", 0, "", DIBuilder::DebugEmissionKind::FullDebug, true);
+void
+mono_llvm_add_instr_attr (LLVMValueRef val, int index, AttrKind kind)
+{
+#if LLVM_API_VERSION > 100
+       CallSite (unwrap<Instruction> (val)).addAttribute (index, convert_attr (kind));
+#else
+  CallSite Call = CallSite(unwrap<Instruction>(val));
+  AttrBuilder B(convert_attr (kind));
+  Call.setAttributes(
+    Call.getAttributes().addAttributes(Call->getContext(), index,
+                                       AttributeSet::get(Call->getContext(),
+                                                         index, B)));
+#endif
 }
+
+#if LLVM_API_VERSION > 100
+
+void*
+mono_llvm_create_di_builder (LLVMModuleRef module)
+{
+       return new DIBuilder (*unwrap(module));
+}
+
+void*
+mono_llvm_di_create_compile_unit (void *di_builder, const char *cu_name, const char *dir, const char *producer)
+{
+       DIBuilder *builder = (DIBuilder*)di_builder;
+
+#if LLVM_API_VERSION >= 500
+       DIFile *di_file;
+
+       di_file = builder->createFile (cu_name, dir);
+       return builder->createCompileUnit (dwarf::DW_LANG_C99, di_file, producer, true, "", 0);
+#else
+       return builder->createCompileUnit (dwarf::DW_LANG_C99, cu_name, dir, producer, true, "", 0);
+#endif
+}
+
+void*
+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)
+{
+       DIBuilder *builder = (DIBuilder*)di_builder;
+       DIFile *di_file;
+       DISubroutineType *type;
+       DISubprogram *di_func;
+
+       // FIXME: Share DIFile
+       di_file = builder->createFile (file, dir);
+       type = builder->createSubroutineType (builder->getOrCreateTypeArray (ArrayRef<Metadata*> ()));
+       di_func = builder->createFunction (di_file, name, mangled_name, di_file, line, type, true, true, 0);
+
+       unwrap<Function>(func)->setMetadata ("dbg", di_func);
+
+       return di_func;
+}
+
+void*
+mono_llvm_di_create_file (void *di_builder, const char *dir, const char *file)
+{
+       DIBuilder *builder = (DIBuilder*)di_builder;
+
+       return builder->createFile (file, dir);
+}
+
+void*
+mono_llvm_di_create_location (void *di_builder, void *scope, int row, int column)
+{
+       return DILocation::get (*unwrap(LLVMGetGlobalContext ()), row, column, (Metadata*)scope);
+}
+
+void
+mono_llvm_di_set_location (LLVMBuilderRef builder, void *loc_md)
+{
+       unwrap(builder)->SetCurrentDebugLocation ((DILocation*)loc_md);
+}
+
+void
+mono_llvm_di_builder_finalize (void *di_builder)
+{
+       DIBuilder *builder = (DIBuilder*)di_builder;
+
+       builder->finalize ();
+}
+
+#endif /* #if LLVM_API_VERSION > 100 */