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
|
|
|
#if LLVM_VERSION_MINOR >= 5
|
|
|
|
#include "llvm/IR/CallSite.h"
|
|
|
|
#else
|
|
|
|
#include "llvm/Support/CallSite.h"
|
|
|
|
#endif
|
|
|
|
|
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
|
|
|
#if LLVM_VERSION_MINOR >= 5
|
|
|
|
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());
|
|
|
|
}
|
|
|
|
#else
|
2011-03-15 16:57:26 -05:00
|
|
|
extern "C" LLVMMemoryBufferRef
|
|
|
|
LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) {
|
2014-07-18 09:07:15 -05:00
|
|
|
OwningPtr<MemoryBuffer> buf;
|
|
|
|
error_code err = MemoryBuffer::getFile(Path, buf, -1, false);
|
|
|
|
if (err) {
|
|
|
|
LLVMRustSetLastError(err.message().c_str());
|
|
|
|
return NULL;
|
2014-04-15 09:25:22 -05:00
|
|
|
}
|
2014-07-18 09:07:15 -05:00
|
|
|
return wrap(buf.take());
|
2011-03-15 16:57:26 -05:00
|
|
|
}
|
2014-07-18 09:07:15 -05:00
|
|
|
#endif
|
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
|
|
|
|
|
|
|
#if LLVM_VERSION_MINOR >= 5
|
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-07-25 21:47:29 -05:00
|
|
|
#else
|
|
|
|
extern "C" void LLVMAddDereferenceableCallSiteAttr(LLVMValueRef, unsigned, uint64_t) {}
|
|
|
|
#endif
|
2014-07-25 18:06:44 -05:00
|
|
|
|
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 21:47:29 -05:00
|
|
|
#if LLVM_VERSION_MINOR >= 5
|
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-07-25 21:47:29 -05:00
|
|
|
#else
|
|
|
|
extern "C" void LLVMAddDereferenceableAttr(LLVMValueRef, unsigned, uint64_t) {}
|
|
|
|
#endif
|
2014-07-25 18:06:44 -05:00
|
|
|
|
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),
|
2014-03-31 16:43:19 -05:00
|
|
|
unwrap(source), order
|
|
|
|
#if LLVM_VERSION_MINOR >= 5
|
|
|
|
, failure_order
|
|
|
|
#endif
|
|
|
|
));
|
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;
|
|
|
|
|
|
|
|
template<typename DIT>
|
2013-07-02 11:10:24 -05:00
|
|
|
DIT unwrapDI(LLVMValueRef ref) {
|
|
|
|
return DIT(ref ? unwrap<MDNode>(ref) : NULL);
|
2013-06-17 10:42:05 -05:00
|
|
|
}
|
2013-06-14 13:38:29 -05:00
|
|
|
|
2014-02-26 16:06:27 -06:00
|
|
|
#if LLVM_VERSION_MINOR >= 5
|
2014-01-27 23:05:33 -06:00
|
|
|
extern "C" const uint32_t LLVMRustDebugMetadataVersion = DEBUG_METADATA_VERSION;
|
2014-02-26 16:06:27 -06:00
|
|
|
#else
|
|
|
|
extern "C" const uint32_t LLVMRustDebugMetadataVersion = 1;
|
|
|
|
#endif
|
2014-01-27 23:05:33 -06:00
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2013-06-11 02:57:25 -05:00
|
|
|
extern "C" void 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) {
|
|
|
|
Builder->createCompileUnit(Lang, File, Dir, Producer, isOptimized,
|
|
|
|
Flags, RuntimeVer, SplitName);
|
|
|
|
}
|
|
|
|
|
2013-06-11 02:57:25 -05:00
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderCreateFile(
|
2013-06-14 13:38:29 -05:00
|
|
|
DIBuilderRef Builder,
|
|
|
|
const char* Filename,
|
|
|
|
const char* Directory) {
|
|
|
|
return wrap(Builder->createFile(Filename, Directory));
|
|
|
|
}
|
|
|
|
|
2013-06-11 02:57:25 -05:00
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderCreateSubroutineType(
|
2013-06-14 13:38:29 -05:00
|
|
|
DIBuilderRef Builder,
|
2013-07-02 11:10:24 -05:00
|
|
|
LLVMValueRef File,
|
2013-06-14 13:38:29 -05:00
|
|
|
LLVMValueRef ParameterTypes) {
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2013-06-11 02:57:25 -05:00
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderCreateFunction(
|
2013-06-14 13:38:29 -05:00
|
|
|
DIBuilderRef Builder,
|
2013-07-02 11:10:24 -05:00
|
|
|
LLVMValueRef Scope,
|
2013-06-14 13:38:29 -05:00
|
|
|
const char* Name,
|
|
|
|
const char* LinkageName,
|
2013-07-02 11:10:24 -05:00
|
|
|
LLVMValueRef File,
|
2013-06-14 13:38:29 -05:00
|
|
|
unsigned LineNo,
|
2013-07-02 11:10:24 -05:00
|
|
|
LLVMValueRef Ty,
|
2013-06-14 13:38:29 -05:00
|
|
|
bool isLocalToUnit,
|
|
|
|
bool isDefinition,
|
|
|
|
unsigned ScopeLine,
|
|
|
|
unsigned Flags,
|
|
|
|
bool isOptimized,
|
|
|
|
LLVMValueRef Fn,
|
|
|
|
LLVMValueRef TParam,
|
|
|
|
LLVMValueRef Decl) {
|
|
|
|
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)));
|
|
|
|
}
|
|
|
|
|
2013-06-11 02:57:25 -05:00
|
|
|
extern "C" LLVMValueRef 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
|
|
|
|
2013-06-11 02:57:25 -05:00
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderCreatePointerType(
|
2013-06-14 13:38:29 -05:00
|
|
|
DIBuilderRef Builder,
|
|
|
|
LLVMValueRef PointeeTy,
|
|
|
|
uint64_t SizeInBits,
|
|
|
|
uint64_t AlignInBits,
|
|
|
|
const char* Name) {
|
|
|
|
return wrap(Builder->createPointerType(
|
|
|
|
unwrapDI<DIType>(PointeeTy), SizeInBits, AlignInBits, Name));
|
|
|
|
}
|
|
|
|
|
2013-06-11 02:57:25 -05:00
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderCreateStructType(
|
2013-06-14 13:38:29 -05:00
|
|
|
DIBuilderRef Builder,
|
|
|
|
LLVMValueRef Scope,
|
|
|
|
const char* Name,
|
|
|
|
LLVMValueRef File,
|
|
|
|
unsigned LineNumber,
|
|
|
|
uint64_t SizeInBits,
|
|
|
|
uint64_t AlignInBits,
|
|
|
|
unsigned Flags,
|
|
|
|
LLVMValueRef DerivedFrom,
|
|
|
|
LLVMValueRef Elements,
|
|
|
|
unsigned RunTimeLang,
|
2013-10-01 05:24:50 -05:00
|
|
|
LLVMValueRef VTableHolder,
|
|
|
|
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,
|
2014-02-26 16:06:27 -06:00
|
|
|
unwrapDI<DIType>(VTableHolder)
|
2014-06-12 11:06:14 -05:00
|
|
|
#if LLVM_VERSION_MINOR >= 4
|
2014-03-31 16:43:19 -05:00
|
|
|
,UniqueId
|
2014-02-26 16:06:27 -06:00
|
|
|
#endif
|
2014-03-31 16:43:19 -05:00
|
|
|
));
|
2013-06-14 13:38:29 -05:00
|
|
|
}
|
|
|
|
|
2013-06-11 02:57:25 -05:00
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderCreateMemberType(
|
2013-06-14 13:38:29 -05:00
|
|
|
DIBuilderRef Builder,
|
|
|
|
LLVMValueRef Scope,
|
|
|
|
const char* Name,
|
|
|
|
LLVMValueRef File,
|
|
|
|
unsigned LineNo,
|
|
|
|
uint64_t SizeInBits,
|
|
|
|
uint64_t AlignInBits,
|
|
|
|
uint64_t OffsetInBits,
|
|
|
|
unsigned Flags,
|
|
|
|
LLVMValueRef Ty) {
|
|
|
|
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
|
|
|
|
2013-06-11 02:57:25 -05:00
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderCreateLexicalBlock(
|
2013-06-14 13:38:29 -05:00
|
|
|
DIBuilderRef Builder,
|
|
|
|
LLVMValueRef Scope,
|
|
|
|
LLVMValueRef File,
|
|
|
|
unsigned Line,
|
2014-03-31 16:43:19 -05:00
|
|
|
unsigned Col,
|
|
|
|
unsigned Discriminator) {
|
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
|
|
|
|
#if LLVM_VERSION_MINOR >= 5
|
|
|
|
, Discriminator
|
|
|
|
#endif
|
|
|
|
));
|
2013-06-14 13:38:29 -05:00
|
|
|
}
|
2013-07-02 11:10:24 -05:00
|
|
|
|
2014-02-20 19:44:29 -06:00
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderCreateStaticVariable(
|
|
|
|
DIBuilderRef Builder,
|
|
|
|
LLVMValueRef Context,
|
|
|
|
const char* Name,
|
|
|
|
const char* LinkageName,
|
|
|
|
LLVMValueRef File,
|
|
|
|
unsigned LineNo,
|
|
|
|
LLVMValueRef Ty,
|
|
|
|
bool isLocalToUnit,
|
|
|
|
LLVMValueRef Val,
|
|
|
|
LLVMValueRef Decl = NULL) {
|
|
|
|
return wrap(Builder->createStaticVariable(unwrapDI<DIDescriptor>(Context),
|
|
|
|
Name,
|
|
|
|
LinkageName,
|
|
|
|
unwrapDI<DIFile>(File),
|
|
|
|
LineNo,
|
|
|
|
unwrapDI<DIType>(Ty),
|
|
|
|
isLocalToUnit,
|
|
|
|
unwrap(Val),
|
|
|
|
unwrapDI<MDNode*>(Decl)));
|
|
|
|
}
|
|
|
|
|
2013-06-11 02:57:25 -05:00
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderCreateLocalVariable(
|
2013-06-14 13:38:29 -05:00
|
|
|
DIBuilderRef Builder,
|
|
|
|
unsigned Tag,
|
|
|
|
LLVMValueRef Scope,
|
|
|
|
const char* Name,
|
|
|
|
LLVMValueRef File,
|
|
|
|
unsigned LineNo,
|
|
|
|
LLVMValueRef Ty,
|
|
|
|
bool AlwaysPreserve,
|
|
|
|
unsigned Flags,
|
|
|
|
unsigned ArgNo) {
|
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));
|
|
|
|
}
|
|
|
|
|
2013-06-14 14:23:42 -05:00
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderCreateArrayType(
|
|
|
|
DIBuilderRef Builder,
|
2013-07-02 11:10:24 -05:00
|
|
|
uint64_t Size,
|
|
|
|
uint64_t AlignInBits,
|
|
|
|
LLVMValueRef Ty,
|
2013-06-14 14:23:42 -05:00
|
|
|
LLVMValueRef Subscripts) {
|
|
|
|
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)));
|
|
|
|
}
|
|
|
|
|
2013-06-11 02:57:25 -05:00
|
|
|
extern "C" LLVMValueRef 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,
|
|
|
|
LLVMValueRef Ty,
|
2013-06-14 13:38:29 -05:00
|
|
|
LLVMValueRef Subscripts) {
|
|
|
|
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)));
|
|
|
|
}
|
|
|
|
|
2013-06-11 02:57:25 -05:00
|
|
|
extern "C" LLVMValueRef 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));
|
|
|
|
}
|
|
|
|
|
2013-06-11 02:57:25 -05:00
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderGetOrCreateArray(
|
2013-06-14 13:38:29 -05:00
|
|
|
DIBuilderRef Builder,
|
2013-07-02 11:10:24 -05:00
|
|
|
LLVMValueRef* Ptr,
|
2013-06-14 13:38:29 -05:00
|
|
|
unsigned Count) {
|
|
|
|
return wrap(Builder->getOrCreateArray(
|
|
|
|
ArrayRef<Value*>(reinterpret_cast<Value**>(Ptr), Count)));
|
|
|
|
}
|
|
|
|
|
2013-06-11 02:57:25 -05:00
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(
|
|
|
|
DIBuilderRef Builder,
|
|
|
|
LLVMValueRef Val,
|
|
|
|
LLVMValueRef VarInfo,
|
|
|
|
LLVMBasicBlockRef InsertAtEnd) {
|
|
|
|
return wrap(Builder->insertDeclare(
|
2013-07-02 11:10:24 -05:00
|
|
|
unwrap(Val),
|
|
|
|
unwrapDI<DIVariable>(VarInfo),
|
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,
|
|
|
|
LLVMValueRef VarInfo,
|
|
|
|
LLVMValueRef InsertBefore) {
|
|
|
|
return wrap(Builder->insertDeclare(
|
2013-07-02 11:10:24 -05:00
|
|
|
unwrap(Val),
|
|
|
|
unwrapDI<DIVariable>(VarInfo),
|
2013-06-14 13:38:29 -05:00
|
|
|
unwrap<Instruction>(InsertBefore)));
|
|
|
|
}
|
2013-07-02 03:33:51 -05:00
|
|
|
|
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderCreateEnumerator(
|
|
|
|
DIBuilderRef Builder,
|
|
|
|
const char* Name,
|
|
|
|
uint64_t Val)
|
|
|
|
{
|
|
|
|
return wrap(Builder->createEnumerator(Name, Val));
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderCreateEnumerationType(
|
|
|
|
DIBuilderRef Builder,
|
|
|
|
LLVMValueRef Scope,
|
|
|
|
const char* Name,
|
|
|
|
LLVMValueRef File,
|
|
|
|
unsigned LineNumber,
|
|
|
|
uint64_t SizeInBits,
|
|
|
|
uint64_t AlignInBits,
|
|
|
|
LLVMValueRef Elements,
|
|
|
|
LLVMValueRef ClassType)
|
|
|
|
{
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderCreateUnionType(
|
|
|
|
DIBuilderRef Builder,
|
|
|
|
LLVMValueRef Scope,
|
|
|
|
const char* Name,
|
|
|
|
LLVMValueRef File,
|
|
|
|
unsigned LineNumber,
|
|
|
|
uint64_t SizeInBits,
|
|
|
|
uint64_t AlignInBits,
|
|
|
|
unsigned Flags,
|
|
|
|
LLVMValueRef 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),
|
2014-02-26 16:06:27 -06:00
|
|
|
RunTimeLang
|
2014-06-12 11:06:14 -05:00
|
|
|
#if LLVM_VERSION_MINOR >= 4
|
2014-03-31 16:43:19 -05:00
|
|
|
,UniqueId
|
2014-02-26 16:06:27 -06:00
|
|
|
#endif
|
2014-03-31 16:43:19 -05:00
|
|
|
));
|
2013-07-28 02:48:16 -05:00
|
|
|
}
|
2013-08-09 15:47:00 -05:00
|
|
|
|
2014-03-31 16:43:19 -05:00
|
|
|
#if LLVM_VERSION_MINOR < 5
|
2013-08-09 15:47:00 -05:00
|
|
|
extern "C" void LLVMSetUnnamedAddr(LLVMValueRef Value, LLVMBool Unnamed) {
|
|
|
|
unwrap<GlobalValue>(Value)->setUnnamedAddr(Unnamed);
|
|
|
|
}
|
2014-03-31 16:43:19 -05:00
|
|
|
#endif
|
2013-08-08 11:33:06 -05:00
|
|
|
|
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderCreateTemplateTypeParameter(
|
|
|
|
DIBuilderRef Builder,
|
|
|
|
LLVMValueRef Scope,
|
|
|
|
const char* Name,
|
|
|
|
LLVMValueRef Ty,
|
2013-09-05 06:29:30 -05:00
|
|
|
LLVMValueRef File,
|
|
|
|
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
|
|
|
|
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderCreateOpDeref(LLVMTypeRef IntTy)
|
|
|
|
{
|
|
|
|
return LLVMConstInt(IntTy, DIBuilder::OpDeref, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderCreateOpPlus(LLVMTypeRef IntTy)
|
|
|
|
{
|
|
|
|
return LLVMConstInt(IntTy, DIBuilder::OpPlus, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderCreateComplexVariable(
|
|
|
|
DIBuilderRef Builder,
|
|
|
|
unsigned Tag,
|
|
|
|
LLVMValueRef Scope,
|
|
|
|
const char *Name,
|
|
|
|
LLVMValueRef File,
|
|
|
|
unsigned LineNo,
|
|
|
|
LLVMValueRef Ty,
|
|
|
|
LLVMValueRef* AddrOps,
|
|
|
|
unsigned AddrOpsCount,
|
|
|
|
unsigned ArgNo)
|
|
|
|
{
|
|
|
|
llvm::ArrayRef<llvm::Value*> addr_ops((llvm::Value**)AddrOps, AddrOpsCount);
|
|
|
|
|
|
|
|
return wrap(Builder->createComplexVariable(
|
|
|
|
Tag,
|
|
|
|
unwrapDI<DIDescriptor>(Scope),
|
|
|
|
Name,
|
|
|
|
unwrapDI<DIFile>(File),
|
|
|
|
LineNo,
|
|
|
|
unwrapDI<DIType>(Ty),
|
|
|
|
addr_ops,
|
|
|
|
ArgNo
|
|
|
|
));
|
|
|
|
}
|
2013-09-05 06:29:30 -05:00
|
|
|
|
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderCreateNameSpace(
|
|
|
|
DIBuilderRef Builder,
|
|
|
|
LLVMValueRef Scope,
|
|
|
|
const char* Name,
|
|
|
|
LLVMValueRef File,
|
|
|
|
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(
|
|
|
|
LLVMValueRef CompositeType,
|
|
|
|
LLVMValueRef TypeArray)
|
|
|
|
{
|
2014-08-15 09:36:05 -05:00
|
|
|
#if LLVM_VERSION_MINOR >= 6
|
2014-08-01 04:23:05 -05:00
|
|
|
unwrapDI<DICompositeType>(CompositeType).setArrays(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
|
|
|
|
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 << ")";
|
|
|
|
}
|
|
|
|
|
2014-02-26 16:06:27 -06: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
|
|
|
extern "C" bool
|
|
|
|
LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
|
|
|
|
Module *Dst = unwrap(dst);
|
|
|
|
MemoryBuffer* buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
|
2014-01-27 14:45:48 -06:00
|
|
|
ErrorOr<Module *> Src = llvm::getLazyBitcodeModule(buf, Dst->getContext());
|
|
|
|
if (!Src) {
|
2014-04-15 09:25:22 -05:00
|
|
|
LLVMRustSetLastError(Src.getError().message().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
|
|
|
delete buf;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-01-27 14:45:48 -06:00
|
|
|
std::string Err;
|
|
|
|
if (Linker::LinkModules(Dst, *Src, Linker::DestroySource, &Err)) {
|
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;
|
|
|
|
}
|
2014-02-26 16:06:27 -06:00
|
|
|
#else
|
|
|
|
extern "C" bool
|
|
|
|
LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
|
|
|
|
Module *Dst = unwrap(dst);
|
|
|
|
MemoryBuffer* buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
|
|
|
|
std::string Err;
|
|
|
|
Module *Src = llvm::getLazyBitcodeModule(buf, Dst->getContext(), &Err);
|
|
|
|
if (!Src) {
|
2014-04-15 09:25:22 -05:00
|
|
|
LLVMRustSetLastError(Err.c_str());
|
2014-02-26 16:06:27 -06:00
|
|
|
delete buf;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Linker::LinkModules(Dst, Src, Linker::DestroySource, &Err)) {
|
2014-04-15 09:25:22 -05:00
|
|
|
LLVMRustSetLastError(Err.c_str());
|
2014-02-26 16:06:27 -06:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#endif
|
2013-12-16 22:58:21 -06:00
|
|
|
|
2014-03-31 16:43:19 -05:00
|
|
|
#if LLVM_VERSION_MINOR >= 5
|
|
|
|
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
|
|
|
|
|
|
|
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-03-31 16:43:19 -05:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#else
|
2013-12-16 22:58:21 -06:00
|
|
|
extern "C" void*
|
|
|
|
LLVMRustOpenArchive(char *path) {
|
|
|
|
OwningPtr<MemoryBuffer> buf;
|
2014-07-18 09:07:15 -05:00
|
|
|
error_code err = MemoryBuffer::getFile(path, buf, -1, false);
|
2013-12-16 22:58:21 -06:00
|
|
|
if (err) {
|
2014-04-15 09:25:22 -05:00
|
|
|
LLVMRustSetLastError(err.message().c_str());
|
2013-12-16 22:58:21 -06:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
Archive *ret = new Archive(buf.take(), err);
|
|
|
|
if (err) {
|
2014-04-15 09:25:22 -05:00
|
|
|
LLVMRustSetLastError(err.message().c_str());
|
2013-12-16 22:58:21 -06:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
2014-03-31 16:43:19 -05:00
|
|
|
#endif
|
2013-12-16 22:58:21 -06:00
|
|
|
|
|
|
|
extern "C" const char*
|
|
|
|
LLVMRustArchiveReadSection(Archive *ar, char *name, size_t *size) {
|
2014-02-26 16:06:27 -06:00
|
|
|
#if LLVM_VERSION_MINOR >= 5
|
|
|
|
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();
|
2014-02-26 16:06:27 -06:00
|
|
|
#else
|
|
|
|
Archive::child_iterator child = ar->begin_children(),
|
|
|
|
end = ar->end_children();
|
|
|
|
for (; child != end; ++child) {
|
2013-12-16 22:58:21 -06:00
|
|
|
StringRef sect_name;
|
|
|
|
error_code err = child->getName(sect_name);
|
|
|
|
if (err) continue;
|
2014-06-17 11:34:50 -05:00
|
|
|
#endif
|
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
|
|
|
|
LLVMRustDestroyArchive(Archive *ar) {
|
|
|
|
delete ar;
|
|
|
|
}
|
2014-01-27 14:45:48 -06:00
|
|
|
|
2014-02-26 16:06:27 -06:00
|
|
|
#if LLVM_VERSION_MINOR >= 5
|
2014-01-27 14:45:48 -06:00
|
|
|
extern "C" void
|
|
|
|
LLVMRustSetDLLExportStorageClass(LLVMValueRef Value) {
|
|
|
|
GlobalValue *V = unwrap<GlobalValue>(Value);
|
|
|
|
V->setDLLStorageClass(GlobalValue::DLLExportStorageClass);
|
|
|
|
}
|
2014-02-26 16:06:27 -06:00
|
|
|
#else
|
|
|
|
extern "C" void
|
|
|
|
LLVMRustSetDLLExportStorageClass(LLVMValueRef Value) {
|
|
|
|
LLVMSetLinkage(Value, LLVMDLLExportLinkage);
|
|
|
|
}
|
|
|
|
#endif
|
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 LLVM_VERSION_MINOR >= 5
|
|
|
|
if (std::error_code ec = (*unwrap(SI))->getName(ret))
|
|
|
|
#else
|
2014-04-03 12:45:36 -05:00
|
|
|
if (error_code ec = (*unwrap(SI))->getName(ret))
|
2014-06-17 11:34:50 -05:00
|
|
|
#endif
|
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());
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|