2013-05-27 18:15:31 -05:00
|
|
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
2012-12-10 17:44:02 -06:00
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
2011-03-15 16:57:26 -05:00
|
|
|
//
|
2012-12-10 17:44:02 -06:00
|
|
|
// 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.
|
|
|
|
|
2013-05-27 18:15:31 -05:00
|
|
|
#include "rustllvm.h"
|
2013-12-16 22:58:21 -06:00
|
|
|
#include "llvm/Object/Archive.h"
|
2014-04-03 12:45:36 -05:00
|
|
|
#include "llvm/Object/ObjectFile.h"
|
2014-09-12 10:17:58 -05:00
|
|
|
#include "llvm/IR/DiagnosticInfo.h"
|
|
|
|
#include "llvm/IR/DiagnosticPrinter.h"
|
2013-05-27 18:15:31 -05:00
|
|
|
|
2014-05-21 14:07:48 -05:00
|
|
|
#include "llvm/IR/CallSite.h"
|
|
|
|
|
2011-10-21 19:35:52 -05:00
|
|
|
//===----------------------------------------------------------------------===
|
2011-03-15 16:57:26 -05:00
|
|
|
//
|
|
|
|
// This file defines alternate interfaces to core functions that are more
|
|
|
|
// readily callable by Rust's FFI.
|
|
|
|
//
|
2011-10-21 19:35:52 -05:00
|
|
|
//===----------------------------------------------------------------------===
|
2011-03-15 16:57:26 -05:00
|
|
|
|
2011-04-15 16:35:46 -05:00
|
|
|
using namespace llvm;
|
2012-09-11 01:05:51 -05:00
|
|
|
using namespace llvm::sys;
|
2013-12-16 22:58:21 -06:00
|
|
|
using namespace llvm::object;
|
2011-04-15 16:35:46 -05:00
|
|
|
|
2014-04-15 09:25:22 -05:00
|
|
|
static char *LastError;
|
2013-04-05 19:17:49 -05:00
|
|
|
|
2014-07-18 09:07:15 -05:00
|
|
|
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());
|
|
|
|
}
|
2011-03-15 16:57:26 -05:00
|
|
|
|
2014-04-15 09:25:22 -05:00
|
|
|
extern "C" char *LLVMRustGetLastError(void) {
|
|
|
|
char *ret = LastError;
|
|
|
|
LastError = NULL;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LLVMRustSetLastError(const char *err) {
|
|
|
|
free((void*) LastError);
|
|
|
|
LastError = strdup(err);
|
2011-03-15 16:57:26 -05:00
|
|
|
}
|
|
|
|
|
2013-08-22 22:58:42 -05:00
|
|
|
extern "C" void
|
|
|
|
LLVMRustSetNormalizedTarget(LLVMModuleRef M, const char *triple) {
|
|
|
|
unwrap(M)->setTargetTriple(Triple::normalize(triple));
|
2011-05-05 13:34:15 -05:00
|
|
|
}
|
|
|
|
|
2011-05-07 13:54:23 -05:00
|
|
|
extern "C" LLVMValueRef LLVMRustConstSmallInt(LLVMTypeRef IntTy, unsigned N,
|
|
|
|
LLVMBool SignExtend) {
|
|
|
|
return LLVMConstInt(IntTy, (unsigned long long)N, SignExtend);
|
|
|
|
}
|
2011-05-10 18:10:08 -05:00
|
|
|
|
2013-05-03 18:25:04 -05:00
|
|
|
extern "C" LLVMValueRef LLVMRustConstInt(LLVMTypeRef IntTy,
|
|
|
|
unsigned N_hi,
|
|
|
|
unsigned N_lo,
|
|
|
|
LLVMBool SignExtend) {
|
2011-11-16 14:15:54 -06:00
|
|
|
unsigned long long N = N_hi;
|
|
|
|
N <<= 32;
|
|
|
|
N |= N_lo;
|
|
|
|
return LLVMConstInt(IntTy, N, SignExtend);
|
|
|
|
}
|
|
|
|
|
2011-05-10 18:10:08 -05:00
|
|
|
extern "C" void LLVMRustPrintPassTimings() {
|
|
|
|
raw_fd_ostream OS (2, false); // stderr.
|
|
|
|
TimerGroup::printAll(OS);
|
|
|
|
}
|
2011-10-31 16:42:17 -05:00
|
|
|
|
2011-11-14 10:32:31 -06:00
|
|
|
extern "C" LLVMValueRef LLVMGetOrInsertFunction(LLVMModuleRef M,
|
|
|
|
const char* Name,
|
|
|
|
LLVMTypeRef FunctionTy) {
|
|
|
|
return wrap(unwrap(M)->getOrInsertFunction(Name,
|
|
|
|
unwrap<FunctionType>(FunctionTy)));
|
|
|
|
}
|
2011-11-09 23:55:09 -06:00
|
|
|
|
|
|
|
extern "C" LLVMTypeRef LLVMMetadataTypeInContext(LLVMContextRef C) {
|
|
|
|
return wrap(Type::getMetadataTy(*unwrap(C)));
|
|
|
|
}
|
2012-06-21 17:01:32 -05:00
|
|
|
|
2014-05-21 14:07:48 -05:00
|
|
|
extern "C" void LLVMAddCallSiteAttribute(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)));
|
2013-08-05 23:21:37 -05:00
|
|
|
}
|
|
|
|
|
2014-07-25 21:47:29 -05:00
|
|
|
|
2014-07-25 18:06:44 -05:00
|
|
|
extern "C" void LLVMAddDereferenceableCallSiteAttr(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)));
|
|
|
|
}
|
|
|
|
|
2014-05-21 14:07:48 -05:00
|
|
|
extern "C" void LLVMAddFunctionAttribute(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));
|
|
|
|
}
|
|
|
|
|
2014-07-25 18:06:44 -05:00
|
|
|
extern "C" void LLVMAddDereferenceableAttr(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));
|
|
|
|
}
|
|
|
|
|
2014-05-21 14:07:48 -05:00
|
|
|
extern "C" void LLVMAddFunctionAttrString(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 LLVMRemoveFunctionAttrString(LLVMValueRef fn, unsigned index, const char *Name) {
|
2014-04-19 12:33:46 -05:00
|
|
|
Function *f = unwrap<Function>(fn);
|
|
|
|
LLVMContext &C = f->getContext();
|
|
|
|
AttrBuilder B;
|
|
|
|
B.addAttribute(Name);
|
2014-05-21 14:07:48 -05:00
|
|
|
AttributeSet to_remove = AttributeSet::get(C, index, B);
|
2014-04-19 12:33:46 -05:00
|
|
|
|
|
|
|
AttributeSet attrs = f->getAttributes();
|
|
|
|
f->setAttributes(attrs.removeAttributes(f->getContext(),
|
2014-05-21 14:07:48 -05:00
|
|
|
index,
|
2014-04-19 12:33:46 -05:00
|
|
|
to_remove));
|
|
|
|
}
|
2013-09-09 01:32:30 -05:00
|
|
|
|
2013-05-12 14:22:20 -05:00
|
|
|
extern "C" LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B,
|
|
|
|
LLVMValueRef source,
|
|
|
|
const char* Name,
|
2013-05-20 19:28:06 -05:00
|
|
|
AtomicOrdering order,
|
|
|
|
unsigned alignment) {
|
2013-05-12 14:22:20 -05:00
|
|
|
LoadInst* li = new LoadInst(unwrap(source),0);
|
|
|
|
li->setVolatile(true);
|
|
|
|
li->setAtomic(order);
|
2013-05-20 19:28:06 -05:00
|
|
|
li->setAlignment(alignment);
|
2013-05-16 21:48:24 -05:00
|
|
|
return wrap(unwrap(B)->Insert(li, Name));
|
2013-05-12 14:22:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef B,
|
2013-05-20 19:28:06 -05:00
|
|
|
LLVMValueRef val,
|
|
|
|
LLVMValueRef target,
|
|
|
|
AtomicOrdering order,
|
|
|
|
unsigned alignment) {
|
2013-05-12 14:22:20 -05:00
|
|
|
StoreInst* si = new StoreInst(unwrap(val),unwrap(target));
|
|
|
|
si->setVolatile(true);
|
|
|
|
si->setAtomic(order);
|
2013-05-20 19:28:06 -05:00
|
|
|
si->setAlignment(alignment);
|
2013-05-12 14:22:20 -05:00
|
|
|
return wrap(unwrap(B)->Insert(si));
|
|
|
|
}
|
|
|
|
|
2012-10-21 21:23:50 -05:00
|
|
|
extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B,
|
|
|
|
LLVMValueRef target,
|
|
|
|
LLVMValueRef old,
|
|
|
|
LLVMValueRef source,
|
2014-03-31 16:43:19 -05:00
|
|
|
AtomicOrdering order,
|
|
|
|
AtomicOrdering failure_order) {
|
2012-10-21 21:23:50 -05:00
|
|
|
return wrap(unwrap(B)->CreateAtomicCmpXchg(unwrap(target), unwrap(old),
|
2015-03-14 07:14:04 -05:00
|
|
|
unwrap(source), order,
|
|
|
|
failure_order
|
2014-03-31 16:43:19 -05:00
|
|
|
));
|
2012-10-21 21:23:50 -05:00
|
|
|
}
|
2013-07-28 02:48:16 -05:00
|
|
|
extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B, AtomicOrdering order) {
|
|
|
|
return wrap(unwrap(B)->CreateFence(order));
|
|
|
|
}
|
2012-07-25 14:06:03 -05:00
|
|
|
|
|
|
|
extern "C" void LLVMSetDebug(int Enabled) {
|
2012-10-08 14:40:09 -05:00
|
|
|
#ifndef NDEBUG
|
2012-07-25 14:06:03 -05:00
|
|
|
DebugFlag = Enabled;
|
2012-10-08 14:40:09 -05:00
|
|
|
#endif
|
2012-07-25 14:06:03 -05:00
|
|
|
}
|
2013-03-10 00:37:50 -06:00
|
|
|
|
|
|
|
extern "C" LLVMValueRef LLVMInlineAsm(LLVMTypeRef Ty,
|
|
|
|
char *AsmString,
|
|
|
|
char *Constraints,
|
|
|
|
LLVMBool HasSideEffects,
|
2013-03-10 03:38:29 -05:00
|
|
|
LLVMBool IsAlignStack,
|
2013-03-08 19:44:37 -06:00
|
|
|
unsigned Dialect) {
|
2013-03-10 00:37:50 -06:00
|
|
|
return wrap(InlineAsm::get(unwrap<FunctionType>(Ty), AsmString,
|
|
|
|
Constraints, HasSideEffects,
|
2013-03-08 19:44:37 -06:00
|
|
|
IsAlignStack, (InlineAsm::AsmDialect) Dialect));
|
2013-03-10 00:37:50 -06:00
|
|
|
}
|
2013-06-13 23:25:12 -05:00
|
|
|
|
2013-06-14 13:38:29 -05:00
|
|
|
typedef DIBuilder* DIBuilderRef;
|
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
#if LLVM_VERSION_MINOR >= 6
|
|
|
|
typedef struct LLVMOpaqueMetadata *LLVMMetadataRef;
|
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
DEFINE_ISA_CONVERSION_FUNCTIONS(Metadata, LLVMMetadataRef)
|
|
|
|
|
|
|
|
inline Metadata **unwrap(LLVMMetadataRef *Vals) {
|
|
|
|
return reinterpret_cast<Metadata**>(Vals);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
typedef LLVMValueRef LLVMMetadataRef;
|
|
|
|
#endif
|
|
|
|
|
2013-06-14 13:38:29 -05:00
|
|
|
template<typename DIT>
|
2015-01-30 12:25:07 -06:00
|
|
|
DIT unwrapDI(LLVMMetadataRef ref) {
|
2013-07-02 11:10:24 -05:00
|
|
|
return DIT(ref ? unwrap<MDNode>(ref) : NULL);
|
2013-06-17 10:42:05 -05:00
|
|
|
}
|
2013-06-14 13:38:29 -05:00
|
|
|
|
2014-01-27 23:05:33 -06:00
|
|
|
extern "C" const uint32_t LLVMRustDebugMetadataVersion = DEBUG_METADATA_VERSION;
|
|
|
|
|
|
|
|
extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M,
|
|
|
|
const char *name,
|
|
|
|
uint32_t value) {
|
|
|
|
unwrap(M)->addModuleFlag(Module::Warning, name, value);
|
|
|
|
}
|
|
|
|
|
2013-06-11 02:57:25 -05:00
|
|
|
extern "C" DIBuilderRef LLVMDIBuilderCreate(LLVMModuleRef M) {
|
2013-06-14 13:38:29 -05:00
|
|
|
return new DIBuilder(*unwrap(M));
|
|
|
|
}
|
|
|
|
|
2013-06-11 02:57:25 -05:00
|
|
|
extern "C" void LLVMDIBuilderDispose(DIBuilderRef Builder) {
|
2013-06-14 13:38:29 -05:00
|
|
|
delete Builder;
|
|
|
|
}
|
|
|
|
|
2013-06-11 02:57:25 -05:00
|
|
|
extern "C" void LLVMDIBuilderFinalize(DIBuilderRef Builder) {
|
2013-06-14 13:38:29 -05:00
|
|
|
Builder->finalize();
|
|
|
|
}
|
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" LLVMMetadataRef LLVMDIBuilderCreateCompileUnit(
|
2013-06-14 13:38:29 -05:00
|
|
|
DIBuilderRef Builder,
|
|
|
|
unsigned Lang,
|
|
|
|
const char* File,
|
|
|
|
const char* Dir,
|
|
|
|
const char* Producer,
|
|
|
|
bool isOptimized,
|
|
|
|
const char* Flags,
|
|
|
|
unsigned RuntimeVer,
|
|
|
|
const char* SplitName) {
|
2014-12-03 16:48:18 -06:00
|
|
|
return wrap(Builder->createCompileUnit(Lang,
|
|
|
|
File,
|
|
|
|
Dir,
|
|
|
|
Producer,
|
|
|
|
isOptimized,
|
|
|
|
Flags,
|
|
|
|
RuntimeVer,
|
|
|
|
SplitName));
|
2013-06-14 13:38:29 -05:00
|
|
|
}
|
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" LLVMMetadataRef LLVMDIBuilderCreateFile(
|
2013-06-14 13:38:29 -05:00
|
|
|
DIBuilderRef Builder,
|
|
|
|
const char* Filename,
|
|
|
|
const char* Directory) {
|
|
|
|
return wrap(Builder->createFile(Filename, Directory));
|
|
|
|
}
|
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" LLVMMetadataRef LLVMDIBuilderCreateSubroutineType(
|
2013-06-14 13:38:29 -05:00
|
|
|
DIBuilderRef Builder,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef File,
|
|
|
|
LLVMMetadataRef ParameterTypes) {
|
2013-06-14 13:38:29 -05:00
|
|
|
return wrap(Builder->createSubroutineType(
|
2013-07-02 11:10:24 -05:00
|
|
|
unwrapDI<DIFile>(File),
|
2014-08-15 09:36:05 -05:00
|
|
|
#if LLVM_VERSION_MINOR >= 6
|
2014-08-01 04:23:05 -05:00
|
|
|
unwrapDI<DITypeArray>(ParameterTypes)));
|
2014-08-15 09:36:05 -05:00
|
|
|
#else
|
|
|
|
unwrapDI<DIArray>(ParameterTypes)));
|
|
|
|
#endif
|
2013-06-14 13:38:29 -05:00
|
|
|
}
|
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" LLVMMetadataRef LLVMDIBuilderCreateFunction(
|
2013-06-14 13:38:29 -05:00
|
|
|
DIBuilderRef Builder,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef Scope,
|
2013-06-14 13:38:29 -05:00
|
|
|
const char* Name,
|
|
|
|
const char* LinkageName,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef File,
|
2013-06-14 13:38:29 -05:00
|
|
|
unsigned LineNo,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef Ty,
|
2013-06-14 13:38:29 -05:00
|
|
|
bool isLocalToUnit,
|
|
|
|
bool isDefinition,
|
|
|
|
unsigned ScopeLine,
|
|
|
|
unsigned Flags,
|
|
|
|
bool isOptimized,
|
|
|
|
LLVMValueRef Fn,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef TParam,
|
|
|
|
LLVMMetadataRef Decl) {
|
2013-06-14 13:38:29 -05:00
|
|
|
return wrap(Builder->createFunction(
|
2013-07-02 11:10:24 -05:00
|
|
|
unwrapDI<DIScope>(Scope), Name, LinkageName,
|
|
|
|
unwrapDI<DIFile>(File), LineNo,
|
2013-08-05 23:21:37 -05:00
|
|
|
unwrapDI<DICompositeType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
|
2013-06-14 13:38:29 -05:00
|
|
|
Flags, isOptimized,
|
2013-07-02 11:10:24 -05:00
|
|
|
unwrap<Function>(Fn),
|
2013-06-14 13:38:29 -05:00
|
|
|
unwrapDI<MDNode*>(TParam),
|
|
|
|
unwrapDI<MDNode*>(Decl)));
|
|
|
|
}
|
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" LLVMMetadataRef LLVMDIBuilderCreateBasicType(
|
2013-06-14 13:38:29 -05:00
|
|
|
DIBuilderRef Builder,
|
|
|
|
const char* Name,
|
|
|
|
uint64_t SizeInBits,
|
|
|
|
uint64_t AlignInBits,
|
|
|
|
unsigned Encoding) {
|
|
|
|
return wrap(Builder->createBasicType(
|
2013-07-02 11:10:24 -05:00
|
|
|
Name, SizeInBits,
|
2013-06-14 13:38:29 -05:00
|
|
|
AlignInBits, Encoding));
|
|
|
|
}
|
2013-07-02 11:10:24 -05:00
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" LLVMMetadataRef LLVMDIBuilderCreatePointerType(
|
2013-06-14 13:38:29 -05:00
|
|
|
DIBuilderRef Builder,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef PointeeTy,
|
2013-06-14 13:38:29 -05:00
|
|
|
uint64_t SizeInBits,
|
|
|
|
uint64_t AlignInBits,
|
|
|
|
const char* Name) {
|
|
|
|
return wrap(Builder->createPointerType(
|
|
|
|
unwrapDI<DIType>(PointeeTy), SizeInBits, AlignInBits, Name));
|
|
|
|
}
|
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" LLVMMetadataRef LLVMDIBuilderCreateStructType(
|
2013-06-14 13:38:29 -05:00
|
|
|
DIBuilderRef Builder,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef Scope,
|
2013-06-14 13:38:29 -05:00
|
|
|
const char* Name,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef File,
|
2013-06-14 13:38:29 -05:00
|
|
|
unsigned LineNumber,
|
|
|
|
uint64_t SizeInBits,
|
|
|
|
uint64_t AlignInBits,
|
|
|
|
unsigned Flags,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef DerivedFrom,
|
|
|
|
LLVMMetadataRef Elements,
|
2013-06-14 13:38:29 -05:00
|
|
|
unsigned RunTimeLang,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef VTableHolder,
|
2013-10-01 05:24:50 -05:00
|
|
|
const char *UniqueId) {
|
2013-06-14 13:38:29 -05:00
|
|
|
return wrap(Builder->createStructType(
|
2013-10-01 05:24:50 -05:00
|
|
|
unwrapDI<DIDescriptor>(Scope),
|
|
|
|
Name,
|
|
|
|
unwrapDI<DIFile>(File),
|
|
|
|
LineNumber,
|
|
|
|
SizeInBits,
|
|
|
|
AlignInBits,
|
|
|
|
Flags,
|
2013-07-02 11:10:24 -05:00
|
|
|
unwrapDI<DIType>(DerivedFrom),
|
2013-10-01 05:24:50 -05:00
|
|
|
unwrapDI<DIArray>(Elements),
|
|
|
|
RunTimeLang,
|
2015-03-14 07:14:04 -05:00
|
|
|
unwrapDI<DIType>(VTableHolder),
|
|
|
|
UniqueId
|
2014-03-31 16:43:19 -05:00
|
|
|
));
|
2013-06-14 13:38:29 -05:00
|
|
|
}
|
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" LLVMMetadataRef LLVMDIBuilderCreateMemberType(
|
2013-06-14 13:38:29 -05:00
|
|
|
DIBuilderRef Builder,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef Scope,
|
2013-06-14 13:38:29 -05:00
|
|
|
const char* Name,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef File,
|
2013-06-14 13:38:29 -05:00
|
|
|
unsigned LineNo,
|
|
|
|
uint64_t SizeInBits,
|
|
|
|
uint64_t AlignInBits,
|
|
|
|
uint64_t OffsetInBits,
|
|
|
|
unsigned Flags,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef Ty) {
|
2013-06-14 13:38:29 -05:00
|
|
|
return wrap(Builder->createMemberType(
|
2013-07-02 11:10:24 -05:00
|
|
|
unwrapDI<DIDescriptor>(Scope), Name,
|
2013-06-14 13:38:29 -05:00
|
|
|
unwrapDI<DIFile>(File), LineNo,
|
2013-07-02 11:10:24 -05:00
|
|
|
SizeInBits, AlignInBits, OffsetInBits, Flags,
|
2013-06-14 13:38:29 -05:00
|
|
|
unwrapDI<DIType>(Ty)));
|
|
|
|
}
|
2013-07-02 11:10:24 -05:00
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" LLVMMetadataRef LLVMDIBuilderCreateLexicalBlock(
|
2013-06-14 13:38:29 -05:00
|
|
|
DIBuilderRef Builder,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef Scope,
|
|
|
|
LLVMMetadataRef File,
|
2013-06-14 13:38:29 -05:00
|
|
|
unsigned Line,
|
2014-09-30 16:20:22 -05:00
|
|
|
unsigned Col) {
|
2013-06-14 13:38:29 -05:00
|
|
|
return wrap(Builder->createLexicalBlock(
|
2013-07-02 11:10:24 -05:00
|
|
|
unwrapDI<DIDescriptor>(Scope),
|
2014-03-31 16:43:19 -05:00
|
|
|
unwrapDI<DIFile>(File), Line, Col
|
2014-09-30 16:20:22 -05:00
|
|
|
#if LLVM_VERSION_MINOR == 5
|
|
|
|
, 0
|
2014-03-31 16:43:19 -05:00
|
|
|
#endif
|
|
|
|
));
|
2013-06-14 13:38:29 -05:00
|
|
|
}
|
2013-07-02 11:10:24 -05:00
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" LLVMMetadataRef LLVMDIBuilderCreateStaticVariable(
|
2014-02-20 19:44:29 -06:00
|
|
|
DIBuilderRef Builder,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef Context,
|
2014-02-20 19:44:29 -06:00
|
|
|
const char* Name,
|
|
|
|
const char* LinkageName,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef File,
|
2014-02-20 19:44:29 -06:00
|
|
|
unsigned LineNo,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef Ty,
|
2014-02-20 19:44:29 -06:00
|
|
|
bool isLocalToUnit,
|
|
|
|
LLVMValueRef Val,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef Decl = NULL) {
|
2014-09-30 16:20:22 -05:00
|
|
|
#if LLVM_VERSION_MINOR == 6
|
|
|
|
return wrap(Builder->createGlobalVariable(unwrapDI<DIDescriptor>(Context),
|
|
|
|
#else
|
2014-02-20 19:44:29 -06:00
|
|
|
return wrap(Builder->createStaticVariable(unwrapDI<DIDescriptor>(Context),
|
2014-09-30 16:20:22 -05:00
|
|
|
#endif
|
2014-02-20 19:44:29 -06:00
|
|
|
Name,
|
|
|
|
LinkageName,
|
|
|
|
unwrapDI<DIFile>(File),
|
|
|
|
LineNo,
|
|
|
|
unwrapDI<DIType>(Ty),
|
|
|
|
isLocalToUnit,
|
2015-01-30 12:25:07 -06:00
|
|
|
cast<Constant>(unwrap(Val)),
|
2014-02-20 19:44:29 -06:00
|
|
|
unwrapDI<MDNode*>(Decl)));
|
|
|
|
}
|
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" LLVMMetadataRef LLVMDIBuilderCreateVariable(
|
2013-06-14 13:38:29 -05:00
|
|
|
DIBuilderRef Builder,
|
|
|
|
unsigned Tag,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef Scope,
|
2013-06-14 13:38:29 -05:00
|
|
|
const char* Name,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef File,
|
2013-06-14 13:38:29 -05:00
|
|
|
unsigned LineNo,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef Ty,
|
2013-06-14 13:38:29 -05:00
|
|
|
bool AlwaysPreserve,
|
|
|
|
unsigned Flags,
|
2015-01-30 12:25:07 -06:00
|
|
|
int64_t* AddrOps,
|
|
|
|
unsigned AddrOpsCount,
|
2013-06-14 13:38:29 -05:00
|
|
|
unsigned ArgNo) {
|
2015-01-30 12:25:07 -06:00
|
|
|
#if LLVM_VERSION_MINOR < 6
|
|
|
|
if (AddrOpsCount > 0) {
|
|
|
|
SmallVector<llvm::Value *, 16> addr_ops;
|
2015-03-14 07:14:04 -05:00
|
|
|
llvm::Type *Int64Ty = Type::getInt64Ty(unwrap<MDNode>(Scope)->getContext());
|
|
|
|
for (unsigned i = 0; i < AddrOpsCount; ++i)
|
2015-01-30 12:25:07 -06:00
|
|
|
addr_ops.push_back(ConstantInt::get(Int64Ty, AddrOps[i]));
|
|
|
|
|
|
|
|
return wrap(Builder->createComplexVariable(
|
|
|
|
Tag,
|
|
|
|
unwrapDI<DIDescriptor>(Scope),
|
|
|
|
Name,
|
|
|
|
unwrapDI<DIFile>(File),
|
|
|
|
LineNo,
|
|
|
|
unwrapDI<DIType>(Ty),
|
|
|
|
addr_ops,
|
|
|
|
ArgNo
|
|
|
|
));
|
|
|
|
}
|
|
|
|
#endif
|
2013-07-02 11:10:24 -05:00
|
|
|
return wrap(Builder->createLocalVariable(Tag,
|
|
|
|
unwrapDI<DIDescriptor>(Scope), Name,
|
|
|
|
unwrapDI<DIFile>(File),
|
|
|
|
LineNo,
|
2013-06-14 13:38:29 -05:00
|
|
|
unwrapDI<DIType>(Ty), AlwaysPreserve, Flags, ArgNo));
|
|
|
|
}
|
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" LLVMMetadataRef LLVMDIBuilderCreateArrayType(
|
2013-06-14 14:23:42 -05:00
|
|
|
DIBuilderRef Builder,
|
2013-07-02 11:10:24 -05:00
|
|
|
uint64_t Size,
|
|
|
|
uint64_t AlignInBits,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef Ty,
|
|
|
|
LLVMMetadataRef Subscripts) {
|
2013-06-14 14:23:42 -05:00
|
|
|
return wrap(Builder->createArrayType(Size, AlignInBits,
|
2013-07-02 11:10:24 -05:00
|
|
|
unwrapDI<DIType>(Ty),
|
2013-06-14 14:23:42 -05:00
|
|
|
unwrapDI<DIArray>(Subscripts)));
|
|
|
|
}
|
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" LLVMMetadataRef LLVMDIBuilderCreateVectorType(
|
2013-06-14 13:38:29 -05:00
|
|
|
DIBuilderRef Builder,
|
2013-07-02 11:10:24 -05:00
|
|
|
uint64_t Size,
|
|
|
|
uint64_t AlignInBits,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef Ty,
|
|
|
|
LLVMMetadataRef Subscripts) {
|
2013-06-14 13:38:29 -05:00
|
|
|
return wrap(Builder->createVectorType(Size, AlignInBits,
|
2013-07-02 11:10:24 -05:00
|
|
|
unwrapDI<DIType>(Ty),
|
2013-06-14 13:38:29 -05:00
|
|
|
unwrapDI<DIArray>(Subscripts)));
|
|
|
|
}
|
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateSubrange(
|
2013-07-02 11:10:24 -05:00
|
|
|
DIBuilderRef Builder,
|
|
|
|
int64_t Lo,
|
2013-06-14 13:38:29 -05:00
|
|
|
int64_t Count) {
|
|
|
|
return wrap(Builder->getOrCreateSubrange(Lo, Count));
|
|
|
|
}
|
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" LLVMMetadataRef LLVMDIBuilderGetOrCreateArray(
|
2013-06-14 13:38:29 -05:00
|
|
|
DIBuilderRef Builder,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef* Ptr,
|
2013-06-14 13:38:29 -05:00
|
|
|
unsigned Count) {
|
|
|
|
return wrap(Builder->getOrCreateArray(
|
2015-03-14 07:14:04 -05:00
|
|
|
#if LLVM_VERSION_MINOR >= 6
|
2015-01-30 12:25:07 -06:00
|
|
|
ArrayRef<Metadata*>(unwrap(Ptr), Count)));
|
2015-03-14 07:14:04 -05:00
|
|
|
#else
|
|
|
|
ArrayRef<Value*>(reinterpret_cast<Value**>(Ptr), Count)));
|
|
|
|
#endif
|
2013-06-14 13:38:29 -05:00
|
|
|
}
|
|
|
|
|
2013-06-11 02:57:25 -05:00
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(
|
|
|
|
DIBuilderRef Builder,
|
|
|
|
LLVMValueRef Val,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef VarInfo,
|
|
|
|
int64_t* AddrOps,
|
|
|
|
unsigned AddrOpsCount,
|
2013-06-11 02:57:25 -05:00
|
|
|
LLVMBasicBlockRef InsertAtEnd) {
|
2015-01-30 12:25:07 -06:00
|
|
|
#if LLVM_VERSION_MINOR >= 6
|
|
|
|
DIExpression Expr;
|
|
|
|
if (AddrOpsCount == 0) {
|
|
|
|
Expr = Builder->createExpression();
|
|
|
|
} else {
|
|
|
|
llvm::ArrayRef<int64_t> addr_ops(AddrOps, AddrOpsCount);
|
|
|
|
Expr = Builder->createExpression(addr_ops);
|
|
|
|
}
|
|
|
|
#endif
|
2013-06-11 02:57:25 -05:00
|
|
|
return wrap(Builder->insertDeclare(
|
2013-07-02 11:10:24 -05:00
|
|
|
unwrap(Val),
|
|
|
|
unwrapDI<DIVariable>(VarInfo),
|
2015-01-30 12:25:07 -06:00
|
|
|
#if LLVM_VERSION_MINOR >= 6
|
|
|
|
Expr,
|
|
|
|
#endif
|
2013-06-11 02:57:25 -05:00
|
|
|
unwrap(InsertAtEnd)));
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareBefore(
|
2013-06-14 13:38:29 -05:00
|
|
|
DIBuilderRef Builder,
|
|
|
|
LLVMValueRef Val,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef VarInfo,
|
|
|
|
int64_t* AddrOps,
|
|
|
|
unsigned AddrOpsCount,
|
2013-06-14 13:38:29 -05:00
|
|
|
LLVMValueRef InsertBefore) {
|
2015-01-30 12:25:07 -06:00
|
|
|
#if LLVM_VERSION_MINOR >= 6
|
|
|
|
DIExpression Expr;
|
|
|
|
if (AddrOpsCount == 0) {
|
|
|
|
Expr = Builder->createExpression();
|
|
|
|
} else {
|
|
|
|
llvm::ArrayRef<int64_t> addr_ops(AddrOps, AddrOpsCount);
|
|
|
|
Expr = Builder->createExpression(addr_ops);
|
|
|
|
}
|
|
|
|
#endif
|
2013-06-14 13:38:29 -05:00
|
|
|
return wrap(Builder->insertDeclare(
|
2013-07-02 11:10:24 -05:00
|
|
|
unwrap(Val),
|
|
|
|
unwrapDI<DIVariable>(VarInfo),
|
2015-01-30 12:25:07 -06:00
|
|
|
#if LLVM_VERSION_MINOR >= 6
|
|
|
|
Expr,
|
|
|
|
#endif
|
2013-06-14 13:38:29 -05:00
|
|
|
unwrap<Instruction>(InsertBefore)));
|
|
|
|
}
|
2013-07-02 03:33:51 -05:00
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" LLVMMetadataRef LLVMDIBuilderCreateEnumerator(
|
2013-07-02 03:33:51 -05:00
|
|
|
DIBuilderRef Builder,
|
|
|
|
const char* Name,
|
|
|
|
uint64_t Val)
|
|
|
|
{
|
|
|
|
return wrap(Builder->createEnumerator(Name, Val));
|
|
|
|
}
|
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" LLVMMetadataRef LLVMDIBuilderCreateEnumerationType(
|
2013-07-02 03:33:51 -05:00
|
|
|
DIBuilderRef Builder,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef Scope,
|
2013-07-02 03:33:51 -05:00
|
|
|
const char* Name,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef File,
|
2013-07-02 03:33:51 -05:00
|
|
|
unsigned LineNumber,
|
|
|
|
uint64_t SizeInBits,
|
|
|
|
uint64_t AlignInBits,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef Elements,
|
|
|
|
LLVMMetadataRef ClassType)
|
2013-07-02 03:33:51 -05:00
|
|
|
{
|
|
|
|
return wrap(Builder->createEnumerationType(
|
|
|
|
unwrapDI<DIDescriptor>(Scope),
|
|
|
|
Name,
|
|
|
|
unwrapDI<DIFile>(File),
|
|
|
|
LineNumber,
|
|
|
|
SizeInBits,
|
|
|
|
AlignInBits,
|
|
|
|
unwrapDI<DIArray>(Elements),
|
|
|
|
unwrapDI<DIType>(ClassType)));
|
2013-07-02 11:10:24 -05:00
|
|
|
}
|
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" LLVMMetadataRef LLVMDIBuilderCreateUnionType(
|
2013-07-02 11:10:24 -05:00
|
|
|
DIBuilderRef Builder,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef Scope,
|
2013-07-02 11:10:24 -05:00
|
|
|
const char* Name,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef File,
|
2013-07-02 11:10:24 -05:00
|
|
|
unsigned LineNumber,
|
|
|
|
uint64_t SizeInBits,
|
|
|
|
uint64_t AlignInBits,
|
|
|
|
unsigned Flags,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef Elements,
|
2014-01-02 08:20:43 -06:00
|
|
|
unsigned RunTimeLang,
|
|
|
|
const char* UniqueId)
|
2013-07-02 11:10:24 -05:00
|
|
|
{
|
|
|
|
return wrap(Builder->createUnionType(
|
|
|
|
unwrapDI<DIDescriptor>(Scope),
|
|
|
|
Name,
|
|
|
|
unwrapDI<DIFile>(File),
|
|
|
|
LineNumber,
|
|
|
|
SizeInBits,
|
|
|
|
AlignInBits,
|
|
|
|
Flags,
|
|
|
|
unwrapDI<DIArray>(Elements),
|
2015-03-14 07:14:04 -05:00
|
|
|
RunTimeLang,
|
|
|
|
UniqueId
|
2014-03-31 16:43:19 -05:00
|
|
|
));
|
2013-07-28 02:48:16 -05:00
|
|
|
}
|
2013-08-09 15:47:00 -05:00
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" LLVMMetadataRef LLVMDIBuilderCreateTemplateTypeParameter(
|
2013-08-08 11:33:06 -05:00
|
|
|
DIBuilderRef Builder,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef Scope,
|
2013-08-08 11:33:06 -05:00
|
|
|
const char* Name,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef Ty,
|
|
|
|
LLVMMetadataRef File,
|
2013-09-05 06:29:30 -05:00
|
|
|
unsigned LineNo,
|
|
|
|
unsigned ColumnNo)
|
2013-08-08 11:33:06 -05:00
|
|
|
{
|
|
|
|
return wrap(Builder->createTemplateTypeParameter(
|
|
|
|
unwrapDI<DIDescriptor>(Scope),
|
|
|
|
Name,
|
|
|
|
unwrapDI<DIType>(Ty),
|
|
|
|
unwrapDI<MDNode*>(File),
|
|
|
|
LineNo,
|
|
|
|
ColumnNo));
|
|
|
|
}
|
2013-08-23 11:45:02 -05:00
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" int64_t LLVMDIBuilderCreateOpDeref()
|
2013-08-23 11:45:02 -05:00
|
|
|
{
|
2015-01-30 12:25:07 -06:00
|
|
|
return dwarf::DW_OP_deref;
|
2013-08-23 11:45:02 -05:00
|
|
|
}
|
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" int64_t LLVMDIBuilderCreateOpPlus()
|
2013-08-23 11:45:02 -05:00
|
|
|
{
|
2015-01-30 12:25:07 -06:00
|
|
|
return dwarf::DW_OP_plus;
|
2013-08-23 11:45:02 -05:00
|
|
|
}
|
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" LLVMMetadataRef LLVMDIBuilderCreateNameSpace(
|
2013-08-23 11:45:02 -05:00
|
|
|
DIBuilderRef Builder,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef Scope,
|
2013-09-05 06:29:30 -05:00
|
|
|
const char* Name,
|
2015-01-30 12:25:07 -06:00
|
|
|
LLVMMetadataRef File,
|
2013-09-05 06:29:30 -05:00
|
|
|
unsigned LineNo)
|
|
|
|
{
|
|
|
|
return wrap(Builder->createNameSpace(
|
|
|
|
unwrapDI<DIDescriptor>(Scope),
|
|
|
|
Name,
|
|
|
|
unwrapDI<DIFile>(File),
|
|
|
|
LineNo));
|
|
|
|
}
|
2013-09-11 09:37:43 -05:00
|
|
|
|
|
|
|
extern "C" void LLVMDICompositeTypeSetTypeArray(
|
2015-01-30 12:25:07 -06:00
|
|
|
DIBuilderRef Builder,
|
|
|
|
LLVMMetadataRef CompositeType,
|
|
|
|
LLVMMetadataRef TypeArray)
|
2013-09-11 09:37:43 -05:00
|
|
|
{
|
2014-08-15 09:36:05 -05:00
|
|
|
#if LLVM_VERSION_MINOR >= 6
|
2015-01-30 12:25:07 -06:00
|
|
|
DICompositeType tmp = unwrapDI<DICompositeType>(CompositeType);
|
|
|
|
Builder->replaceArrays(tmp, unwrapDI<DIArray>(TypeArray));
|
2014-08-15 09:36:05 -05:00
|
|
|
#else
|
|
|
|
unwrapDI<DICompositeType>(CompositeType).setTypeArray(unwrapDI<DIArray>(TypeArray));
|
|
|
|
#endif
|
2013-09-11 09:37:43 -05:00
|
|
|
}
|
2013-10-11 18:56:11 -05:00
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderCreateDebugLocation(
|
|
|
|
LLVMContextRef Context,
|
|
|
|
unsigned Line,
|
|
|
|
unsigned Column,
|
|
|
|
LLVMMetadataRef Scope,
|
|
|
|
LLVMMetadataRef InlinedAt) {
|
|
|
|
|
|
|
|
LLVMContext& context = *unwrap(Context);
|
|
|
|
|
|
|
|
DebugLoc debug_loc = DebugLoc::get(Line,
|
|
|
|
Column,
|
|
|
|
unwrapDI<MDNode*>(Scope),
|
|
|
|
unwrapDI<MDNode*>(InlinedAt));
|
|
|
|
|
|
|
|
#if LLVM_VERSION_MINOR >= 6
|
|
|
|
return wrap(MetadataAsValue::get(context, debug_loc.getAsMDNode(context)));
|
|
|
|
#else
|
|
|
|
return wrap(debug_loc.getAsMDNode(context));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-09-10 01:12:09 -05:00
|
|
|
extern "C" void LLVMWriteTypeToString(LLVMTypeRef Type, RustStringRef str) {
|
|
|
|
raw_rust_string_ostream os(str);
|
2013-10-11 18:56:11 -05:00
|
|
|
unwrap<llvm::Type>(Type)->print(os);
|
|
|
|
}
|
Implement LTO
This commit implements LTO for rust leveraging LLVM's passes. What this means
is:
* When compiling an rlib, in addition to insdering foo.o into the archive, also
insert foo.bc (the LLVM bytecode) of the optimized module.
* When the compiler detects the -Z lto option, it will attempt to perform LTO on
a staticlib or binary output. The compiler will emit an error if a dylib or
rlib output is being generated.
* The actual act of performing LTO is as follows:
1. Force all upstream libraries to have an rlib version available.
2. Load the bytecode of each upstream library from the rlib.
3. Link all this bytecode into the current LLVM module (just using llvm
apis)
4. Run an internalization pass which internalizes all symbols except those
found reachable for the local crate of compilation.
5. Run the LLVM LTO pass manager over this entire module
6a. If assembling an archive, then add all upstream rlibs into the output
archive. This ignores all of the object/bitcode/metadata files rust
generated and placed inside the rlibs.
6b. If linking a binary, create copies of all upstream rlibs, remove the
rust-generated object-file, and then link everything as usual.
As I have explained in #10741, this process is excruciatingly slow, so this is
*not* turned on by default, and it is also why I have decided to hide it behind
a -Z flag for now. The good news is that the binary sizes are about as small as
they can be as a result of LTO, so it's definitely working.
Closes #10741
Closes #10740
2013-12-03 01:19:29 -06:00
|
|
|
|
2014-09-10 01:12:09 -05:00
|
|
|
extern "C" void LLVMWriteValueToString(LLVMValueRef Value, RustStringRef str) {
|
|
|
|
raw_rust_string_ostream os(str);
|
2014-01-15 13:39:08 -06:00
|
|
|
os << "(";
|
|
|
|
unwrap<llvm::Value>(Value)->getType()->print(os);
|
|
|
|
os << ":";
|
|
|
|
unwrap<llvm::Value>(Value)->print(os);
|
|
|
|
os << ")";
|
|
|
|
}
|
|
|
|
|
Implement LTO
This commit implements LTO for rust leveraging LLVM's passes. What this means
is:
* When compiling an rlib, in addition to insdering foo.o into the archive, also
insert foo.bc (the LLVM bytecode) of the optimized module.
* When the compiler detects the -Z lto option, it will attempt to perform LTO on
a staticlib or binary output. The compiler will emit an error if a dylib or
rlib output is being generated.
* The actual act of performing LTO is as follows:
1. Force all upstream libraries to have an rlib version available.
2. Load the bytecode of each upstream library from the rlib.
3. Link all this bytecode into the current LLVM module (just using llvm
apis)
4. Run an internalization pass which internalizes all symbols except those
found reachable for the local crate of compilation.
5. Run the LLVM LTO pass manager over this entire module
6a. If assembling an archive, then add all upstream rlibs into the output
archive. This ignores all of the object/bitcode/metadata files rust
generated and placed inside the rlibs.
6b. If linking a binary, create copies of all upstream rlibs, remove the
rust-generated object-file, and then link everything as usual.
As I have explained in #10741, this process is excruciatingly slow, so this is
*not* turned on by default, and it is also why I have decided to hide it behind
a -Z flag for now. The good news is that the binary sizes are about as small as
they can be as a result of LTO, so it's definitely working.
Closes #10741
Closes #10740
2013-12-03 01:19:29 -06:00
|
|
|
extern "C" bool
|
|
|
|
LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
|
|
|
|
Module *Dst = unwrap(dst);
|
2014-09-30 16:20:22 -05:00
|
|
|
#if LLVM_VERSION_MINOR == 5
|
Implement LTO
This commit implements LTO for rust leveraging LLVM's passes. What this means
is:
* When compiling an rlib, in addition to insdering foo.o into the archive, also
insert foo.bc (the LLVM bytecode) of the optimized module.
* When the compiler detects the -Z lto option, it will attempt to perform LTO on
a staticlib or binary output. The compiler will emit an error if a dylib or
rlib output is being generated.
* The actual act of performing LTO is as follows:
1. Force all upstream libraries to have an rlib version available.
2. Load the bytecode of each upstream library from the rlib.
3. Link all this bytecode into the current LLVM module (just using llvm
apis)
4. Run an internalization pass which internalizes all symbols except those
found reachable for the local crate of compilation.
5. Run the LLVM LTO pass manager over this entire module
6a. If assembling an archive, then add all upstream rlibs into the output
archive. This ignores all of the object/bitcode/metadata files rust
generated and placed inside the rlibs.
6b. If linking a binary, create copies of all upstream rlibs, remove the
rust-generated object-file, and then link everything as usual.
As I have explained in #10741, this process is excruciatingly slow, so this is
*not* turned on by default, and it is also why I have decided to hide it behind
a -Z flag for now. The good news is that the binary sizes are about as small as
they can be as a result of LTO, so it's definitely working.
Closes #10741
Closes #10740
2013-12-03 01:19:29 -06:00
|
|
|
MemoryBuffer* buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
|
2014-01-27 14:45:48 -06:00
|
|
|
ErrorOr<Module *> Src = llvm::getLazyBitcodeModule(buf, Dst->getContext());
|
2014-09-30 16:20:22 -05:00
|
|
|
#else
|
|
|
|
std::unique_ptr<MemoryBuffer> buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
|
|
|
|
ErrorOr<Module *> Src = llvm::getLazyBitcodeModule(std::move(buf), Dst->getContext());
|
|
|
|
#endif
|
2014-01-27 14:45:48 -06:00
|
|
|
if (!Src) {
|
2014-04-15 09:25:22 -05:00
|
|
|
LLVMRustSetLastError(Src.getError().message().c_str());
|
2014-09-30 16:20:22 -05:00
|
|
|
#if LLVM_VERSION_MINOR == 5
|
Implement LTO
This commit implements LTO for rust leveraging LLVM's passes. What this means
is:
* When compiling an rlib, in addition to insdering foo.o into the archive, also
insert foo.bc (the LLVM bytecode) of the optimized module.
* When the compiler detects the -Z lto option, it will attempt to perform LTO on
a staticlib or binary output. The compiler will emit an error if a dylib or
rlib output is being generated.
* The actual act of performing LTO is as follows:
1. Force all upstream libraries to have an rlib version available.
2. Load the bytecode of each upstream library from the rlib.
3. Link all this bytecode into the current LLVM module (just using llvm
apis)
4. Run an internalization pass which internalizes all symbols except those
found reachable for the local crate of compilation.
5. Run the LLVM LTO pass manager over this entire module
6a. If assembling an archive, then add all upstream rlibs into the output
archive. This ignores all of the object/bitcode/metadata files rust
generated and placed inside the rlibs.
6b. If linking a binary, create copies of all upstream rlibs, remove the
rust-generated object-file, and then link everything as usual.
As I have explained in #10741, this process is excruciatingly slow, so this is
*not* turned on by default, and it is also why I have decided to hide it behind
a -Z flag for now. The good news is that the binary sizes are about as small as
they can be as a result of LTO, so it's definitely working.
Closes #10741
Closes #10740
2013-12-03 01:19:29 -06:00
|
|
|
delete buf;
|
2014-09-30 16:20:22 -05:00
|
|
|
#endif
|
Implement LTO
This commit implements LTO for rust leveraging LLVM's passes. What this means
is:
* When compiling an rlib, in addition to insdering foo.o into the archive, also
insert foo.bc (the LLVM bytecode) of the optimized module.
* When the compiler detects the -Z lto option, it will attempt to perform LTO on
a staticlib or binary output. The compiler will emit an error if a dylib or
rlib output is being generated.
* The actual act of performing LTO is as follows:
1. Force all upstream libraries to have an rlib version available.
2. Load the bytecode of each upstream library from the rlib.
3. Link all this bytecode into the current LLVM module (just using llvm
apis)
4. Run an internalization pass which internalizes all symbols except those
found reachable for the local crate of compilation.
5. Run the LLVM LTO pass manager over this entire module
6a. If assembling an archive, then add all upstream rlibs into the output
archive. This ignores all of the object/bitcode/metadata files rust
generated and placed inside the rlibs.
6b. If linking a binary, create copies of all upstream rlibs, remove the
rust-generated object-file, and then link everything as usual.
As I have explained in #10741, this process is excruciatingly slow, so this is
*not* turned on by default, and it is also why I have decided to hide it behind
a -Z flag for now. The good news is that the binary sizes are about as small as
they can be as a result of LTO, so it's definitely working.
Closes #10741
Closes #10740
2013-12-03 01:19:29 -06:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-01-27 14:45:48 -06:00
|
|
|
std::string Err;
|
2015-01-30 12:25:07 -06:00
|
|
|
|
|
|
|
#if LLVM_VERSION_MINOR >= 6
|
|
|
|
raw_string_ostream Stream(Err);
|
|
|
|
DiagnosticPrinterRawOStream DP(Stream);
|
|
|
|
if (Linker::LinkModules(Dst, *Src, [&](const DiagnosticInfo &DI) { DI.print(DP); })) {
|
|
|
|
#else
|
2014-01-27 14:45:48 -06:00
|
|
|
if (Linker::LinkModules(Dst, *Src, Linker::DestroySource, &Err)) {
|
2015-01-30 12:25:07 -06:00
|
|
|
#endif
|
2014-04-15 09:25:22 -05:00
|
|
|
LLVMRustSetLastError(Err.c_str());
|
Implement LTO
This commit implements LTO for rust leveraging LLVM's passes. What this means
is:
* When compiling an rlib, in addition to insdering foo.o into the archive, also
insert foo.bc (the LLVM bytecode) of the optimized module.
* When the compiler detects the -Z lto option, it will attempt to perform LTO on
a staticlib or binary output. The compiler will emit an error if a dylib or
rlib output is being generated.
* The actual act of performing LTO is as follows:
1. Force all upstream libraries to have an rlib version available.
2. Load the bytecode of each upstream library from the rlib.
3. Link all this bytecode into the current LLVM module (just using llvm
apis)
4. Run an internalization pass which internalizes all symbols except those
found reachable for the local crate of compilation.
5. Run the LLVM LTO pass manager over this entire module
6a. If assembling an archive, then add all upstream rlibs into the output
archive. This ignores all of the object/bitcode/metadata files rust
generated and placed inside the rlibs.
6b. If linking a binary, create copies of all upstream rlibs, remove the
rust-generated object-file, and then link everything as usual.
As I have explained in #10741, this process is excruciatingly slow, so this is
*not* turned on by default, and it is also why I have decided to hide it behind
a -Z flag for now. The good news is that the binary sizes are about as small as
they can be as a result of LTO, so it's definitely working.
Closes #10741
Closes #10740
2013-12-03 01:19:29 -06:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2013-12-16 22:58:21 -06:00
|
|
|
|
2014-03-31 16:43:19 -05:00
|
|
|
extern "C" void*
|
|
|
|
LLVMRustOpenArchive(char *path) {
|
2014-07-18 09:07:15 -05:00
|
|
|
ErrorOr<std::unique_ptr<MemoryBuffer>> buf_or = MemoryBuffer::getFile(path,
|
|
|
|
-1,
|
|
|
|
false);
|
2014-07-23 01:14:58 -05:00
|
|
|
if (!buf_or) {
|
|
|
|
LLVMRustSetLastError(buf_or.getError().message().c_str());
|
2014-07-18 09:07:15 -05:00
|
|
|
return nullptr;
|
2014-03-31 16:43:19 -05:00
|
|
|
}
|
2014-07-23 01:14:58 -05:00
|
|
|
|
2014-09-30 16:20:22 -05:00
|
|
|
#if LLVM_VERSION_MINOR >= 6
|
|
|
|
ErrorOr<std::unique_ptr<Archive>> archive_or =
|
|
|
|
Archive::create(buf_or.get()->getMemBufferRef());
|
|
|
|
|
|
|
|
if (!archive_or) {
|
|
|
|
LLVMRustSetLastError(archive_or.getError().message().c_str());
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
OwningBinary<Archive> *ret = new OwningBinary<Archive>(
|
|
|
|
std::move(archive_or.get()), std::move(buf_or.get()));
|
|
|
|
#else
|
2014-07-23 01:14:58 -05:00
|
|
|
std::error_code err;
|
|
|
|
Archive *ret = new Archive(std::move(buf_or.get()), err);
|
2014-03-31 16:43:19 -05:00
|
|
|
if (err) {
|
2014-04-15 09:25:22 -05:00
|
|
|
LLVMRustSetLastError(err.message().c_str());
|
2014-09-30 16:20:22 -05:00
|
|
|
return nullptr;
|
2014-03-31 16:43:19 -05:00
|
|
|
}
|
2014-09-30 16:20:22 -05:00
|
|
|
#endif
|
|
|
|
|
2014-03-31 16:43:19 -05:00
|
|
|
return ret;
|
|
|
|
}
|
2013-12-16 22:58:21 -06:00
|
|
|
|
|
|
|
extern "C" const char*
|
2014-09-30 16:20:22 -05:00
|
|
|
#if LLVM_VERSION_MINOR >= 6
|
|
|
|
LLVMRustArchiveReadSection(OwningBinary<Archive> *ob, char *name, size_t *size) {
|
|
|
|
|
2015-01-30 12:25:07 -06:00
|
|
|
Archive *ar = ob->getBinary();
|
2014-09-30 16:20:22 -05:00
|
|
|
#else
|
2013-12-16 22:58:21 -06:00
|
|
|
LLVMRustArchiveReadSection(Archive *ar, char *name, size_t *size) {
|
2014-09-30 16:20:22 -05:00
|
|
|
#endif
|
|
|
|
|
2014-02-26 16:06:27 -06:00
|
|
|
Archive::child_iterator child = ar->child_begin(),
|
|
|
|
end = ar->child_end();
|
2014-06-17 11:34:50 -05:00
|
|
|
for (; child != end; ++child) {
|
|
|
|
ErrorOr<StringRef> name_or_err = child->getName();
|
|
|
|
if (name_or_err.getError()) continue;
|
|
|
|
StringRef sect_name = name_or_err.get();
|
2013-12-16 22:58:21 -06:00
|
|
|
if (sect_name.trim(" ") == name) {
|
|
|
|
StringRef buf = child->getBuffer();
|
|
|
|
*size = buf.size();
|
|
|
|
return buf.data();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" void
|
2014-09-30 16:20:22 -05:00
|
|
|
#if LLVM_VERSION_MINOR >= 6
|
|
|
|
LLVMRustDestroyArchive(OwningBinary<Archive> *ar) {
|
|
|
|
#else
|
2013-12-16 22:58:21 -06:00
|
|
|
LLVMRustDestroyArchive(Archive *ar) {
|
2014-09-30 16:20:22 -05:00
|
|
|
#endif
|
2013-12-16 22:58:21 -06:00
|
|
|
delete ar;
|
|
|
|
}
|
2014-01-27 14:45:48 -06:00
|
|
|
|
|
|
|
extern "C" void
|
|
|
|
LLVMRustSetDLLExportStorageClass(LLVMValueRef Value) {
|
|
|
|
GlobalValue *V = unwrap<GlobalValue>(Value);
|
|
|
|
V->setDLLStorageClass(GlobalValue::DLLExportStorageClass);
|
|
|
|
}
|
2014-03-05 17:14:16 -06:00
|
|
|
|
|
|
|
extern "C" int
|
|
|
|
LLVMVersionMinor() {
|
|
|
|
return LLVM_VERSION_MINOR;
|
|
|
|
}
|
2014-04-03 12:45:36 -05:00
|
|
|
|
2014-06-12 11:06:14 -05:00
|
|
|
extern "C" int
|
|
|
|
LLVMVersionMajor() {
|
|
|
|
return LLVM_VERSION_MAJOR;
|
|
|
|
}
|
|
|
|
|
2014-04-03 12:45:36 -05:00
|
|
|
// 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" int
|
|
|
|
LLVMRustGetSectionName(LLVMSectionIteratorRef SI, const char **ptr) {
|
|
|
|
StringRef ret;
|
2014-06-17 11:34:50 -05:00
|
|
|
if (std::error_code ec = (*unwrap(SI))->getName(ret))
|
2014-04-03 12:45:36 -05:00
|
|
|
report_fatal_error(ec.message());
|
|
|
|
*ptr = ret.data();
|
|
|
|
return ret.size();
|
|
|
|
}
|
2014-05-10 03:30:55 -05:00
|
|
|
|
|
|
|
// LLVMArrayType function does not support 64-bit ElementCount
|
|
|
|
extern "C" LLVMTypeRef
|
|
|
|
LLVMRustArrayType(LLVMTypeRef ElementType, uint64_t ElementCount) {
|
|
|
|
return wrap(ArrayType::get(unwrap(ElementType), ElementCount));
|
|
|
|
}
|
2014-09-12 10:17:58 -05:00
|
|
|
|
|
|
|
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
|
|
|
|
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DebugLoc, LLVMDebugLocRef)
|
|
|
|
|
|
|
|
extern "C" void
|
|
|
|
LLVMWriteTwineToString(LLVMTwineRef T, RustStringRef str) {
|
|
|
|
raw_rust_string_ostream os(str);
|
|
|
|
unwrap(T)->print(os);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" void
|
|
|
|
LLVMUnpackOptimizationDiagnostic(
|
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
2015-01-22 12:43:39 -06:00
|
|
|
extern "C" void
|
|
|
|
LLVMUnpackInlineAsmDiagnostic(
|
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
2014-09-12 10:17:58 -05:00
|
|
|
extern "C" void LLVMWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef di, RustStringRef str) {
|
|
|
|
raw_rust_string_ostream os(str);
|
|
|
|
DiagnosticPrinterRawOStream dp(os);
|
|
|
|
unwrap(di)->print(dp);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" int LLVMGetDiagInfoKind(LLVMDiagnosticInfoRef di) {
|
|
|
|
return unwrap(di)->getKind();
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" void LLVMWriteDebugLocToString(
|
|
|
|
LLVMContextRef C,
|
|
|
|
LLVMDebugLocRef dl,
|
|
|
|
RustStringRef str)
|
|
|
|
{
|
|
|
|
raw_rust_string_ostream os(str);
|
|
|
|
unwrap(dl)->print(*unwrap(C), os);
|
|
|
|
}
|
2014-09-27 03:33:36 -05:00
|
|
|
|
|
|
|
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
|
|
|
|
|
|
|
|
extern "C" void LLVMSetInlineAsmDiagnosticHandler(
|
|
|
|
LLVMContextRef C,
|
|
|
|
LLVMContext::InlineAsmDiagHandlerTy H,
|
|
|
|
void *CX)
|
|
|
|
{
|
|
|
|
unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" void LLVMWriteSMDiagnosticToString(LLVMSMDiagnosticRef d, RustStringRef str) {
|
|
|
|
raw_rust_string_ostream os(str);
|
|
|
|
unwrap(d)->print("", os);
|
|
|
|
}
|