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"
|
|
|
|
|
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;
|
2011-04-15 16:35:46 -05:00
|
|
|
|
2013-08-22 22:58:42 -05:00
|
|
|
const char *LLVMRustError;
|
2013-04-05 19:17:49 -05:00
|
|
|
|
2011-03-15 16:57:26 -05:00
|
|
|
extern "C" LLVMMemoryBufferRef
|
|
|
|
LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) {
|
|
|
|
LLVMMemoryBufferRef MemBuf = NULL;
|
2011-05-04 23:27:00 -05:00
|
|
|
LLVMCreateMemoryBufferWithContentsOfFile(Path, &MemBuf,
|
|
|
|
const_cast<char **>(&LLVMRustError));
|
2011-03-15 16:57:26 -05:00
|
|
|
return MemBuf;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" const char *LLVMRustGetLastError(void) {
|
|
|
|
return LLVMRustError;
|
|
|
|
}
|
|
|
|
|
2012-08-26 07:40:21 -05:00
|
|
|
// Custom memory manager for MCJITting. It needs special features
|
|
|
|
// that the generic JIT memory manager doesn't entail. Based on
|
|
|
|
// code from LLI, change where needed for Rust.
|
|
|
|
class RustMCJITMemoryManager : public JITMemoryManager {
|
|
|
|
public:
|
|
|
|
SmallVector<sys::MemoryBlock, 16> AllocatedDataMem;
|
|
|
|
SmallVector<sys::MemoryBlock, 16> AllocatedCodeMem;
|
|
|
|
SmallVector<sys::MemoryBlock, 16> FreeCodeMem;
|
2012-08-29 00:49:35 -05:00
|
|
|
void* __morestack;
|
2012-09-11 01:05:51 -05:00
|
|
|
DenseSet<DynamicLibrary*> crates;
|
2012-08-26 07:40:21 -05:00
|
|
|
|
2012-08-29 00:49:35 -05:00
|
|
|
RustMCJITMemoryManager(void* sym) : __morestack(sym) { }
|
2012-08-26 07:40:21 -05:00
|
|
|
~RustMCJITMemoryManager();
|
|
|
|
|
2012-09-11 01:05:51 -05:00
|
|
|
bool loadCrate(const char*, std::string*);
|
|
|
|
|
2012-08-26 07:40:21 -05:00
|
|
|
virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
|
|
|
|
unsigned SectionID);
|
|
|
|
|
|
|
|
virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
|
2013-04-01 15:55:49 -05:00
|
|
|
unsigned SectionID, bool isReadOnly);
|
2013-05-25 17:23:12 -05:00
|
|
|
bool finalizeMemory(std::string *ErrMsg) { return false; }
|
2013-04-01 15:55:49 -05:00
|
|
|
|
|
|
|
virtual bool applyPermissions(std::string *Str);
|
2012-08-26 07:40:21 -05:00
|
|
|
|
|
|
|
virtual void *getPointerToNamedFunction(const std::string &Name,
|
|
|
|
bool AbortOnFailure = true);
|
|
|
|
|
|
|
|
// Invalidate instruction cache for code sections. Some platforms with
|
|
|
|
// separate data cache and instruction cache require explicit cache flush,
|
|
|
|
// otherwise JIT code manipulations (like resolved relocations) will get to
|
|
|
|
// the data cache but not to the instruction cache.
|
|
|
|
virtual void invalidateInstructionCache();
|
|
|
|
|
|
|
|
// The MCJITMemoryManager doesn't use the following functions, so we don't
|
|
|
|
// need implement them.
|
|
|
|
virtual void setMemoryWritable() {
|
|
|
|
llvm_unreachable("Unimplemented call");
|
|
|
|
}
|
|
|
|
virtual void setMemoryExecutable() {
|
|
|
|
llvm_unreachable("Unimplemented call");
|
|
|
|
}
|
|
|
|
virtual void setPoisonMemory(bool poison) {
|
|
|
|
llvm_unreachable("Unimplemented call");
|
|
|
|
}
|
|
|
|
virtual void AllocateGOT() {
|
|
|
|
llvm_unreachable("Unimplemented call");
|
|
|
|
}
|
|
|
|
virtual uint8_t *getGOTBase() const {
|
|
|
|
llvm_unreachable("Unimplemented call");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
virtual uint8_t *startFunctionBody(const Function *F,
|
|
|
|
uintptr_t &ActualSize){
|
|
|
|
llvm_unreachable("Unimplemented call");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
virtual uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize,
|
|
|
|
unsigned Alignment) {
|
|
|
|
llvm_unreachable("Unimplemented call");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart,
|
|
|
|
uint8_t *FunctionEnd) {
|
|
|
|
llvm_unreachable("Unimplemented call");
|
|
|
|
}
|
|
|
|
virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
|
|
|
|
llvm_unreachable("Unimplemented call");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
|
|
|
|
llvm_unreachable("Unimplemented call");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
virtual void deallocateFunctionBody(void *Body) {
|
|
|
|
llvm_unreachable("Unimplemented call");
|
|
|
|
}
|
|
|
|
virtual uint8_t* startExceptionTable(const Function* F,
|
|
|
|
uintptr_t &ActualSize) {
|
|
|
|
llvm_unreachable("Unimplemented call");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
virtual void endExceptionTable(const Function *F, uint8_t *TableStart,
|
|
|
|
uint8_t *TableEnd, uint8_t* FrameRegister) {
|
|
|
|
llvm_unreachable("Unimplemented call");
|
|
|
|
}
|
|
|
|
virtual void deallocateExceptionTable(void *ET) {
|
|
|
|
llvm_unreachable("Unimplemented call");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-09-11 01:05:51 -05:00
|
|
|
bool RustMCJITMemoryManager::loadCrate(const char* file, std::string* err) {
|
|
|
|
DynamicLibrary crate = DynamicLibrary::getPermanentLibrary(file,
|
|
|
|
err);
|
|
|
|
|
|
|
|
if(crate.isValid()) {
|
|
|
|
crates.insert(&crate);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-08-26 07:40:21 -05:00
|
|
|
uint8_t *RustMCJITMemoryManager::allocateDataSection(uintptr_t Size,
|
2013-04-01 15:55:49 -05:00
|
|
|
unsigned Alignment,
|
|
|
|
unsigned SectionID,
|
|
|
|
bool isReadOnly) {
|
2012-08-26 07:40:21 -05:00
|
|
|
if (!Alignment)
|
|
|
|
Alignment = 16;
|
|
|
|
uint8_t *Addr = (uint8_t*)calloc((Size + Alignment - 1)/Alignment, Alignment);
|
|
|
|
AllocatedDataMem.push_back(sys::MemoryBlock(Addr, Size));
|
|
|
|
return Addr;
|
|
|
|
}
|
|
|
|
|
2013-04-01 15:55:49 -05:00
|
|
|
bool RustMCJITMemoryManager::applyPermissions(std::string *Str) {
|
|
|
|
// Empty.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-08-26 07:40:21 -05:00
|
|
|
uint8_t *RustMCJITMemoryManager::allocateCodeSection(uintptr_t Size,
|
2013-04-01 15:55:49 -05:00
|
|
|
unsigned Alignment,
|
|
|
|
unsigned SectionID) {
|
2012-08-26 07:40:21 -05:00
|
|
|
if (!Alignment)
|
|
|
|
Alignment = 16;
|
|
|
|
unsigned NeedAllocate = Alignment * ((Size + Alignment - 1)/Alignment + 1);
|
|
|
|
uintptr_t Addr = 0;
|
|
|
|
// Look in the list of free code memory regions and use a block there if one
|
|
|
|
// is available.
|
|
|
|
for (int i = 0, e = FreeCodeMem.size(); i != e; ++i) {
|
|
|
|
sys::MemoryBlock &MB = FreeCodeMem[i];
|
|
|
|
if (MB.size() >= NeedAllocate) {
|
|
|
|
Addr = (uintptr_t)MB.base();
|
|
|
|
uintptr_t EndOfBlock = Addr + MB.size();
|
|
|
|
// Align the address.
|
|
|
|
Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1);
|
|
|
|
// Store cutted free memory block.
|
|
|
|
FreeCodeMem[i] = sys::MemoryBlock((void*)(Addr + Size),
|
|
|
|
EndOfBlock - Addr - Size);
|
|
|
|
return (uint8_t*)Addr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// No pre-allocated free block was large enough. Allocate a new memory region.
|
|
|
|
sys::MemoryBlock MB = sys::Memory::AllocateRWX(NeedAllocate, 0, 0);
|
|
|
|
|
|
|
|
AllocatedCodeMem.push_back(MB);
|
|
|
|
Addr = (uintptr_t)MB.base();
|
|
|
|
uintptr_t EndOfBlock = Addr + MB.size();
|
|
|
|
// Align the address.
|
|
|
|
Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1);
|
|
|
|
// The AllocateRWX may allocate much more memory than we need. In this case,
|
|
|
|
// we store the unused memory as a free memory block.
|
|
|
|
unsigned FreeSize = EndOfBlock-Addr-Size;
|
|
|
|
if (FreeSize > 16)
|
|
|
|
FreeCodeMem.push_back(sys::MemoryBlock((void*)(Addr + Size), FreeSize));
|
|
|
|
|
|
|
|
// Return aligned address
|
|
|
|
return (uint8_t*)Addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RustMCJITMemoryManager::invalidateInstructionCache() {
|
|
|
|
for (int i = 0, e = AllocatedCodeMem.size(); i != e; ++i)
|
|
|
|
sys::Memory::InvalidateInstructionCache(AllocatedCodeMem[i].base(),
|
|
|
|
AllocatedCodeMem[i].size());
|
|
|
|
}
|
|
|
|
|
|
|
|
void *RustMCJITMemoryManager::getPointerToNamedFunction(const std::string &Name,
|
|
|
|
bool AbortOnFailure) {
|
|
|
|
#ifdef __linux__
|
|
|
|
// Force the following functions to be linked in to anything that uses the
|
|
|
|
// JIT. This is a hack designed to work around the all-too-clever Glibc
|
|
|
|
// strategy of making these functions work differently when inlined vs. when
|
|
|
|
// not inlined, and hiding their real definitions in a separate archive file
|
|
|
|
// that the dynamic linker can't see. For more info, search for
|
|
|
|
// 'libc_nonshared.a' on Google, or read http://llvm.org/PR274.
|
|
|
|
if (Name == "stat") return (void*)(intptr_t)&stat;
|
|
|
|
if (Name == "fstat") return (void*)(intptr_t)&fstat;
|
|
|
|
if (Name == "lstat") return (void*)(intptr_t)&lstat;
|
|
|
|
if (Name == "stat64") return (void*)(intptr_t)&stat64;
|
|
|
|
if (Name == "fstat64") return (void*)(intptr_t)&fstat64;
|
|
|
|
if (Name == "lstat64") return (void*)(intptr_t)&lstat64;
|
|
|
|
if (Name == "atexit") return (void*)(intptr_t)&atexit;
|
|
|
|
if (Name == "mknod") return (void*)(intptr_t)&mknod;
|
|
|
|
#endif
|
|
|
|
|
2012-12-27 16:17:32 -06:00
|
|
|
if (Name == "__morestack" || Name == "___morestack") return &__morestack;
|
2012-08-27 18:51:30 -05:00
|
|
|
|
2012-08-26 07:40:21 -05:00
|
|
|
const char *NameStr = Name.c_str();
|
2012-09-11 01:05:51 -05:00
|
|
|
|
2012-09-28 03:05:49 -05:00
|
|
|
// Look through loaded crates and main for symbols.
|
2012-09-11 01:05:51 -05:00
|
|
|
|
2012-08-26 07:40:21 -05:00
|
|
|
void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr);
|
|
|
|
if (Ptr) return Ptr;
|
|
|
|
|
2012-12-22 15:24:19 -06:00
|
|
|
// If it wasn't found and if it starts with an underscore ('_') character,
|
|
|
|
// try again without the underscore.
|
|
|
|
if (NameStr[0] == '_') {
|
|
|
|
Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr+1);
|
|
|
|
if (Ptr) return Ptr;
|
|
|
|
}
|
|
|
|
|
2012-08-26 07:40:21 -05:00
|
|
|
if (AbortOnFailure)
|
|
|
|
report_fatal_error("Program used external function '" + Name +
|
|
|
|
"' which could not be resolved!");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
RustMCJITMemoryManager::~RustMCJITMemoryManager() {
|
|
|
|
for (unsigned i = 0, e = AllocatedCodeMem.size(); i != e; ++i)
|
|
|
|
sys::Memory::ReleaseRWX(AllocatedCodeMem[i]);
|
|
|
|
for (unsigned i = 0, e = AllocatedDataMem.size(); i != e; ++i)
|
|
|
|
free(AllocatedDataMem[i].base());
|
|
|
|
}
|
|
|
|
|
2012-08-29 00:49:35 -05:00
|
|
|
extern "C" void*
|
2012-09-11 01:05:51 -05:00
|
|
|
LLVMRustPrepareJIT(void* __morestack) {
|
|
|
|
// An execution engine will take ownership of this later
|
|
|
|
// and clean it up for us.
|
|
|
|
|
|
|
|
return (void*) new RustMCJITMemoryManager(__morestack);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" bool
|
|
|
|
LLVMRustLoadCrate(void* mem, const char* crate) {
|
|
|
|
RustMCJITMemoryManager* manager = (RustMCJITMemoryManager*) mem;
|
|
|
|
std::string Err;
|
|
|
|
|
|
|
|
assert(manager);
|
|
|
|
|
|
|
|
if(!manager->loadCrate(crate, &Err)) {
|
|
|
|
LLVMRustError = Err.c_str();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-06-13 23:25:18 -05:00
|
|
|
extern "C" LLVMExecutionEngineRef
|
|
|
|
LLVMRustBuildJIT(void* mem,
|
|
|
|
LLVMModuleRef M,
|
|
|
|
bool EnableSegmentedStacks) {
|
2012-08-24 23:54:30 -05:00
|
|
|
|
|
|
|
InitializeNativeTarget();
|
|
|
|
InitializeNativeTargetAsmPrinter();
|
2012-09-27 01:07:33 -05:00
|
|
|
InitializeNativeTargetAsmParser();
|
2012-08-24 23:54:30 -05:00
|
|
|
|
|
|
|
std::string Err;
|
|
|
|
TargetOptions Options;
|
2012-08-26 07:40:21 -05:00
|
|
|
Options.JITEmitDebugInfo = true;
|
2013-08-28 19:41:40 -05:00
|
|
|
Options.NoFramePointerElim = true;
|
2012-08-27 18:51:30 -05:00
|
|
|
Options.EnableSegmentedStacks = EnableSegmentedStacks;
|
2012-09-11 01:05:51 -05:00
|
|
|
RustMCJITMemoryManager* MM = (RustMCJITMemoryManager*) mem;
|
|
|
|
assert(MM);
|
2012-08-24 23:54:30 -05:00
|
|
|
|
2012-08-29 00:49:35 -05:00
|
|
|
ExecutionEngine* EE = EngineBuilder(unwrap(M))
|
2012-09-28 03:05:49 -05:00
|
|
|
.setErrorStr(&Err)
|
2012-08-24 23:54:30 -05:00
|
|
|
.setTargetOptions(Options)
|
2012-08-26 07:40:21 -05:00
|
|
|
.setJITMemoryManager(MM)
|
2012-08-24 23:54:30 -05:00
|
|
|
.setUseMCJIT(true)
|
2012-08-29 00:49:35 -05:00
|
|
|
.setAllocateGVsWithCode(false)
|
2012-08-24 23:54:30 -05:00
|
|
|
.create();
|
|
|
|
|
|
|
|
if(!EE || Err != "") {
|
|
|
|
LLVMRustError = Err.c_str();
|
2013-06-13 23:25:18 -05:00
|
|
|
// The EngineBuilder only takes ownership of these two structures if the
|
|
|
|
// create() call is successful, but here it wasn't successful.
|
|
|
|
LLVMDisposeModule(M);
|
|
|
|
delete MM;
|
|
|
|
return NULL;
|
2012-08-24 23:54:30 -05:00
|
|
|
}
|
|
|
|
|
2012-08-26 07:40:21 -05:00
|
|
|
MM->invalidateInstructionCache();
|
2013-06-13 23:25:18 -05:00
|
|
|
return wrap(EE);
|
2012-08-24 23:54:30 -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
|
|
|
|
2013-08-05 23:21:37 -05:00
|
|
|
extern "C" void LLVMAddFunctionAttrString(LLVMValueRef fn, const char *Name) {
|
|
|
|
unwrap<Function>(fn)->addFnAttr(Name);
|
|
|
|
}
|
|
|
|
|
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,
|
|
|
|
AtomicOrdering order) {
|
|
|
|
return wrap(unwrap(B)->CreateAtomicCmpXchg(unwrap(target), unwrap(old),
|
|
|
|
unwrap(source), order));
|
|
|
|
}
|
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
|
|
|
|
|
|
|
/**
|
|
|
|
* This function is intended to be a threadsafe interface into enabling a
|
|
|
|
* multithreaded LLVM. This is invoked at the start of the translation phase of
|
|
|
|
* compilation to ensure that LLVM is ready.
|
|
|
|
*
|
|
|
|
* All of trans properly isolates LLVM with the use of a different
|
|
|
|
* LLVMContextRef per task, thus allowing parallel compilation of different
|
|
|
|
* crates in the same process. At the time of this writing, the use case for
|
|
|
|
* this is unit tests for rusti, but there are possible other applications.
|
|
|
|
*/
|
|
|
|
extern "C" bool LLVMRustStartMultithreading() {
|
|
|
|
static Mutex lock;
|
|
|
|
bool ret = true;
|
|
|
|
assert(lock.acquire());
|
|
|
|
if (!LLVMIsMultithreaded()) {
|
|
|
|
ret = LLVMStartMultithreaded();
|
|
|
|
}
|
|
|
|
assert(lock.release());
|
|
|
|
return ret;
|
|
|
|
}
|
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
|
|
|
|
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),
|
2013-06-14 13:38:29 -05:00
|
|
|
unwrapDI<DIArray>(ParameterTypes)));
|
|
|
|
}
|
|
|
|
|
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,
|
|
|
|
LLVMValueRef VTableHolder) {
|
|
|
|
return wrap(Builder->createStructType(
|
2013-07-02 11:10:24 -05:00
|
|
|
unwrapDI<DIDescriptor>(Scope), Name,
|
|
|
|
unwrapDI<DIFile>(File), LineNumber,
|
|
|
|
SizeInBits, AlignInBits, Flags,
|
|
|
|
unwrapDI<DIType>(DerivedFrom),
|
|
|
|
unwrapDI<DIArray>(Elements), RunTimeLang,
|
2013-06-14 13:38:29 -05:00
|
|
|
unwrapDI<MDNode*>(VTableHolder)));
|
|
|
|
}
|
|
|
|
|
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,
|
|
|
|
unsigned Col) {
|
|
|
|
return wrap(Builder->createLexicalBlock(
|
2013-07-02 11:10:24 -05:00
|
|
|
unwrapDI<DIDescriptor>(Scope),
|
2013-06-14 13:38:29 -05:00
|
|
|
unwrapDI<DIFile>(File), Line, Col));
|
|
|
|
}
|
2013-07-02 11:10:24 -05:00
|
|
|
|
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,
|
|
|
|
unsigned RunTimeLang)
|
|
|
|
{
|
|
|
|
return wrap(Builder->createUnionType(
|
|
|
|
unwrapDI<DIDescriptor>(Scope),
|
|
|
|
Name,
|
|
|
|
unwrapDI<DIFile>(File),
|
|
|
|
LineNumber,
|
|
|
|
SizeInBits,
|
|
|
|
AlignInBits,
|
|
|
|
Flags,
|
|
|
|
unwrapDI<DIArray>(Elements),
|
|
|
|
RunTimeLang));
|
2013-07-28 02:48:16 -05:00
|
|
|
}
|
2013-08-09 15:47:00 -05:00
|
|
|
|
|
|
|
extern "C" void LLVMSetUnnamedAddr(LLVMValueRef Value, LLVMBool Unnamed) {
|
|
|
|
unwrap<GlobalValue>(Value)->setUnnamedAddr(Unnamed);
|
|
|
|
}
|
2013-08-08 11:33:06 -05:00
|
|
|
|
|
|
|
extern "C" LLVMValueRef LLVMDIBuilderCreateTemplateTypeParameter(
|
|
|
|
DIBuilderRef Builder,
|
|
|
|
LLVMValueRef Scope,
|
|
|
|
const char* Name,
|
|
|
|
LLVMValueRef Ty,
|
|
|
|
LLVMValueRef File = 0,
|
|
|
|
unsigned LineNo = 0,
|
|
|
|
unsigned ColumnNo = 0)
|
|
|
|
{
|
|
|
|
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
|
|
|
|
));
|
|
|
|
}
|