blob: 0da25e7ac57b7a7eea4628692251f0b92743d3cd [file] [log] [blame]
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#include "rustllvm.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/CallSite.h"
//===----------------------------------------------------------------------===
//
// This file defines alternate interfaces to core functions that are more
// readily callable by Rust's FFI.
//
//===----------------------------------------------------------------------===
using namespace llvm;
using namespace llvm::sys;
using namespace llvm::object;
// LLVMAtomicOrdering is already an enum - don't create another
// one.
static AtomicOrdering from_rust(LLVMAtomicOrdering Ordering) {
switch (Ordering) {
case LLVMAtomicOrderingNotAtomic:
return AtomicOrdering::NotAtomic;
case LLVMAtomicOrderingUnordered:
return AtomicOrdering::Unordered;
case LLVMAtomicOrderingMonotonic:
return AtomicOrdering::Monotonic;
case LLVMAtomicOrderingAcquire:
return AtomicOrdering::Acquire;
case LLVMAtomicOrderingRelease:
return AtomicOrdering::Release;
case LLVMAtomicOrderingAcquireRelease:
return AtomicOrdering::AcquireRelease;
case LLVMAtomicOrderingSequentiallyConsistent:
return AtomicOrdering::SequentiallyConsistent;
}
llvm_unreachable("Invalid LLVMAtomicOrdering value!");
}
static char *LastError;
extern "C" LLVMMemoryBufferRef
LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) {
ErrorOr<std::unique_ptr<MemoryBuffer>> buf_or = MemoryBuffer::getFile(Path,
-1,
false);
if (!buf_or) {
LLVMRustSetLastError(buf_or.getError().message().c_str());
return nullptr;
}
return wrap(buf_or.get().release());
}
extern "C" char *LLVMRustGetLastError(void) {
char *ret = LastError;
LastError = NULL;
return ret;
}
void LLVMRustSetLastError(const char *err) {
free((void*) LastError);
LastError = strdup(err);
}
extern "C" void
LLVMRustSetNormalizedTarget(LLVMModuleRef M, const char *triple) {
unwrap(M)->setTargetTriple(Triple::normalize(triple));
}
extern "C" void LLVMRustPrintPassTimings() {
raw_fd_ostream OS (2, false); // stderr.
TimerGroup::printAll(OS);
}
extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M,
const char* Name) {
return wrap(unwrap(M)->getNamedValue(Name));
}
extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
const char* Name,
LLVMTypeRef FunctionTy) {
return wrap(unwrap(M)->getOrInsertFunction(Name,
unwrap<FunctionType>(FunctionTy)));
}
extern "C" LLVMValueRef LLVMRustGetOrInsertGlobal(LLVMModuleRef M,
const char* Name,
LLVMTypeRef Ty) {
return wrap(unwrap(M)->getOrInsertGlobal(Name, unwrap(Ty)));
}
extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) {
return wrap(Type::getMetadataTy(*unwrap(C)));
}
extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned index, uint64_t Val) {
CallSite Call = CallSite(unwrap<Instruction>(Instr));
AttrBuilder B;
B.addRawValue(Val);
Call.setAttributes(
Call.getAttributes().addAttributes(Call->getContext(), index,
AttributeSet::get(Call->getContext(),
index, B)));
}
extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr,
unsigned idx,
uint64_t b)
{
CallSite Call = CallSite(unwrap<Instruction>(Instr));
AttrBuilder B;
B.addDereferenceableAttr(b);
Call.setAttributes(
Call.getAttributes().addAttributes(Call->getContext(), idx,
AttributeSet::get(Call->getContext(),
idx, B)));
}
extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn,
unsigned index,
uint64_t Val)
{
Function *A = unwrap<Function>(Fn);
AttrBuilder B;
B.addRawValue(Val);
A->addAttributes(index, AttributeSet::get(A->getContext(), index, B));
}
extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn,
unsigned index,
uint64_t bytes)
{
Function *A = unwrap<Function>(Fn);
AttrBuilder B;
B.addDereferenceableAttr(bytes);
A->addAttributes(index, AttributeSet::get(A->getContext(), index, B));
}
extern "C" void LLVMRustAddFunctionAttrString(LLVMValueRef Fn,
unsigned index,
const char *Name)
{
Function *F = unwrap<Function>(Fn);
AttrBuilder B;
B.addAttribute(Name);
F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
}
extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
unsigned index,
const char *Name,
const char *Value) {
Function *F = unwrap<Function>(Fn);
AttrBuilder B;
B.addAttribute(Name, Value);
F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
}
extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn,
unsigned index,
uint64_t Val)
{
Function *A = unwrap<Function>(Fn);
const AttributeSet PAL = A->getAttributes();
AttrBuilder B(Val);
const AttributeSet PALnew =
PAL.removeAttributes(A->getContext(), index,
AttributeSet::get(A->getContext(), index, B));
A->setAttributes(PALnew);
}
extern "C" void LLVMRustRemoveFunctionAttrString(LLVMValueRef fn,
unsigned index,
const char *Name)
{
Function *f = unwrap<Function>(fn);
LLVMContext &C = f->getContext();
AttrBuilder B;
B.addAttribute(Name);
AttributeSet to_remove = AttributeSet::get(C, index, B);
AttributeSet attrs = f->getAttributes();
f->setAttributes(attrs.removeAttributes(f->getContext(),
index,
to_remove));
}
// enable fpmath flag UnsafeAlgebra
extern "C" void LLVMRustSetHasUnsafeAlgebra(LLVMValueRef V) {
if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) {
I->setHasUnsafeAlgebra(true);
}
}
extern "C" LLVMValueRef LLVMRustBuildAtomicLoad(LLVMBuilderRef B,
LLVMValueRef source,
const char* Name,
LLVMAtomicOrdering order,
unsigned alignment) {
LoadInst* li = new LoadInst(unwrap(source),0);
li->setAtomic(from_rust(order));
li->setAlignment(alignment);
return wrap(unwrap(B)->Insert(li, Name));
}
extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B,
LLVMValueRef val,
LLVMValueRef target,
LLVMAtomicOrdering order,
unsigned alignment) {
StoreInst* si = new StoreInst(unwrap(val),unwrap(target));
si->setAtomic(from_rust(order));
si->setAlignment(alignment);
return wrap(unwrap(B)->Insert(si));
}
extern "C" LLVMValueRef LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B,
LLVMValueRef target,
LLVMValueRef old,
LLVMValueRef source,
LLVMAtomicOrdering order,
LLVMAtomicOrdering failure_order,
LLVMBool weak) {
AtomicCmpXchgInst* acxi = unwrap(B)->CreateAtomicCmpXchg(
unwrap(target),
unwrap(old),
unwrap(source),
from_rust(order),
from_rust(failure_order));
acxi->setWeak(weak);
return wrap(acxi);
}
enum class LLVMRustSynchronizationScope {
Other,
SingleThread,
CrossThread,
};
static SynchronizationScope
from_rust(LLVMRustSynchronizationScope scope)
{
switch (scope) {
case LLVMRustSynchronizationScope::SingleThread:
return SingleThread;
case LLVMRustSynchronizationScope::CrossThread:
return CrossThread;
default:
llvm_unreachable("bad SynchronizationScope.");
}
}
extern "C" LLVMValueRef LLVMRustBuildAtomicFence(
LLVMBuilderRef B,
LLVMAtomicOrdering order,
LLVMRustSynchronizationScope scope)
{
return wrap(unwrap(B)->CreateFence(from_rust(order), from_rust(scope)));
}
extern "C" void LLVMRustSetDebug(int Enabled) {
#ifndef NDEBUG
DebugFlag = Enabled;
#endif
}
enum class LLVMRustAsmDialect {
Other,
Att,
Intel,
};
static InlineAsm::AsmDialect
from_rust(LLVMRustAsmDialect dialect)
{
switch (dialect) {
case LLVMRustAsmDialect::Att:
return InlineAsm::AD_ATT;
case LLVMRustAsmDialect::Intel:
return InlineAsm::AD_Intel;
default:
llvm_unreachable("bad AsmDialect.");
}
}
extern "C" LLVMValueRef LLVMRustInlineAsm(LLVMTypeRef Ty,
char *AsmString,
char *Constraints,
LLVMBool HasSideEffects,
LLVMBool IsAlignStack,
LLVMRustAsmDialect Dialect) {
return wrap(InlineAsm::get(unwrap<FunctionType>(Ty), AsmString,
Constraints, HasSideEffects,
IsAlignStack, from_rust(Dialect)));
}
typedef DIBuilder* LLVMRustDIBuilderRef;
typedef struct LLVMOpaqueMetadata *LLVMRustMetadataRef;
namespace llvm {
DEFINE_ISA_CONVERSION_FUNCTIONS(Metadata, LLVMRustMetadataRef)
inline Metadata **unwrap(LLVMRustMetadataRef *Vals) {
return reinterpret_cast<Metadata**>(Vals);
}
}
template<typename DIT>
DIT* unwrapDIptr(LLVMRustMetadataRef ref) {
return (DIT*) (ref ? unwrap<MDNode>(ref) : NULL);
}
#define DIDescriptor DIScope
#define DIArray DINodeArray
#define unwrapDI unwrapDIptr
extern "C" uint32_t LLVMRustDebugMetadataVersion() {
return DEBUG_METADATA_VERSION;
}
extern "C" uint32_t LLVMRustVersionMinor() {
return LLVM_VERSION_MINOR;
}
extern "C" uint32_t LLVMRustVersionMajor() {
return LLVM_VERSION_MAJOR;
}
extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M,
const char *name,
uint32_t value) {
unwrap(M)->addModuleFlag(Module::Warning, name, value);
}
extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
return new DIBuilder(*unwrap(M));
}
extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
delete Builder;
}
extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
Builder->finalize();
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateCompileUnit(
LLVMRustDIBuilderRef Builder,
unsigned Lang,
const char* File,
const char* Dir,
const char* Producer,
bool isOptimized,
const char* Flags,
unsigned RuntimeVer,
const char* SplitName) {
return wrap(Builder->createCompileUnit(Lang,
File,
Dir,
Producer,
isOptimized,
Flags,
RuntimeVer,
SplitName));
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateFile(
LLVMRustDIBuilderRef Builder,
const char* Filename,
const char* Directory) {
return wrap(Builder->createFile(Filename, Directory));
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateSubroutineType(
LLVMRustDIBuilderRef Builder,
LLVMRustMetadataRef File,
LLVMRustMetadataRef ParameterTypes) {
return wrap(Builder->createSubroutineType(
#if LLVM_VERSION_MINOR == 7
unwrapDI<DIFile>(File),
#endif
DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateFunction(
LLVMRustDIBuilderRef Builder,
LLVMRustMetadataRef Scope,
const char* Name,
const char* LinkageName,
LLVMRustMetadataRef File,
unsigned LineNo,
LLVMRustMetadataRef Ty,
bool isLocalToUnit,
bool isDefinition,
unsigned ScopeLine,
unsigned Flags,
bool isOptimized,
LLVMValueRef Fn,
LLVMRustMetadataRef TParam,
LLVMRustMetadataRef Decl) {
#if LLVM_VERSION_MINOR >= 8
DITemplateParameterArray TParams =
DITemplateParameterArray(unwrap<MDTuple>(TParam));
DISubprogram *Sub = Builder->createFunction(
unwrapDI<DIScope>(Scope), Name, LinkageName,
unwrapDI<DIFile>(File), LineNo,
unwrapDI<DISubroutineType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
Flags, isOptimized,
TParams,
unwrapDIptr<DISubprogram>(Decl));
unwrap<Function>(Fn)->setSubprogram(Sub);
return wrap(Sub);
#else
return wrap(Builder->createFunction(
unwrapDI<DIScope>(Scope), Name, LinkageName,
unwrapDI<DIFile>(File), LineNo,
unwrapDI<DISubroutineType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
Flags, isOptimized,
unwrap<Function>(Fn),
unwrapDIptr<MDNode>(TParam),
unwrapDIptr<MDNode>(Decl)));
#endif
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateBasicType(
LLVMRustDIBuilderRef Builder,
const char* Name,
uint64_t SizeInBits,
uint64_t AlignInBits,
unsigned Encoding) {
return wrap(Builder->createBasicType(
Name, SizeInBits,
AlignInBits, Encoding));
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreatePointerType(
LLVMRustDIBuilderRef Builder,
LLVMRustMetadataRef PointeeTy,
uint64_t SizeInBits,
uint64_t AlignInBits,
const char* Name) {
return wrap(Builder->createPointerType(
unwrapDI<DIType>(PointeeTy), SizeInBits, AlignInBits, Name));
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateStructType(
LLVMRustDIBuilderRef Builder,
LLVMRustMetadataRef Scope,
const char* Name,
LLVMRustMetadataRef File,
unsigned LineNumber,
uint64_t SizeInBits,
uint64_t AlignInBits,
unsigned Flags,
LLVMRustMetadataRef DerivedFrom,
LLVMRustMetadataRef Elements,
unsigned RunTimeLang,
LLVMRustMetadataRef VTableHolder,
const char *UniqueId) {
return wrap(Builder->createStructType(
unwrapDI<DIDescriptor>(Scope),
Name,
unwrapDI<DIFile>(File),
LineNumber,
SizeInBits,
AlignInBits,
Flags,
unwrapDI<DIType>(DerivedFrom),
DINodeArray(unwrapDI<MDTuple>(Elements)),
RunTimeLang,
unwrapDI<DIType>(VTableHolder),
UniqueId
));
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateMemberType(
LLVMRustDIBuilderRef Builder,
LLVMRustMetadataRef Scope,
const char* Name,
LLVMRustMetadataRef File,
unsigned LineNo,
uint64_t SizeInBits,
uint64_t AlignInBits,
uint64_t OffsetInBits,
unsigned Flags,
LLVMRustMetadataRef Ty) {
return wrap(Builder->createMemberType(
unwrapDI<DIDescriptor>(Scope), Name,
unwrapDI<DIFile>(File), LineNo,
SizeInBits, AlignInBits, OffsetInBits, Flags,
unwrapDI<DIType>(Ty)));
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
LLVMRustDIBuilderRef Builder,
LLVMRustMetadataRef Scope,
LLVMRustMetadataRef File,
unsigned Line,
unsigned Col) {
return wrap(Builder->createLexicalBlock(
unwrapDI<DIDescriptor>(Scope),
unwrapDI<DIFile>(File), Line, Col
));
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateStaticVariable(
LLVMRustDIBuilderRef Builder,
LLVMRustMetadataRef Context,
const char* Name,
const char* LinkageName,
LLVMRustMetadataRef File,
unsigned LineNo,
LLVMRustMetadataRef Ty,
bool isLocalToUnit,
LLVMValueRef Val,
LLVMRustMetadataRef Decl = NULL) {
return wrap(Builder->createGlobalVariable(unwrapDI<DIDescriptor>(Context),
Name,
LinkageName,
unwrapDI<DIFile>(File),
LineNo,
unwrapDI<DIType>(Ty),
isLocalToUnit,
cast<Constant>(unwrap(Val)),
unwrapDIptr<MDNode>(Decl)));
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateVariable(
LLVMRustDIBuilderRef Builder,
unsigned Tag,
LLVMRustMetadataRef Scope,
const char* Name,
LLVMRustMetadataRef File,
unsigned LineNo,
LLVMRustMetadataRef Ty,
bool AlwaysPreserve,
unsigned Flags,
int64_t* AddrOps,
unsigned AddrOpsCount,
unsigned ArgNo) {
#if LLVM_VERSION_MINOR >= 8
if (Tag == 0x100) { // DW_TAG_auto_variable
return wrap(Builder->createAutoVariable(
unwrapDI<DIDescriptor>(Scope), Name,
unwrapDI<DIFile>(File),
LineNo,
unwrapDI<DIType>(Ty), AlwaysPreserve, Flags));
} else {
return wrap(Builder->createParameterVariable(
unwrapDI<DIDescriptor>(Scope), Name, ArgNo,
unwrapDI<DIFile>(File),
LineNo,
unwrapDI<DIType>(Ty), AlwaysPreserve, Flags));
}
#else
return wrap(Builder->createLocalVariable(Tag,
unwrapDI<DIDescriptor>(Scope), Name,
unwrapDI<DIFile>(File),
LineNo,
unwrapDI<DIType>(Ty), AlwaysPreserve, Flags, ArgNo));
#endif
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateArrayType(
LLVMRustDIBuilderRef Builder,
uint64_t Size,
uint64_t AlignInBits,
LLVMRustMetadataRef Ty,
LLVMRustMetadataRef Subscripts) {
return wrap(Builder->createArrayType(Size, AlignInBits,
unwrapDI<DIType>(Ty),
DINodeArray(unwrapDI<MDTuple>(Subscripts))
));
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateVectorType(
LLVMRustDIBuilderRef Builder,
uint64_t Size,
uint64_t AlignInBits,
LLVMRustMetadataRef Ty,
LLVMRustMetadataRef Subscripts) {
return wrap(Builder->createVectorType(Size, AlignInBits,
unwrapDI<DIType>(Ty),
DINodeArray(unwrapDI<MDTuple>(Subscripts))
));
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderGetOrCreateSubrange(
LLVMRustDIBuilderRef Builder,
int64_t Lo,
int64_t Count) {
return wrap(Builder->getOrCreateSubrange(Lo, Count));
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderGetOrCreateArray(
LLVMRustDIBuilderRef Builder,
LLVMRustMetadataRef* Ptr,
unsigned Count) {
Metadata **DataValue = unwrap(Ptr);
return wrap(Builder->getOrCreateArray(
ArrayRef<Metadata*>(DataValue, Count)).get());
}
extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
LLVMRustDIBuilderRef Builder,
LLVMValueRef Val,
LLVMRustMetadataRef VarInfo,
int64_t* AddrOps,
unsigned AddrOpsCount,
LLVMValueRef DL,
LLVMBasicBlockRef InsertAtEnd) {
return wrap(Builder->insertDeclare(
unwrap(Val),
unwrap<DILocalVariable>(VarInfo),
Builder->createExpression(
llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
DebugLoc(cast<MDNode>(unwrap<MetadataAsValue>(DL)->getMetadata())),
unwrap(InsertAtEnd)));
}
extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareBefore(
LLVMRustDIBuilderRef Builder,
LLVMValueRef Val,
LLVMRustMetadataRef VarInfo,
int64_t* AddrOps,
unsigned AddrOpsCount,
LLVMValueRef DL,
LLVMValueRef InsertBefore) {
return wrap(Builder->insertDeclare(
unwrap(Val),
unwrap<DILocalVariable>(VarInfo),
Builder->createExpression(
llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
DebugLoc(cast<MDNode>(unwrap<MetadataAsValue>(DL)->getMetadata())),
unwrap<Instruction>(InsertBefore)));
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateEnumerator(
LLVMRustDIBuilderRef Builder,
const char* Name,
uint64_t Val)
{
return wrap(Builder->createEnumerator(Name, Val));
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateEnumerationType(
LLVMRustDIBuilderRef Builder,
LLVMRustMetadataRef Scope,
const char* Name,
LLVMRustMetadataRef File,
unsigned LineNumber,
uint64_t SizeInBits,
uint64_t AlignInBits,
LLVMRustMetadataRef Elements,
LLVMRustMetadataRef ClassType)
{
return wrap(Builder->createEnumerationType(
unwrapDI<DIDescriptor>(Scope),
Name,
unwrapDI<DIFile>(File),
LineNumber,
SizeInBits,
AlignInBits,
DINodeArray(unwrapDI<MDTuple>(Elements)),
unwrapDI<DIType>(ClassType)));
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateUnionType(
LLVMRustDIBuilderRef Builder,
LLVMRustMetadataRef Scope,
const char* Name,
LLVMRustMetadataRef File,
unsigned LineNumber,
uint64_t SizeInBits,
uint64_t AlignInBits,
unsigned Flags,
LLVMRustMetadataRef Elements,
unsigned RunTimeLang,
const char* UniqueId)
{
return wrap(Builder->createUnionType(
unwrapDI<DIDescriptor>(Scope),
Name,
unwrapDI<DIFile>(File),
LineNumber,
SizeInBits,
AlignInBits,
Flags,
DINodeArray(unwrapDI<MDTuple>(Elements)),
RunTimeLang,
UniqueId
));
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
LLVMRustDIBuilderRef Builder,
LLVMRustMetadataRef Scope,
const char* Name,
LLVMRustMetadataRef Ty,
LLVMRustMetadataRef File,
unsigned LineNo,
unsigned ColumnNo)
{
return wrap(Builder->createTemplateTypeParameter(
unwrapDI<DIDescriptor>(Scope),
Name,
unwrapDI<DIType>(Ty)
));
}
extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateNameSpace(
LLVMRustDIBuilderRef Builder,
LLVMRustMetadataRef Scope,
const char* Name,
LLVMRustMetadataRef File,
unsigned LineNo)
{
return wrap(Builder->createNameSpace(
unwrapDI<DIDescriptor>(Scope),
Name,
unwrapDI<DIFile>(File),
LineNo));
}
extern "C" void LLVMRustDICompositeTypeSetTypeArray(
LLVMRustDIBuilderRef Builder,
LLVMRustMetadataRef CompositeType,
LLVMRustMetadataRef TypeArray)
{
DICompositeType *tmp = unwrapDI<DICompositeType>(CompositeType);
Builder->replaceArrays(tmp, DINodeArray(unwrap<MDTuple>(TypeArray)));
}
extern "C" LLVMValueRef LLVMRustDIBuilderCreateDebugLocation(
LLVMContextRef Context,
unsigned Line,
unsigned Column,
LLVMRustMetadataRef Scope,
LLVMRustMetadataRef InlinedAt)
{
LLVMContext& context = *unwrap(Context);
DebugLoc debug_loc = DebugLoc::get(Line,
Column,
unwrapDIptr<MDNode>(Scope),
unwrapDIptr<MDNode>(InlinedAt));
return wrap(MetadataAsValue::get(context, debug_loc.getAsMDNode()));
}
extern "C" int64_t LLVMRustDIBuilderCreateOpDeref()
{
return dwarf::DW_OP_deref;
}
extern "C" int64_t LLVMRustDIBuilderCreateOpPlus()
{
return dwarf::DW_OP_plus;
}
extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Type, RustStringRef str) {
raw_rust_string_ostream os(str);
unwrap<llvm::Type>(Type)->print(os);
}
extern "C" void LLVMRustWriteValueToString(LLVMValueRef Value, RustStringRef str) {
raw_rust_string_ostream os(str);
os << "(";
unwrap<llvm::Value>(Value)->getType()->print(os);
os << ":";
unwrap<llvm::Value>(Value)->print(os);
os << ")";
}
extern "C" bool
LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
Module *Dst = unwrap(dst);
std::unique_ptr<MemoryBuffer> buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
ErrorOr<std::unique_ptr<Module>> Src =
llvm::getLazyBitcodeModule(std::move(buf), Dst->getContext());
if (!Src) {
LLVMRustSetLastError(Src.getError().message().c_str());
return false;
}
std::string Err;
raw_string_ostream Stream(Err);
DiagnosticPrinterRawOStream DP(Stream);
#if LLVM_VERSION_MINOR >= 8
if (Linker::linkModules(*Dst, std::move(Src.get()))) {
#else
if (Linker::LinkModules(Dst, Src->get(), [&](const DiagnosticInfo &DI) { DI.print(DP); })) {
#endif
LLVMRustSetLastError(Err.c_str());
return false;
}
return true;
}
// Note that the two following functions look quite similar to the
// LLVMGetSectionName function. Sadly, it appears that this function only
// returns a char* pointer, which isn't guaranteed to be null-terminated. The
// function provided by LLVM doesn't return the length, so we've created our own
// function which returns the length as well as the data pointer.
//
// For an example of this not returning a null terminated string, see
// lib/Object/COFFObjectFile.cpp in the getSectionName function. One of the
// branches explicitly creates a StringRef without a null terminator, and then
// that's returned.
inline section_iterator *unwrap(LLVMSectionIteratorRef SI) {
return reinterpret_cast<section_iterator*>(SI);
}
extern "C" size_t
LLVMRustGetSectionName(LLVMSectionIteratorRef SI, const char **ptr) {
StringRef ret;
if (std::error_code ec = (*unwrap(SI))->getName(ret))
report_fatal_error(ec.message());
*ptr = ret.data();
return ret.size();
}
// LLVMArrayType function does not support 64-bit ElementCount
extern "C" LLVMTypeRef
LLVMRustArrayType(LLVMTypeRef ElementType, uint64_t ElementCount) {
return wrap(ArrayType::get(unwrap(ElementType), ElementCount));
}
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DebugLoc, LLVMDebugLocRef)
extern "C" void
LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef str) {
raw_rust_string_ostream os(str);
unwrap(T)->print(os);
}
extern "C" void
LLVMRustUnpackOptimizationDiagnostic(
LLVMDiagnosticInfoRef di,
const char **pass_name_out,
LLVMValueRef *function_out,
LLVMDebugLocRef *debugloc_out,
LLVMTwineRef *message_out)
{
// Undefined to call this not on an optimization diagnostic!
llvm::DiagnosticInfoOptimizationBase *opt
= static_cast<llvm::DiagnosticInfoOptimizationBase*>(unwrap(di));
*pass_name_out = opt->getPassName();
*function_out = wrap(&opt->getFunction());
*debugloc_out = wrap(&opt->getDebugLoc());
*message_out = wrap(&opt->getMsg());
}
extern "C" void
LLVMRustUnpackInlineAsmDiagnostic(
LLVMDiagnosticInfoRef di,
unsigned *cookie_out,
LLVMTwineRef *message_out,
LLVMValueRef *instruction_out)
{
// Undefined to call this not on an inline assembly diagnostic!
llvm::DiagnosticInfoInlineAsm *ia
= static_cast<llvm::DiagnosticInfoInlineAsm*>(unwrap(di));
*cookie_out = ia->getLocCookie();
*message_out = wrap(&ia->getMsgStr());
*instruction_out = wrap(ia->getInstruction());
}
extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef di, RustStringRef str) {
raw_rust_string_ostream os(str);
DiagnosticPrinterRawOStream dp(os);
unwrap(di)->print(dp);
}
enum class LLVMRustDiagnosticKind {
Other,
InlineAsm,
StackSize,
DebugMetadataVersion,
SampleProfile,
OptimizationRemark,
OptimizationRemarkMissed,
OptimizationRemarkAnalysis,
OptimizationRemarkAnalysisFPCommute,
OptimizationRemarkAnalysisAliasing,
OptimizationRemarkOther,
OptimizationFailure,
};
static LLVMRustDiagnosticKind
to_rust(DiagnosticKind kind)
{
switch (kind) {
case DK_InlineAsm:
return LLVMRustDiagnosticKind::InlineAsm;
case DK_StackSize:
return LLVMRustDiagnosticKind::StackSize;
case DK_DebugMetadataVersion:
return LLVMRustDiagnosticKind::DebugMetadataVersion;
case DK_SampleProfile:
return LLVMRustDiagnosticKind::SampleProfile;
case DK_OptimizationRemark:
return LLVMRustDiagnosticKind::OptimizationRemark;
case DK_OptimizationRemarkMissed:
return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
case DK_OptimizationRemarkAnalysis:
return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
#if LLVM_VERSION_MINOR >= 8
case DK_OptimizationRemarkAnalysisFPCommute:
return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
case DK_OptimizationRemarkAnalysisAliasing:
return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
#endif
default:
#if LLVM_VERSION_MINOR >= 9
return (kind >= DK_FirstRemark && kind <= DK_LastRemark) ?
LLVMRustDiagnosticKind::OptimizationRemarkOther :
LLVMRustDiagnosticKind::Other;
#else
return LLVMRustDiagnosticKind::Other;
#endif
}
}
extern "C" LLVMRustDiagnosticKind LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef di) {
return to_rust((DiagnosticKind) unwrap(di)->getKind());
}
// This is kept distinct from LLVMGetTypeKind, because when
// a new type kind is added, the Rust-side enum must be
// updated or UB will result.
extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
switch (unwrap(Ty)->getTypeID()) {
case Type::VoidTyID:
return LLVMVoidTypeKind;
case Type::HalfTyID:
return LLVMHalfTypeKind;
case Type::FloatTyID:
return LLVMFloatTypeKind;
case Type::DoubleTyID:
return LLVMDoubleTypeKind;
case Type::X86_FP80TyID:
return LLVMX86_FP80TypeKind;
case Type::FP128TyID:
return LLVMFP128TypeKind;
case Type::PPC_FP128TyID:
return LLVMPPC_FP128TypeKind;
case Type::LabelTyID:
return LLVMLabelTypeKind;
case Type::MetadataTyID:
return LLVMMetadataTypeKind;
case Type::IntegerTyID:
return LLVMIntegerTypeKind;
case Type::FunctionTyID:
return LLVMFunctionTypeKind;
case Type::StructTyID:
return LLVMStructTypeKind;
case Type::ArrayTyID:
return LLVMArrayTypeKind;
case Type::PointerTyID:
return LLVMPointerTypeKind;
case Type::VectorTyID:
return LLVMVectorTypeKind;
case Type::X86_MMXTyID:
return LLVMX86_MMXTypeKind;
#if LLVM_VERSION_MINOR >= 8
case Type::TokenTyID:
return LLVMTokenTypeKind;
#endif
}
llvm_unreachable("Unhandled TypeID.");
}
extern "C" void LLVMRustWriteDebugLocToString(
LLVMContextRef C,
LLVMDebugLocRef dl,
RustStringRef str)
{
raw_rust_string_ostream os(str);
unwrap(dl)->print(os);
}
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
LLVMContextRef C,
LLVMContext::InlineAsmDiagHandlerTy H,
void *CX)
{
unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
}
extern "C" void LLVMRustWriteSMDiagnosticToString(LLVMSMDiagnosticRef d,
RustStringRef str) {
raw_rust_string_ostream os(str);
unwrap(d)->print("", os);
}
extern "C" LLVMValueRef
LLVMRustBuildLandingPad(LLVMBuilderRef Builder,
LLVMTypeRef Ty,
LLVMValueRef PersFn,
unsigned NumClauses,
const char* Name,
LLVMValueRef F) {
return LLVMBuildLandingPad(Builder, Ty, PersFn, NumClauses, Name);
}
extern "C" LLVMValueRef
LLVMRustBuildCleanupPad(LLVMBuilderRef Builder,
LLVMValueRef ParentPad,
unsigned ArgCnt,
LLVMValueRef *LLArgs,
const char *Name) {
#if LLVM_VERSION_MINOR >= 8
Value **Args = unwrap(LLArgs);
if (ParentPad == NULL) {
Type *Ty = Type::getTokenTy(unwrap(Builder)->getContext());
ParentPad = wrap(Constant::getNullValue(Ty));
}
return wrap(unwrap(Builder)->CreateCleanupPad(unwrap(ParentPad),
ArrayRef<Value*>(Args, ArgCnt),
Name));
#else
return NULL;
#endif
}
extern "C" LLVMValueRef
LLVMRustBuildCleanupRet(LLVMBuilderRef Builder,
LLVMValueRef CleanupPad,
LLVMBasicBlockRef UnwindBB) {
#if LLVM_VERSION_MINOR >= 8
CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
return wrap(unwrap(Builder)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
#else
return NULL;
#endif
}
extern "C" LLVMValueRef
LLVMRustBuildCatchPad(LLVMBuilderRef Builder,
LLVMValueRef ParentPad,
unsigned ArgCnt,
LLVMValueRef *LLArgs,
const char *Name) {
#if LLVM_VERSION_MINOR >= 8
Value **Args = unwrap(LLArgs);
return wrap(unwrap(Builder)->CreateCatchPad(unwrap(ParentPad),
ArrayRef<Value*>(Args, ArgCnt),
Name));
#else
return NULL;
#endif
}
extern "C" LLVMValueRef
LLVMRustBuildCatchRet(LLVMBuilderRef Builder,
LLVMValueRef Pad,
LLVMBasicBlockRef BB) {
#if LLVM_VERSION_MINOR >= 8
return wrap(unwrap(Builder)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
unwrap(BB)));
#else
return NULL;
#endif
}
extern "C" LLVMValueRef
LLVMRustBuildCatchSwitch(LLVMBuilderRef Builder,
LLVMValueRef ParentPad,
LLVMBasicBlockRef BB,
unsigned NumHandlers,
const char *Name) {
#if LLVM_VERSION_MINOR >= 8
if (ParentPad == NULL) {
Type *Ty = Type::getTokenTy(unwrap(Builder)->getContext());
ParentPad = wrap(Constant::getNullValue(Ty));
}
return wrap(unwrap(Builder)->CreateCatchSwitch(unwrap(ParentPad),
unwrap(BB),
NumHandlers,
Name));
#else
return NULL;
#endif
}
extern "C" void
LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
LLVMBasicBlockRef Handler) {
#if LLVM_VERSION_MINOR >= 8
Value *CatchSwitch = unwrap(CatchSwitchRef);
cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
#endif
}
extern "C" void
LLVMRustSetPersonalityFn(LLVMBuilderRef B,
LLVMValueRef Personality) {
#if LLVM_VERSION_MINOR >= 8
unwrap(B)->GetInsertBlock()
->getParent()
->setPersonalityFn(cast<Function>(unwrap(Personality)));
#endif
}
#if LLVM_VERSION_MINOR >= 8
extern "C" OperandBundleDef*
LLVMRustBuildOperandBundleDef(const char *Name,
LLVMValueRef *Inputs,
unsigned NumInputs) {
return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
}
extern "C" void
LLVMRustFreeOperandBundleDef(OperandBundleDef* Bundle) {
delete Bundle;
}
extern "C" LLVMValueRef
LLVMRustBuildCall(LLVMBuilderRef B,
LLVMValueRef Fn,
LLVMValueRef *Args,
unsigned NumArgs,
OperandBundleDef *Bundle,
const char *Name) {
unsigned len = Bundle ? 1 : 0;
ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, len);
return wrap(unwrap(B)->CreateCall(unwrap(Fn),
makeArrayRef(unwrap(Args), NumArgs),
Bundles,
Name));
}
extern "C" LLVMValueRef
LLVMRustBuildInvoke(LLVMBuilderRef B,
LLVMValueRef Fn,
LLVMValueRef *Args,
unsigned NumArgs,
LLVMBasicBlockRef Then,
LLVMBasicBlockRef Catch,
OperandBundleDef *Bundle,
const char *Name) {
unsigned len = Bundle ? 1 : 0;
ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, len);
return wrap(unwrap(B)->CreateInvoke(unwrap(Fn), unwrap(Then), unwrap(Catch),
makeArrayRef(unwrap(Args), NumArgs),
Bundles,
Name));
}
#else
extern "C" void*
LLVMRustBuildOperandBundleDef(const char *Name,
LLVMValueRef *Inputs,
unsigned NumInputs) {
return NULL;
}
extern "C" void
LLVMRustFreeOperandBundleDef(void* Bundle) {
}
extern "C" LLVMValueRef
LLVMRustBuildCall(LLVMBuilderRef B,
LLVMValueRef Fn,
LLVMValueRef *Args,
unsigned NumArgs,
void *Bundle,
const char *Name) {
return LLVMBuildCall(B, Fn, Args, NumArgs, Name);
}
extern "C" LLVMValueRef
LLVMRustBuildInvoke(LLVMBuilderRef B,
LLVMValueRef Fn,
LLVMValueRef *Args,
unsigned NumArgs,
LLVMBasicBlockRef Then,
LLVMBasicBlockRef Catch,
void *Bundle,
const char *Name) {
return LLVMBuildInvoke(B, Fn, Args, NumArgs, Then, Catch, Name);
}
#endif
extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B, LLVMBasicBlockRef BB) {
auto point = unwrap(BB)->getFirstInsertionPt();
unwrap(B)->SetInsertPoint(unwrap(BB), point);
}
extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V, const char *Name) {
Triple TargetTriple(unwrap(M)->getTargetTriple());
GlobalObject *GV = unwrap<GlobalObject>(V);
if (!TargetTriple.isOSBinFormatMachO()) {
GV->setComdat(unwrap(M)->getOrInsertComdat(Name));
}
}
extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) {
GlobalObject *GV = unwrap<GlobalObject>(V);
GV->setComdat(nullptr);
}