about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustc/lib/llvm.rs71
-rw-r--r--src/librustc/middle/trans/base.rs42
-rw-r--r--src/librustc/middle/trans/build.rs3
-rw-r--r--src/librustc/middle/trans/cabi_mips.rs3
-rw-r--r--src/librustc/middle/trans/closure.rs4
-rw-r--r--src/librustc/middle/trans/common.rs73
-rw-r--r--src/librustc/middle/trans/debuginfo.rs9
-rw-r--r--src/librustc/middle/trans/type_of.rs2
-rw-r--r--src/rustllvm/RustWrapper.cpp29
-rw-r--r--src/rustllvm/rustllvm.def.in3
10 files changed, 126 insertions, 113 deletions
diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs
index f6beb078e46..0e9ea982d9f 100644
--- a/src/librustc/lib/llvm.rs
+++ b/src/librustc/lib/llvm.rs
@@ -239,16 +239,12 @@ pub mod llvm {
         #[fast_ffi]
         pub unsafe fn LLVMContextCreate() -> ContextRef;
         #[fast_ffi]
-        pub unsafe fn LLVMGetGlobalContext() -> ContextRef;
-        #[fast_ffi]
         pub unsafe fn LLVMContextDispose(C: ContextRef);
         #[fast_ffi]
         pub unsafe fn LLVMGetMDKindIDInContext(C: ContextRef,
                                            Name: *c_char,
                                            SLen: c_uint)
                                         -> c_uint;
-        #[fast_ffi]
-        pub unsafe fn LLVMGetMDKindID(Name: *c_char, SLen: c_uint) -> c_uint;
 
         /* Create and destroy modules. */
         #[fast_ffi]
@@ -256,6 +252,8 @@ pub mod llvm {
                                                     C: ContextRef)
                                                  -> ModuleRef;
         #[fast_ffi]
+        pub unsafe fn LLVMGetModuleContext(M: ModuleRef) -> ContextRef;
+        #[fast_ffi]
         pub unsafe fn LLVMDisposeModule(M: ModuleRef);
 
         /** Data layout. See Module::getDataLayout. */
@@ -301,18 +299,6 @@ pub mod llvm {
                                            NumBits: c_uint) -> TypeRef;
 
         #[fast_ffi]
-        pub unsafe fn LLVMInt1Type() -> TypeRef;
-        #[fast_ffi]
-        pub unsafe fn LLVMInt8Type() -> TypeRef;
-        #[fast_ffi]
-        pub unsafe fn LLVMInt16Type() -> TypeRef;
-        #[fast_ffi]
-        pub unsafe fn LLVMInt32Type() -> TypeRef;
-        #[fast_ffi]
-        pub unsafe fn LLVMInt64Type() -> TypeRef;
-        #[fast_ffi]
-        pub unsafe fn LLVMIntType(NumBits: c_uint) -> TypeRef;
-        #[fast_ffi]
         pub unsafe fn LLVMGetIntTypeWidth(IntegerTy: TypeRef) -> c_uint;
 
         /* Operations on real types */
@@ -327,17 +313,6 @@ pub mod llvm {
         #[fast_ffi]
         pub unsafe fn LLVMPPCFP128TypeInContext(C: ContextRef) -> TypeRef;
 
-        #[fast_ffi]
-        pub unsafe fn LLVMFloatType() -> TypeRef;
-        #[fast_ffi]
-        pub unsafe fn LLVMDoubleType() -> TypeRef;
-        #[fast_ffi]
-        pub unsafe fn LLVMX86FP80Type() -> TypeRef;
-        #[fast_ffi]
-        pub unsafe fn LLVMFP128Type() -> TypeRef;
-        #[fast_ffi]
-        pub unsafe fn LLVMPPCFP128Type() -> TypeRef;
-
         /* Operations on function types */
         #[fast_ffi]
         pub unsafe fn LLVMFunctionType(ReturnType: TypeRef,
@@ -361,11 +336,6 @@ pub mod llvm {
                                               ElementCount: c_uint,
                                               Packed: Bool) -> TypeRef;
         #[fast_ffi]
-        pub unsafe fn LLVMStructType(ElementTypes: *TypeRef,
-                                     ElementCount: c_uint,
-                                     Packed: Bool)
-                                  -> TypeRef;
-        #[fast_ffi]
         pub unsafe fn LLVMCountStructElementTypes(StructTy: TypeRef)
                                                -> c_uint;
         #[fast_ffi]
@@ -403,13 +373,6 @@ pub mod llvm {
         #[fast_ffi]
         pub unsafe fn LLVMMetadataTypeInContext(C: ContextRef) -> TypeRef;
 
-        #[fast_ffi]
-        pub unsafe fn LLVMVoidType() -> TypeRef;
-        #[fast_ffi]
-        pub unsafe fn LLVMLabelType() -> TypeRef;
-        #[fast_ffi]
-        pub unsafe fn LLVMMetadataType() -> TypeRef;
-
         /* Operations on all values */
         #[fast_ffi]
         pub unsafe fn LLVMTypeOf(Val: ValueRef) -> TypeRef;
@@ -482,15 +445,11 @@ pub mod llvm {
                                         SLen: c_uint)
                                      -> ValueRef;
         #[fast_ffi]
-        pub unsafe fn LLVMMDString(Str: *c_char, SLen: c_uint) -> ValueRef;
-        #[fast_ffi]
         pub unsafe fn LLVMMDNodeInContext(C: ContextRef,
                                       Vals: *ValueRef,
                                       Count: c_uint)
                                    -> ValueRef;
         #[fast_ffi]
-        pub unsafe fn LLVMMDNode(Vals: *ValueRef, Count: c_uint) -> ValueRef;
-        #[fast_ffi]
         pub unsafe fn LLVMAddNamedMetadataOperand(M: ModuleRef, Str: *c_char,
                                        Val: ValueRef);
 
@@ -544,20 +503,11 @@ pub mod llvm {
                                                Packed: Bool) -> ValueRef;
 
         #[fast_ffi]
-        pub unsafe fn LLVMConstString(Str: *c_char,
-                                      Length: c_uint,
-                                      DontNullTerminate: Bool)
-                                   -> ValueRef;
-        #[fast_ffi]
         pub unsafe fn LLVMConstArray(ElementTy: TypeRef,
                                      ConstantVals: *ValueRef,
                                      Length: c_uint)
                                   -> ValueRef;
         #[fast_ffi]
-        pub unsafe fn LLVMConstStruct(ConstantVals: *ValueRef,
-                                      Count: c_uint,
-                                      Packed: Bool) -> ValueRef;
-        #[fast_ffi]
         pub unsafe fn LLVMConstVector(ScalarConstantVals: *ValueRef,
                                       Size: c_uint) -> ValueRef;
 
@@ -970,15 +920,6 @@ pub mod llvm {
                                                     BB: BasicBlockRef,
                                                     Name: *c_char)
                                                  -> BasicBlockRef;
-
-        #[fast_ffi]
-        pub unsafe fn LLVMAppendBasicBlock(Fn: ValueRef,
-                                       Name: *c_char)
-                                    -> BasicBlockRef;
-        #[fast_ffi]
-        pub unsafe fn LLVMInsertBasicBlock(InsertBeforeBB: BasicBlockRef,
-                                       Name: *c_char)
-                                    -> BasicBlockRef;
         #[fast_ffi]
         pub unsafe fn LLVMDeleteBasicBlock(BB: BasicBlockRef);
 
@@ -1039,8 +980,6 @@ pub mod llvm {
         #[fast_ffi]
         pub unsafe fn LLVMCreateBuilderInContext(C: ContextRef) -> BuilderRef;
         #[fast_ffi]
-        pub unsafe fn LLVMCreateBuilder() -> BuilderRef;
-        #[fast_ffi]
         pub unsafe fn LLVMPositionBuilder(Builder: BuilderRef,
                                           Block: BasicBlockRef,
                                           Instr: ValueRef);
@@ -1893,7 +1832,8 @@ pub mod llvm {
 
         /** Parses LLVM asm in the given file */
         #[fast_ffi]
-        pub unsafe fn LLVMRustParseAssemblyFile(Filename: *c_char)
+        pub unsafe fn LLVMRustParseAssemblyFile(Filename: *c_char,
+                                                C: ContextRef)
                                              -> ModuleRef;
 
         #[fast_ffi]
@@ -1910,6 +1850,9 @@ pub mod llvm {
         pub unsafe fn LLVMRustPrintPassTimings();
 
         #[fast_ffi]
+        pub unsafe fn LLVMRustStartMultithreading() -> bool;
+
+        #[fast_ffi]
         pub unsafe fn LLVMStructCreateNamed(C: ContextRef, Name: *c_char)
                                          -> TypeRef;
 
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 8e015d9a677..393155ddd7f 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -29,7 +29,7 @@ use back::link::{mangle_exported_name};
 use back::{link, abi, upcall};
 use driver::session;
 use driver::session::Session;
-use lib::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef};
+use lib::llvm::{ContextRef, ModuleRef, ValueRef, TypeRef, BasicBlockRef};
 use lib::llvm::{True, False};
 use lib::llvm::{llvm, mk_target_data, mk_type_names};
 use lib;
@@ -73,6 +73,7 @@ use core::libc::c_uint;
 use core::str;
 use core::uint;
 use core::vec;
+use core::local_data;
 use extra::time;
 use syntax::ast::ident;
 use syntax::ast_map::{path, path_elt_to_str, path_name};
@@ -1186,7 +1187,7 @@ pub fn new_block(cx: fn_ctxt, parent: Option<block>, kind: block_kind,
     };
     unsafe {
         let llbb = str::as_c_str(*cx.ccx.sess.str_of(s), |buf| {
-            llvm::LLVMAppendBasicBlock(cx.llfn, buf)
+            llvm::LLVMAppendBasicBlockInContext(cx.ccx.llcx, cx.llfn, buf)
         });
         let bcx = mk_block(llbb,
                            parent,
@@ -1560,11 +1561,12 @@ pub struct BasicBlocks {
 // Creates the standard set of basic blocks for a function
 pub fn mk_standard_basic_blocks(llfn: ValueRef) -> BasicBlocks {
     unsafe {
+        let cx = task_llcx();
         BasicBlocks {
             sa: str::as_c_str("static_allocas",
-                           |buf| llvm::LLVMAppendBasicBlock(llfn, buf)),
+                           |buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf)),
             rt: str::as_c_str("return",
-                           |buf| llvm::LLVMAppendBasicBlock(llfn, buf))
+                           |buf| llvm::LLVMAppendBasicBlockInContext(cx, llfn, buf))
         }
     }
 }
@@ -2347,7 +2349,7 @@ pub fn create_entry_wrapper(ccx: @CrateContext,
         };
         let llbb = str::as_c_str("top", |buf| {
             unsafe {
-                llvm::LLVMAppendBasicBlock(llfn, buf)
+                llvm::LLVMAppendBasicBlockInContext(ccx.llcx, llfn, buf)
             }
         });
         let bld = ccx.builder.B;
@@ -2665,10 +2667,10 @@ pub fn declare_intrinsics(llmod: ModuleRef) -> HashMap<~str, ValueRef> {
                            T_void()));
     let memcpy32 =
         decl_cdecl_fn(llmod, "llvm.memcpy.p0i8.p0i8.i32",
-                      T_fn(copy T_memcpy32_args, T_void()));
+                      T_fn(T_memcpy32_args, T_void()));
     let memcpy64 =
         decl_cdecl_fn(llmod, "llvm.memcpy.p0i8.p0i8.i64",
-                      T_fn(copy T_memcpy64_args, T_void()));
+                      T_fn(T_memcpy64_args, T_void()));
     let memmove32 =
         decl_cdecl_fn(llmod, "llvm.memmove.p0i8.p0i8.i32",
                       T_fn(T_memcpy32_args, T_void()));
@@ -3043,9 +3045,13 @@ pub fn trans_crate(sess: session::Session,
     let llmod_id = link_meta.name.to_owned() + ".rc";
 
     unsafe {
+        if !llvm::LLVMRustStartMultithreading() {
+            sess.bug("couldn't enable multi-threaded LLVM");
+        }
+        let llcx = llvm::LLVMContextCreate();
+        set_task_llcx(llcx);
         let llmod = str::as_c_str(llmod_id, |buf| {
-            llvm::LLVMModuleCreateWithNameInContext
-                (buf, llvm::LLVMGetGlobalContext())
+            llvm::LLVMModuleCreateWithNameInContext(buf, llcx)
         });
         let data_layout: &str = sess.targ_cfg.target_strs.data_layout;
         let targ_triple: &str = sess.targ_cfg.target_strs.target_triple;
@@ -3079,6 +3085,7 @@ pub fn trans_crate(sess: session::Session,
         let ccx = @CrateContext {
               sess: sess,
               llmod: llmod,
+              llcx: llcx,
               td: td,
               tn: tn,
               externs: @mut HashMap::new(),
@@ -3133,7 +3140,9 @@ pub fn trans_crate(sess: session::Session,
               float_type: float_type,
               task_type: task_type,
               opaque_vec_type: T_opaque_vec(targ_cfg),
-              builder: BuilderRef_res(unsafe { llvm::LLVMCreateBuilder() }),
+              builder: BuilderRef_res(unsafe {
+                  llvm::LLVMCreateBuilderInContext(llcx)
+              }),
               shape_cx: mk_ctxt(llmod),
               crate_map: crate_map,
               uses_gc: @mut false,
@@ -3181,3 +3190,16 @@ pub fn trans_crate(sess: session::Session,
         return (llmod, link_meta);
     }
 }
+
+fn task_local_llcx_key(_v: @ContextRef) {}
+
+pub fn task_llcx() -> ContextRef {
+    let opt = unsafe { local_data::local_data_get(task_local_llcx_key) };
+    *opt.expect("task-local LLVMContextRef wasn't ever set!")
+}
+
+fn set_task_llcx(c: ContextRef) {
+    unsafe {
+        local_data::local_data_set(task_local_llcx_key, @c);
+    }
+}
diff --git a/src/librustc/middle/trans/build.rs b/src/librustc/middle/trans/build.rs
index 8b281487504..25aa59b852d 100644
--- a/src/librustc/middle/trans/build.rs
+++ b/src/librustc/middle/trans/build.rs
@@ -564,7 +564,8 @@ pub fn LoadRangeAssert(cx: block, PointerVal: ValueRef, lo: c_ulonglong,
 
         do vec::as_imm_buf([min, max]) |ptr, len| {
             llvm::LLVMSetMetadata(value, lib::llvm::MD_range as c_uint,
-                                  llvm::LLVMMDNode(ptr, len as c_uint));
+                                  llvm::LLVMMDNodeInContext(cx.fcx.ccx.llcx,
+                                                            ptr, len as c_uint));
         }
     }
 
diff --git a/src/librustc/middle/trans/cabi_mips.rs b/src/librustc/middle/trans/cabi_mips.rs
index 6be398c0bb2..366c0a90a4c 100644
--- a/src/librustc/middle/trans/cabi_mips.rs
+++ b/src/librustc/middle/trans/cabi_mips.rs
@@ -19,6 +19,7 @@ use lib::llvm::{llvm, TypeRef, Integer, Pointer, Float, Double};
 use lib::llvm::{Struct, Array, Attribute};
 use lib::llvm::{StructRetAttribute};
 use lib::llvm::True;
+use middle::trans::base::task_llcx;
 use middle::trans::common::*;
 use middle::trans::cabi::*;
 
@@ -166,7 +167,7 @@ fn coerce_to_int(size: uint) -> ~[TypeRef] {
     let r = size % 32;
     if r > 0 {
         unsafe {
-            args.push(llvm::LLVMIntType(r as c_uint))
+            args.push(llvm::LLVMIntTypeInContext(task_llcx(), r as c_uint))
         }
     }
 
diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs
index 27d962d6cc7..916a23940cc 100644
--- a/src/librustc/middle/trans/closure.rs
+++ b/src/librustc/middle/trans/closure.rs
@@ -326,7 +326,9 @@ pub fn load_environment(fcx: fn_ctxt,
                 str::as_c_str("load_env",
                               |buf|
                               unsafe {
-                                llvm::LLVMAppendBasicBlock(fcx.llfn, buf)
+                                llvm::LLVMAppendBasicBlockInContext(fcx.ccx.llcx,
+                                                                    fcx.llfn,
+                                                                    buf)
                               });
             fcx.llloadenv = Some(ll);
             ll
diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs
index b29972f039b..9f4e886b124 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -16,7 +16,7 @@ use back::{abi, upcall};
 use driver::session;
 use driver::session::Session;
 use lib::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef, BuilderRef};
-use lib::llvm::{True, False, Bool};
+use lib::llvm::{ContextRef, True, False, Bool};
 use lib::llvm::{llvm, TargetData, TypeNames, associate_type, name_has_type};
 use lib;
 use metadata::common::LinkMeta;
@@ -160,6 +160,7 @@ pub type ExternMap = @mut HashMap<@str, ValueRef>;
 pub struct CrateContext {
      sess: session::Session,
      llmod: ModuleRef,
+     llcx: ContextRef,
      td: TargetData,
      tn: @TypeNames,
      externs: ExternMap,
@@ -798,30 +799,44 @@ impl block_ {
 
 // LLVM type constructors.
 pub fn T_void() -> TypeRef {
-    unsafe {
-        return llvm::LLVMVoidType();
-    }
+    unsafe { return llvm::LLVMVoidTypeInContext(base::task_llcx()); }
 }
 
 pub fn T_nil() -> TypeRef {
     return T_struct([], false)
 }
 
-pub fn T_metadata() -> TypeRef { unsafe { return llvm::LLVMMetadataType(); } }
+pub fn T_metadata() -> TypeRef {
+    unsafe { return llvm::LLVMMetadataTypeInContext(base::task_llcx()); }
+}
 
-pub fn T_i1() -> TypeRef { unsafe { return llvm::LLVMInt1Type(); } }
+pub fn T_i1() -> TypeRef {
+    unsafe { return llvm::LLVMInt1TypeInContext(base::task_llcx()); }
+}
 
-pub fn T_i8() -> TypeRef { unsafe { return llvm::LLVMInt8Type(); } }
+pub fn T_i8() -> TypeRef {
+    unsafe { return llvm::LLVMInt8TypeInContext(base::task_llcx()); }
+}
 
-pub fn T_i16() -> TypeRef { unsafe { return llvm::LLVMInt16Type(); } }
+pub fn T_i16() -> TypeRef {
+    unsafe { return llvm::LLVMInt16TypeInContext(base::task_llcx()); }
+}
 
-pub fn T_i32() -> TypeRef { unsafe { return llvm::LLVMInt32Type(); } }
+pub fn T_i32() -> TypeRef {
+    unsafe { return llvm::LLVMInt32TypeInContext(base::task_llcx()); }
+}
 
-pub fn T_i64() -> TypeRef { unsafe { return llvm::LLVMInt64Type(); } }
+pub fn T_i64() -> TypeRef {
+    unsafe { return llvm::LLVMInt64TypeInContext(base::task_llcx()); }
+}
 
-pub fn T_f32() -> TypeRef { unsafe { return llvm::LLVMFloatType(); } }
+pub fn T_f32() -> TypeRef {
+    unsafe { return llvm::LLVMFloatTypeInContext(base::task_llcx()); }
+}
 
-pub fn T_f64() -> TypeRef { unsafe { return llvm::LLVMDoubleType(); } }
+pub fn T_f64() -> TypeRef {
+    unsafe { return llvm::LLVMDoubleTypeInContext(base::task_llcx()); }
+}
 
 pub fn T_bool() -> TypeRef { return T_i8(); }
 
@@ -881,8 +896,8 @@ pub fn T_size_t(targ_cfg: @session::config) -> TypeRef {
 pub fn T_fn(inputs: &[TypeRef], output: TypeRef) -> TypeRef {
     unsafe {
         return llvm::LLVMFunctionType(output, to_ptr(inputs),
-                                   inputs.len() as c_uint,
-                                   False);
+                                      inputs.len() as c_uint,
+                                      False);
     }
 }
 
@@ -904,16 +919,18 @@ pub fn T_root(t: TypeRef, addrspace: addrspace) -> TypeRef {
 
 pub fn T_struct(elts: &[TypeRef], packed: bool) -> TypeRef {
     unsafe {
-        return llvm::LLVMStructType(to_ptr(elts),
-                                    elts.len() as c_uint,
-                                    packed as Bool);
+        return llvm::LLVMStructTypeInContext(base::task_llcx(),
+                                             to_ptr(elts),
+                                             elts.len() as c_uint,
+                                             packed as Bool);
     }
 }
 
 pub fn T_named_struct(name: &str) -> TypeRef {
     unsafe {
-        let c = llvm::LLVMGetGlobalContext();
-        return str::as_c_str(name, |buf| llvm::LLVMStructCreateNamed(c, buf));
+        return str::as_c_str(name, |buf| {
+            llvm::LLVMStructCreateNamed(base::task_llcx(), buf)
+        });
     }
 }
 
@@ -1191,7 +1208,8 @@ pub fn C_cstr(cx: @CrateContext, s: @~str) -> ValueRef {
         }
 
         let sc = do str::as_c_str(*s) |buf| {
-            llvm::LLVMConstString(buf, s.len() as c_uint, False)
+            llvm::LLVMConstStringInContext(cx.llcx, buf, s.len() as c_uint,
+                                           False)
         };
         let g =
             str::as_c_str(fmt!("str%u", (cx.names)("str").name),
@@ -1220,7 +1238,8 @@ pub fn C_estr_slice(cx: @CrateContext, s: @~str) -> ValueRef {
 pub fn C_postr(s: &str) -> ValueRef {
     unsafe {
         return do str::as_c_str(s) |buf| {
-            llvm::LLVMConstString(buf, s.len() as c_uint, False)
+            llvm::LLVMConstStringInContext(base::task_llcx(),
+                                           buf, s.len() as c_uint, False)
         };
     }
 }
@@ -1239,7 +1258,8 @@ pub fn C_zero_byte_arr(size: uint) -> ValueRef {
 pub fn C_struct(elts: &[ValueRef]) -> ValueRef {
     unsafe {
         do vec::as_imm_buf(elts) |ptr, len| {
-            llvm::LLVMConstStruct(ptr, len as c_uint, False)
+            llvm::LLVMConstStructInContext(base::task_llcx(),
+                                           ptr, len as c_uint, False)
         }
     }
 }
@@ -1247,7 +1267,8 @@ pub fn C_struct(elts: &[ValueRef]) -> ValueRef {
 pub fn C_packed_struct(elts: &[ValueRef]) -> ValueRef {
     unsafe {
         do vec::as_imm_buf(elts) |ptr, len| {
-            llvm::LLVMConstStruct(ptr, len as c_uint, True)
+            llvm::LLVMConstStructInContext(base::task_llcx(),
+                                           ptr, len as c_uint, True)
         }
     }
 }
@@ -1263,13 +1284,13 @@ pub fn C_named_struct(T: TypeRef, elts: &[ValueRef]) -> ValueRef {
 pub fn C_array(ty: TypeRef, elts: &[ValueRef]) -> ValueRef {
     unsafe {
         return llvm::LLVMConstArray(ty, vec::raw::to_ptr(elts),
-                                 elts.len() as c_uint);
+                                    elts.len() as c_uint);
     }
 }
 
 pub fn C_bytes(bytes: &[u8]) -> ValueRef {
     unsafe {
-        return llvm::LLVMConstString(
+        return llvm::LLVMConstStringInContext(base::task_llcx(),
             cast::transmute(vec::raw::to_ptr(bytes)),
             bytes.len() as c_uint, True);
     }
@@ -1277,7 +1298,7 @@ pub fn C_bytes(bytes: &[u8]) -> ValueRef {
 
 pub fn C_bytes_plus_null(bytes: &[u8]) -> ValueRef {
     unsafe {
-        return llvm::LLVMConstString(
+        return llvm::LLVMConstStringInContext(base::task_llcx(),
             cast::transmute(vec::raw::to_ptr(bytes)),
             bytes.len() as c_uint, False);
     }
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index ce93cad73b6..840ced3d0cd 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -13,6 +13,7 @@ use core::prelude::*;
 use driver::session;
 use lib::llvm::ValueRef;
 use lib::llvm::llvm;
+use middle::trans::base::task_llcx;
 use middle::trans::common::*;
 use middle::trans::machine;
 use middle::trans::type_of;
@@ -61,7 +62,9 @@ static DW_ATE_unsigned_char: int = 0x08;
 fn llstr(s: &str) -> ValueRef {
     do str::as_c_str(s) |sbuf| {
         unsafe {
-            llvm::LLVMMDString(sbuf, s.len() as libc::c_uint)
+            llvm::LLVMMDStringInContext(task_llcx(),
+                                        sbuf,
+                                        s.len() as libc::c_uint)
         }
     }
 }
@@ -79,7 +82,9 @@ fn lli1(bval: bool) -> ValueRef {
 }
 fn llmdnode(elems: &[ValueRef]) -> ValueRef {
     unsafe {
-        llvm::LLVMMDNode(vec::raw::to_ptr(elems), elems.len() as libc::c_uint)
+        llvm::LLVMMDNodeInContext(task_llcx(),
+                                  vec::raw::to_ptr(elems),
+                                  elems.len() as libc::c_uint)
     }
 }
 fn llunused() -> ValueRef {
diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs
index e3c424f8e7e..2fff45678bc 100644
--- a/src/librustc/middle/trans/type_of.rs
+++ b/src/librustc/middle/trans/type_of.rs
@@ -58,7 +58,7 @@ pub fn type_of_fn(cx: @CrateContext, inputs: &[ty::t], output: ty::t)
         if output_is_immediate {
             T_fn(atys, lloutputtype)
         } else {
-            T_fn(atys, llvm::LLVMVoidType())
+            T_fn(atys, llvm::LLVMVoidTypeInContext(cx.llcx))
         }
     }
 }
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index 4ee5df28d24..17eb0f50b9b 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -447,9 +447,10 @@ LLVMRustWriteOutputFile(LLVMPassManagerRef PMR,
   return true;
 }
 
-extern "C" LLVMModuleRef LLVMRustParseAssemblyFile(const char *Filename) {
+extern "C" LLVMModuleRef LLVMRustParseAssemblyFile(LLVMContextRef C,
+                                                   const char *Filename) {
   SMDiagnostic d;
-  Module *m = ParseAssemblyFile(Filename, d, getGlobalContext());
+  Module *m = ParseAssemblyFile(Filename, d, *unwrap(C));
   if (m) {
     return wrap(m);
   } else {
@@ -499,9 +500,6 @@ extern "C" LLVMValueRef LLVMGetOrInsertFunction(LLVMModuleRef M,
 extern "C" LLVMTypeRef LLVMMetadataTypeInContext(LLVMContextRef C) {
   return wrap(Type::getMetadataTy(*unwrap(C)));
 }
-extern "C" LLVMTypeRef LLVMMetadataType(void) {
-  return LLVMMetadataTypeInContext(LLVMGetGlobalContext());
-}
 
 extern "C" LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B,
                                             LLVMValueRef source,
@@ -561,3 +559,24 @@ extern "C" LLVMValueRef LLVMInlineAsm(LLVMTypeRef Ty,
                                Constraints, HasSideEffects,
                                IsAlignStack, (InlineAsm::AsmDialect) Dialect));
 }
+
+/**
+ * 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;
+}
diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in
index 8ebdbd0f307..f8c68d798b9 100644
--- a/src/rustllvm/rustllvm.def.in
+++ b/src/rustllvm/rustllvm.def.in
@@ -10,6 +10,7 @@ LLVMRustExecuteJIT
 LLVMRustParseBitcode
 LLVMRustParseAssemblyFile
 LLVMRustPrintPassTimings
+LLVMRustStartMultithreading
 LLVMCreateObjectFile
 LLVMDisposeObjectFile
 LLVMGetSections
@@ -319,7 +320,6 @@ LLVMGetFunctionAttr
 LLVMGetFunctionCallConv
 LLVMGetGC
 LLVMGetGlobalContext
-LLVMGetGlobalContext
 LLVMGetGlobalParent
 LLVMGetGlobalPassRegistry
 LLVMGetIncomingBlock
@@ -500,7 +500,6 @@ LLVMMDNode
 LLVMMDNodeInContext
 LLVMMDString
 LLVMMDStringInContext
-LLVMMetadataType
 LLVMMetadataTypeInContext
 LLVMModuleCreateWithName
 LLVMModuleCreateWithNameInContext