]> git.lizzy.rs Git - rust.git/commitdiff
jit: Add custom memory manager (still segfaulting)
authorZack Corr <zack@z0w0.me>
Sun, 26 Aug 2012 12:40:21 +0000 (22:40 +1000)
committerBrian Anderson <banderson@mozilla.com>
Fri, 31 Aug 2012 23:20:35 +0000 (16:20 -0700)
mk/libuv/ia32/win/src/libuv/uv.target.mk.bak [deleted file]
src/rustc/back/link.rs
src/rustc/lib/llvm.rs
src/rustllvm/RustWrapper.cpp
src/rustllvm/rustllvm.def.in

diff --git a/mk/libuv/ia32/win/src/libuv/uv.target.mk.bak b/mk/libuv/ia32/win/src/libuv/uv.target.mk.bak
deleted file mode 100644 (file)
index 00b34e4..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-# This file is generated by gyp; do not edit.
-
-TOOLSET := target
-TARGET := uv
-DEFS_Debug := '-DWIN32' \
-       '-D_CRT_SECURE_NO_DEPRECATE' \
-       '-D_CRT_NONSTDC_NO_DEPRECATE' \
-       '-DHAVE_CONFIG_H' \
-       '-D_WIN32_WINNT=0x0600' \
-       '-DEIO_STACKSIZE=262144' \
-       '-D_GNU_SOURCE' \
-       '-DDEBUG' \
-       '-D_DEBUG'
-
-# Flags passed to all source files.
-CFLAGS_Debug := -g \
-       -O0
-
-# Flags passed to only C files.
-CFLAGS_C_Debug := 
-
-# Flags passed to only C++ files.
-CFLAGS_CC_Debug := 
-
-INCS_Debug := -I$(srcdir)\src\libuv\include \
-       -I$(srcdir)\src\libuv\include\uv-private \
-       -I$(srcdir)\src\libuv\src \
-       -I$(srcdir)\src\libuv\src\ares\config_win32
-
-DEFS_Release := '-DWIN32' \
-       '-D_CRT_SECURE_NO_DEPRECATE' \
-       '-D_CRT_NONSTDC_NO_DEPRECATE' \
-       '-DHAVE_CONFIG_H' \
-       '-D_WIN32_WINNT=0x0600' \
-       '-DEIO_STACKSIZE=262144' \
-       '-D_GNU_SOURCE' \
-       '-DNDEBUG'
-
-# Flags passed to all source files.
-CFLAGS_Release := -O3 \
-       -fomit-frame-pointer \
-       -fdata-sections \
-       -ffunction-sections
-
-# Flags passed to only C files.
-CFLAGS_C_Release := 
-
-# Flags passed to only C++ files.
-CFLAGS_CC_Release := 
-
-INCS_Release := -I$(srcdir)\src\libuv\include \
-       -I$(srcdir)\src\libuv\include\uv-private \
-       -I$(srcdir)\src\libuv\src \
-       -I$(srcdir)\src\libuv\src\ares\config_win32
-
-OBJS := $(obj).target\$(TARGET)\src\libuv\src\uv-common.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_cancel.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares__close_sockets.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_data.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_destroy.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_expand_name.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_expand_string.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_fds.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_free_hostent.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_free_string.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_gethostbyaddr.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_gethostbyname.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares__get_hostent.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_getnameinfo.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_getopt.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_getsock.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_init.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_library_init.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_llist.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_mkquery.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_nowarn.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_options.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_parse_aaaa_reply.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_parse_a_reply.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_parse_mx_reply.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_parse_ns_reply.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_parse_ptr_reply.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_parse_srv_reply.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_parse_txt_reply.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_process.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_query.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares__read_line.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_search.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_send.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_strcasecmp.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_strdup.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_strerror.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_timeout.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares__timeval.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_version.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_writev.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\bitncmp.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\inet_net_pton.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\inet_ntop.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\windows_port.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_getenv.o \
-       $(obj).target\$(TARGET)\src\libuv\src\ares\ares_platform.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\async.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\cares.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\core.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\dl.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\error.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\fs.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\fs-event.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\getaddrinfo.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\handle.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\loop-watcher.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\pipe.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\thread.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\process.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\req.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\stream.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\tcp.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\tty.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\threadpool.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\timer.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\udp.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\util.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\winapi.o \
-       $(obj).target\$(TARGET)\src\libuv\src\win\winsock.o
-
-# Add to the list of files we specially track dependencies for.
-all_deps += $(OBJS)
-
-# CFLAGS et al overrides must be target-local.
-# See "Target-specific Variable Values" in the GNU Make manual.
-$(OBJS): TOOLSET := $(TOOLSET)
-$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
-$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
-
-# Suffix rules, putting all outputs into $(obj).
-
-$(obj).$(TOOLSET)\$(TARGET)\%.o: $(srcdir)\%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-# Try building from generated source, too.
-
-$(obj).$(TOOLSET)\$(TARGET)\%.o: $(obj).$(TOOLSET)\%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-$(obj).$(TOOLSET)\$(TARGET)\%.o: $(obj)\%.c FORCE_DO_CMD
-       @$(call do_cmd,cc,1)
-
-# End of this set of suffix rules
-### Rules for final target.
-LDFLAGS_Debug := 
-
-LDFLAGS_Release := 
-
-LIBS := 
-
-$(obj).target\src\libuv\libuv.a: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
-$(obj).target\src\libuv\libuv.a: LIBS := $(LIBS)
-$(obj).target\src\libuv\libuv.a: TOOLSET := $(TOOLSET)
-$(obj).target\src\libuv\libuv.a: $(OBJS) FORCE_DO_CMD
-       $(call do_cmd,alink)
-
-all_deps += $(obj).target\src\libuv\libuv.a
-# Add target alias
-.PHONY: uv
-uv: $(obj).target\src\libuv\libuv.a
-
index 04c38c11d62aa41b295c5e359d35d236876d938c..06d90e982c147319346d89aea376635c08a39553 100644 (file)
@@ -160,14 +160,37 @@ fn run_passes(sess: session, llmod: ModuleRef, output: &Path) {
                 llvm::LLVMAddCFGSimplificationPass(pm.llpm);*/
 
                 // JIT execution takes ownership of the module,
-                // so don't dispose and return.
+                // so don't dispose and return. Due to a weird bug
+                // with dynamic libraries, we need to separate jitting
+                // into two functions and load crates inbetween.
+
+                if !llvm::LLVMRustPrepareJIT(pm.llpm,
+                                             llmod,
+                                             CodeGenOptLevel,
+                                             true) {
+                    llvm_err(sess, ~"Could not JIT");
+                }
+
+                // We need to tell LLVM where to resolve all linked
+                // symbols from. The equivalent of -lstd, -lcore, etc.
+                /*let cstore = sess.cstore;
+                for cstore::get_used_crate_files(cstore).each |cratepath| {
+                    debug!{"linking: %s", cratepath};
+
+                    let _: () = str::as_c_str(
+                        cratepath,
+                        |buf_t| {
+                            if !llvm::LLVMRustLoadLibrary(buf_t) {
+                                llvm_err(sess, ~"Could not link");
+                            }
+                            debug!{"linked: %s", cratepath};
+                        });
+                }*/
 
-                if !llvm::LLVMRustJIT(pm.llpm,
-                                      llmod,
-                                      CodeGenOptLevel,
-                                      true) {
+                if !llvm::LLVMRustExecuteJIT() {
                     llvm_err(sess, ~"Could not JIT");
                 }
+
                 if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); }
                 return;
             }
