about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorZack Corr <zack@z0w0.me>2012-09-11 16:05:51 +1000
committerZack Corr <zack@z0w0.me>2012-09-27 12:57:58 +1000
commit887b59b7bea4d795ebe30655ac051f7872aa6a44 (patch)
tree9106ca5de37a2ae972ae65dbf41b226f593e1b13 /src/rustc
parent996ec62cbfce9f25ecc8b573a0b9eb7f4a1b6db9 (diff)
jit: Separate JIT execution into two functions and load crates before main lookup
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/back/link.rs38
-rw-r--r--src/rustc/lib/llvm.rs22
2 files changed, 47 insertions, 13 deletions
diff --git a/src/rustc/back/link.rs b/src/rustc/back/link.rs
index 4bbd51524c4..751f0369141 100644
--- a/src/rustc/back/link.rs
+++ b/src/rustc/back/link.rs
@@ -74,14 +74,44 @@ mod jit {
             m: ModuleRef,
             opt: c_int,
             stacks: bool) unsafe {
-        let ptr = llvm::LLVMRustJIT(rusti::morestack_addr(),
-                                    pm, m, opt, stacks);
+        let manager = llvm::LLVMRustPrepareJIT(rusti::morestack_addr());
+
+        // We need to tell JIT where to resolve all linked
+        // symbols from. The equivalent of -lstd, -lcore, etc.
+        // By default the JIT will resolve symbols from the std and
+        // core linked into rustc. We don't want that,
+        // incase the user wants to use an older std library.
+
+        let cstore = sess.cstore;
+        for cstore::get_used_crate_files(cstore).each |cratepath| {
+            let path = cratepath.to_str();
+
+            debug!("linking: %s", path);
+
+            let _: () = str::as_c_str(
+                path,
+                |buf_t| {
+                    if !llvm::LLVMRustLoadCrate(manager, buf_t) {
+                        llvm_err(sess, ~"Could not link");
+                    }
+                    debug!("linked: %s", path);
+                });
+        }
+
+        // The execute function will return a void pointer
+        // to the _rust_main function. We can do closure
+        // magic here to turn it straight into a callable rust
+        // closure. It will also cleanup the memory manager
+        // for us.
+
+        let entry = llvm::LLVMRustExecuteJIT(manager,
+                                      pm, m, opt, stacks);
 
-        if ptr::is_null(ptr) {
+        if ptr::is_null(entry) {
             llvm_err(sess, ~"Could not JIT");
         } else {
             let closure = Closure {
-                code: ptr,
+                code: entry,
                 env: ptr::null()
             };
             let func: fn(~[~str]) = cast::transmute(move closure);
diff --git a/src/rustc/lib/llvm.rs b/src/rustc/lib/llvm.rs
index 031ce219308..c16fe31f933 100644
--- a/src/rustc/lib/llvm.rs
+++ b/src/rustc/lib/llvm.rs
@@ -990,15 +990,19 @@ extern mod llvm {
         call. */
     fn LLVMRustGetLastError() -> *c_char;
 
-    /** Load a shared library to resolve symbols against. */
-    fn LLVMRustLoadLibrary(Filename: *c_char) -> bool;
-
-    /** Create and execute the JIT engine. */
-    fn LLVMRustJIT(__morestack: *(),
-                   PM: PassManagerRef,
-                   M: ModuleRef,
-                   OptLevel: c_int,
-                   EnableSegmentedStacks: bool) -> *();
+    /** Prepare the JIT. Returns a memory manager that can load crates. */
+    fn LLVMRustPrepareJIT(__morestack: *()) -> *();
+
+    /** Load a crate into the memory manager. */
+    fn LLVMRustLoadCrate(MM: *(),
+                         Filename: *c_char) -> bool;
+
+    /** Execute the JIT engine. */
+    fn LLVMRustExecuteJIT(MM: *(),
+                          PM: PassManagerRef,
+                          M: ModuleRef,
+                          OptLevel: c_int,
+                          EnableSegmentedStacks: bool) -> *();
 
     /** Parses the bitcode in the given memory buffer. */
     fn LLVMRustParseBitcode(MemBuf: MemoryBufferRef) -> ModuleRef;