Skip to content

Commit

Permalink
Changes to LLVM ExecutionEngine wrapper
Browse files Browse the repository at this point in the history
* Removes `RustJITMemoryManager` from public API.
  This was really sort of an implementation detail to begin with.
* `__morestack` is linked to C++ wrapper code and this pointer
  is used when resolving the symbol for `ExecutionEngine` code.
* `__morestack_addr` is also resolved for `ExecutionEngine` code.
  This function is sometimes referenced in LLVM-generated code,
  but was not able to be resolved on Mac OS systems.
* Added Windows support to `ExecutionEngine` API.
* Added a test for basic `ExecutionEngine` functionality.
  • Loading branch information
murarth committed Jun 8, 2015
1 parent aca207a commit 021e483
Show file tree
Hide file tree
Showing 5 changed files with 293 additions and 30 deletions.
8 changes: 1 addition & 7 deletions src/librustc_llvm/lib.rs
Expand Up @@ -468,9 +468,6 @@ pub type BuilderRef = *mut Builder_opaque;
pub enum ExecutionEngine_opaque {}
pub type ExecutionEngineRef = *mut ExecutionEngine_opaque;
#[allow(missing_copy_implementations)]
pub enum RustJITMemoryManager_opaque {}
pub type RustJITMemoryManagerRef = *mut RustJITMemoryManager_opaque;
#[allow(missing_copy_implementations)]
pub enum MemoryBuffer_opaque {}
pub type MemoryBufferRef = *mut MemoryBuffer_opaque;
#[allow(missing_copy_implementations)]
Expand Down Expand Up @@ -1080,10 +1077,7 @@ extern {
pub fn LLVMDisposeBuilder(Builder: BuilderRef);

/* Execution engine */
pub fn LLVMRustCreateJITMemoryManager(morestack: *const ())
-> RustJITMemoryManagerRef;
pub fn LLVMBuildExecutionEngine(Mod: ModuleRef,
MM: RustJITMemoryManagerRef) -> ExecutionEngineRef;
pub fn LLVMBuildExecutionEngine(Mod: ModuleRef) -> ExecutionEngineRef;
pub fn LLVMDisposeExecutionEngine(EE: ExecutionEngineRef);
pub fn LLVMExecutionEngineFinalizeObject(EE: ExecutionEngineRef);
pub fn LLVMRustLoadDynamicLibrary(path: *const c_char) -> Bool;
Expand Down
50 changes: 35 additions & 15 deletions src/rustllvm/ExecutionEngineWrapper.cpp
Expand Up @@ -16,34 +16,38 @@ using namespace llvm;
using namespace llvm::sys;
using namespace llvm::object;

// libmorestack is not used on Windows
#ifndef _WIN32
extern "C" void __morestack(void);

static void* morestack_addr() {
return reinterpret_cast<void*>(__morestack);
}
#endif

class RustJITMemoryManager : public SectionMemoryManager
{
typedef SectionMemoryManager Base;

const void *morestack;

public:

RustJITMemoryManager(const void *morestack_ptr)
: morestack(morestack_ptr)
{}
RustJITMemoryManager() {}

uint64_t getSymbolAddress(const std::string &Name) override
{
#ifndef _WIN32
if (Name == "__morestack" || Name == "___morestack")
return reinterpret_cast<uint64_t>(morestack);
return reinterpret_cast<uint64_t>(__morestack);
if (Name == "__morestack_addr" || Name == "___morestack_addr")
return reinterpret_cast<uint64_t>(morestack_addr);
#endif

return Base::getSymbolAddress(Name);
}
};

DEFINE_SIMPLE_CONVERSION_FUNCTIONS(RustJITMemoryManager, LLVMRustJITMemoryManagerRef)

extern "C" LLVMRustJITMemoryManagerRef LLVMRustCreateJITMemoryManager(void *morestack)
{
return wrap(new RustJITMemoryManager(morestack));
}

extern "C" LLVMBool LLVMRustLoadDynamicLibrary(const char *path)
{
std::string err;
Expand All @@ -60,6 +64,13 @@ extern "C" LLVMBool LLVMRustLoadDynamicLibrary(const char *path)
extern "C" void LLVMExecutionEngineAddModule(
LLVMExecutionEngineRef eeref, LLVMModuleRef mref)
{
#ifdef _WIN32
// On Windows, MCJIT must generate ELF objects
std::string target = getProcessTriple();
target += "-elf";
target = Triple::normalize(target);
unwrap(mref)->setTargetTriple(target);
#endif
LLVMAddModule(eeref, mref);
}

Expand All @@ -74,27 +85,36 @@ extern "C" LLVMBool LLVMExecutionEngineRemoveModule(
return ee->removeModule(m);
}

extern "C" LLVMExecutionEngineRef LLVMBuildExecutionEngine(
LLVMModuleRef mod, LLVMRustJITMemoryManagerRef mref)
extern "C" LLVMExecutionEngineRef LLVMBuildExecutionEngine(LLVMModuleRef mod)
{
// These are necessary for code generation to work properly.
InitializeNativeTarget();
InitializeNativeTargetAsmPrinter();
InitializeNativeTargetAsmParser();

#ifdef _WIN32
// On Windows, MCJIT must generate ELF objects
std::string target = getProcessTriple();
target += "-elf";
target = Triple::normalize(target);
unwrap(mod)->setTargetTriple(target);
#endif

std::string error_str;
TargetOptions options;

options.JITEmitDebugInfo = true;
options.NoFramePointerElim = true;

RustJITMemoryManager *mm = new RustJITMemoryManager;

ExecutionEngine *ee =
#if LLVM_VERSION_MINOR >= 6
EngineBuilder(std::unique_ptr<Module>(unwrap(mod)))
.setMCJITMemoryManager(std::unique_ptr<RustJITMemoryManager>(unwrap(mref)))
.setMCJITMemoryManager(std::unique_ptr<RustJITMemoryManager>(mm))
#else
EngineBuilder(unwrap(mod))
.setMCJITMemoryManager(unwrap(mref))
.setMCJITMemoryManager(mm)
#endif
.setEngineKind(EngineKind::JIT)
.setErrorStr(&error_str)
Expand Down
8 changes: 0 additions & 8 deletions src/rustllvm/rustllvm.h
Expand Up @@ -51,14 +51,6 @@
#include "llvm/IR/DIBuilder.h"
#include "llvm/Linker/Linker.h"

// Used by RustMCJITMemoryManager::getPointerToNamedFunction()
// to get around glibc issues. See the function for more information.
#ifdef __linux__
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#endif

void LLVMRustSetLastError(const char*);

typedef struct OpaqueRustString *RustStringRef;
Expand Down
8 changes: 8 additions & 0 deletions src/test/run-make/execution-engine/Makefile
@@ -0,0 +1,8 @@
-include ../tools.mk

# This is a basic test of LLVM ExecutionEngine functionality using compiled
# Rust code built using the `rustc` crate.

all:
$(RUSTC) test.rs
$(call RUN,test $(RUSTC))

0 comments on commit 021e483

Please sign in to comment.