index 5c8bab166ecb20f86078e51f1ee979a98c5ea6d2..ec9c669501b0ee5ec984ed1193c9352a53660146 100644 (file)
@@ -986,12 +986,18 @@ fn LLVMRustWriteOutputFile(PM: PassManagerRef, M: ModuleRef,
         call. */
     fn LLVMRustGetLastError() -> *c_char;
 
-    /** JIT the module. **/
-    fn LLVMRustJIT(PM: PassManagerRef,
+    /** Load a shared library to resolve symbols against. */
+    fn LLVMRustLoadLibrary(Filename: *c_char) -> bool;
+
+    /** Create the JIT engine. */
+    fn LLVMRustPrepareJIT(PM: PassManagerRef,
                    M: ModuleRef,
                    OptLevel: c_int,
                    EnableSegmentedStacks: bool) -> bool;
 
+    /** Execute the JIT engine. */
+    fn LLVMRustExecuteJIT() -> bool;
+
     /** Parses the bitcode in the given memory buffer. */
     fn LLVMRustParseBitcode(MemBuf: MemoryBufferRef) -> ModuleRef;
 
index 8f8503a74d497578b507861be8e4c8a307505405..290f9f135e9649f8b68a39b3f5850d2b466f880d 100644 (file)
 #include "llvm/Support/Host.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/Memory.h"
 #include "llvm/ExecutionEngine/ExecutionEngine.h"
 #include "llvm/ExecutionEngine/JIT.h"
+#include "llvm/ExecutionEngine/JITMemoryManager.h"
+#include "llvm/ExecutionEngine/MCJIT.h"
 #include "llvm/ExecutionEngine/Interpreter.h"
 #include "llvm/ExecutionEngine/GenericValue.h"
 #include "llvm-c/Core.h"
 #include "llvm-c/Object.h"
 #include <cstdlib>
 
+// 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
+
 using namespace llvm;
 
 static const char *LLVMRustError;
@@ -85,7 +96,208 @@ void LLVMInitializeX86AsmParser();
                              LLVMInitializeX86AsmParser();
 
 extern "C" bool
-LLVMRustJIT(LLVMPassManagerRef PMR,
+LLVMRustLoadLibrary(const char* file) {
+  std::string err;
+
+  if(llvm::sys::DynamicLibrary::LoadLibraryPermanently(file, &err)) {
+    LLVMRustError = err.c_str();
+    return false;
+  }
+
+  return true;
+}
+
+ExecutionEngine* EE;
+
+// 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;
+
+  RustMCJITMemoryManager() { }
+  ~RustMCJITMemoryManager();
+
+  virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
+                                       unsigned SectionID);
+
+  virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
+                                       unsigned SectionID);
+
+  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");
+  }
+};
+
+uint8_t *RustMCJITMemoryManager::allocateDataSection(uintptr_t Size,
+                                                    unsigned Alignment,
+                                                    unsigned SectionID) {
+  if (!Alignment)
+    Alignment = 16;
+  uint8_t *Addr = (uint8_t*)calloc((Size + Alignment - 1)/Alignment, Alignment);
+  AllocatedDataMem.push_back(sys::MemoryBlock(Addr, Size));
+  return Addr;
+}
+
+uint8_t *RustMCJITMemoryManager::allocateCodeSection(uintptr_t Size,
+                                                    unsigned Alignment,
+                                                    unsigned SectionID) {
+  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
+
+  const char *NameStr = Name.c_str();
+  void *Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(NameStr);
+  if (Ptr) return Ptr;
+
+  // 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;
+  }
+
+  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());
+}
+
+// Separated functions because loading libraries before creating
+// an execution engine seems to break stuff.
+
+extern "C" bool
+LLVMRustPrepareJIT(LLVMPassManagerRef PMR,
             LLVMModuleRef M,
             CodeGenOpt::Level OptLevel,
             bool EnableSegmentedStacks) {
@@ -96,15 +308,16 @@ LLVMRustJIT(LLVMPassManagerRef PMR,
 
   std::string Err;
   TargetOptions Options;
-  Options.NoFramePointerElim = true;
-  Options.EnableSegmentedStacks = EnableSegmentedStacks;
+  Options.JITEmitDebugInfo = true;
+  //Options.NoFramePointerElim = true;
+  //Options.EnableSegmentedStacks = EnableSegmentedStacks;
 
-  PassManager *PM = unwrap<PassManager>(PMR);
-
-  PM->run(*unwrap(M));
+  unwrap<PassManager>(PMR)->run(*unwrap(M));
 
-  ExecutionEngine* EE = EngineBuilder(unwrap(M))
+  RustMCJITMemoryManager* MM = new RustMCJITMemoryManager();
+  EE = EngineBuilder(unwrap(M))
     .setTargetOptions(Options)
+    .setJITMemoryManager(MM)
     .setOptLevel(OptLevel)
     .setUseMCJIT(true)
     .create();
@@ -114,6 +327,16 @@ LLVMRustJIT(LLVMPassManagerRef PMR,
     return false;
   }
 
+  MM->invalidateInstructionCache();
+
+  return true;
+}
+
+extern "C" bool
+LLVMRustExecuteJIT() {
+  assert(EE);
+
+  std::string Err;
   Function* func = EE->FindFunctionNamed("main");
 
   if(!func || Err != "") {
@@ -121,9 +344,13 @@ LLVMRustJIT(LLVMPassManagerRef PMR,
     return false;
   }
 
-  std::vector<GenericValue> args;
+  //std::vector<GenericValue> args;
+  typedef int (*entry_t)(int, int);
+  entry_t entry = (entry_t) EE->getPointerToFunction(func);
 
-  EE->runFunction(func, args);
+  assert(entry);
+  entry(0, 0);
+  //EE->runFunction(func, args);
 
   return true;
 }
index 2fd4b3fa6f3594a1b2298bf4f6a0b15c85495189..0cb047ad5d03caa814df8d71e8cc51b4f21fb59b 100644 (file)
@@ -4,7 +4,9 @@ LLVMRustWriteOutputFile
 LLVMRustGetLastError
 LLVMRustConstSmallInt
 LLVMRustConstInt
-LLVMRustJIT
+LLVMRustLoadLibrary
+LLVMRustPrepareJIT
+LLVMRustExecuteJIT
 LLVMRustParseBitcode
 LLVMRustParseAssemblyFile
 LLVMRustPrintPassTimings