about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Chugunov <vadimcn@gmail.com>2013-06-14 11:38:29 -0700
committerVadim Chugunov <vadimcn@gmail.com>2013-06-17 08:41:23 -0700
commit868f9a88d6a0a495c10baa35a2fb359b5681375f (patch)
tree5a7ae055af7f09ff1870ebab08a9393912de34a5
parent5f0e494d9d7c7c4c866414abd7701d22902415b6 (diff)
downloadrust-868f9a88d6a0a495c10baa35a2fb359b5681375f.tar.gz
rust-868f9a88d6a0a495c10baa35a2fb359b5681375f.zip
Use DIBuilder in debuginfo
-rw-r--r--src/librustc/lib/llvm.rs185
-rw-r--r--src/librustc/middle/trans/base.rs6
-rw-r--r--src/librustc/middle/trans/debuginfo.rs1129
-rw-r--r--src/rustllvm/RustWrapper.cpp201
-rw-r--r--src/rustllvm/rustllvm.def.in17
-rw-r--r--src/rustllvm/rustllvm.h2
6 files changed, 832 insertions, 708 deletions
diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs
index 289bb4f63f5..ece0c1cb190 100644
--- a/src/librustc/lib/llvm.rs
+++ b/src/librustc/lib/llvm.rs
@@ -224,13 +224,51 @@ pub type SectionIteratorRef = *SectionIterator_opaque;
 pub enum Pass_opaque {}
 pub type PassRef = *Pass_opaque;
 
+pub mod debuginfo {
+    use core::prelude::*;
+    use super::{ValueRef};
+    
+    pub enum DIBuilder_opaque {}
+    pub type DIBuilderRef = *DIBuilder_opaque;
+    
+    pub type DIDescriptor = ValueRef;
+    pub type DIScope = DIDescriptor;
+    pub type DILocation = DIDescriptor;
+    pub type DIFile = DIScope;
+    pub type DILexicalBlock = DIScope;
+    pub type DISubprogram = DIScope;
+    pub type DIType = DIDescriptor;
+    pub type DIBasicType = DIType;
+    pub type DIDerivedType = DIType;
+    pub type DICompositeType = DIDerivedType;
+    pub type DIVariable = DIDescriptor;
+    pub type DIArray = DIDescriptor;
+    pub type DISubrange = DIDescriptor;
+
+    pub enum DIDescriptorFlags {
+      FlagPrivate            = 1 << 0,
+      FlagProtected          = 1 << 1,
+      FlagFwdDecl            = 1 << 2,
+      FlagAppleBlock         = 1 << 3,
+      FlagBlockByrefStruct   = 1 << 4,
+      FlagVirtual            = 1 << 5,
+      FlagArtificial         = 1 << 6,
+      FlagExplicit           = 1 << 7,
+      FlagPrototyped         = 1 << 8,
+      FlagObjcClassComplete  = 1 << 9,
+      FlagObjectPointer      = 1 << 10,
+      FlagVector             = 1 << 11,
+      FlagStaticMember       = 1 << 12
+    }
+}
+
 pub mod llvm {
     use super::{AtomicBinOp, AtomicOrdering, BasicBlockRef, ExecutionEngineRef};
     use super::{Bool, BuilderRef, ContextRef, MemoryBufferRef, ModuleRef};
     use super::{ObjectFileRef, Opcode, PassManagerRef, PassManagerBuilderRef};
     use super::{SectionIteratorRef, TargetDataRef, TypeKind, TypeRef, UseRef};
-    use super::{ValueRef,PassRef};
-
+    use super::{ValueRef, PassRef};
+    use super::debuginfo::*;
     use core::libc::{c_char, c_int, c_longlong, c_ushort, c_uint, c_ulonglong};
 
     #[link_args = "-Lrustllvm -lrustllvm"]
@@ -1885,6 +1923,149 @@ pub mod llvm {
                                     AlignStack: Bool, Dialect: c_uint)
                                  -> ValueRef;
 
+
+        #[fast_ffi]
+        pub unsafe fn DIBuilder_new(M: ModuleRef) -> DIBuilderRef;
+
+        #[fast_ffi]
+        pub unsafe fn DIBuilder_delete(Builder: DIBuilderRef);
+
+        #[fast_ffi]
+        pub unsafe fn DIBuilder_finalize(Builder: DIBuilderRef);
+
+        #[fast_ffi]
+        pub unsafe fn DIBuilder_createCompileUnit(
+            Builder: DIBuilderRef,
+            Lang: c_uint,
+            File: *c_char,
+            Dir: *c_char,
+            Producer: *c_char,
+            isOptimized: bool,
+            Flags: *c_char,
+            RuntimeVer: c_uint,
+            SplitName: *c_char);
+
+        #[fast_ffi]
+        pub unsafe fn DIBuilder_createFile(
+            Builder: DIBuilderRef,
+            Filename: *c_char,
+            Directory: *c_char) -> DIFile;
+
+        #[fast_ffi]
+        pub unsafe fn DIBuilder_createSubroutineType(
+            Builder: DIBuilderRef,
+            File: DIFile,
+            ParameterTypes: DIArray) -> DICompositeType;
+
+        #[fast_ffi]
+        pub unsafe fn DIBuilder_createFunction(
+            Builder: DIBuilderRef,
+            Scope: DIDescriptor,
+            Name: *c_char,
+            LinkageName: *c_char,
+            File: DIFile,
+            LineNo: c_uint,
+            Ty: DIType,
+            isLocalToUnit: bool,
+            isDefinition: bool,
+            ScopeLine: c_uint,
+            Flags: c_uint,
+            isOptimized: bool,
+            Fn: ValueRef,
+            TParam: ValueRef,
+            Decl: ValueRef) -> DISubprogram;
+
+        #[fast_ffi]
+        pub unsafe fn DIBuilder_createBasicType(
+            Builder: DIBuilderRef,
+            Name: *c_char,
+            SizeInBits: c_ulonglong,
+            AlignInBits: c_ulonglong,
+            Encoding: c_uint) -> DIBasicType;
+
+        #[fast_ffi]
+        pub unsafe fn DIBuilder_createPointerType(
+            Builder: DIBuilderRef,
+            PointeeTy: DIType,
+            SizeInBits: c_ulonglong,
+            AlignInBits: c_ulonglong,
+            Name: *c_char) -> DIDerivedType;
+
+        #[fast_ffi]
+        pub unsafe fn DIBuilder_createStructType(
+            Builder: DIBuilderRef,
+            Scope: DIDescriptor,
+            Name: *c_char,
+            File: DIFile,
+            LineNumber: c_uint,
+            SizeInBits: c_ulonglong,
+            AlignInBits: c_ulonglong,
+            Flags: c_uint,
+            DerivedFrom: DIType,
+            Elements: DIArray,
+            RunTimeLang: c_uint,
+            VTableHolder: ValueRef) -> DICompositeType;
+
+        #[fast_ffi]
+        pub unsafe fn DIBuilder_createMemberType(
+            Builder: DIBuilderRef,
+            Scope: DIDescriptor,
+            Name: *c_char,
+            File: DIFile,
+            LineNo: c_uint,
+            SizeInBits: c_ulonglong,
+            AlignInBits: c_ulonglong,
+            OffsetInBits: c_ulonglong,
+            Flags: c_uint,
+            Ty: DIType) -> DIDerivedType;
+
+        #[fast_ffi]
+        pub unsafe fn DIBuilder_createLexicalBlock(
+            Builder: DIBuilderRef,
+            Scope: DIDescriptor,
+            File: DIFile,
+            Line: c_uint,
+            Col: c_uint) -> DILexicalBlock;
+
+        #[fast_ffi]
+        pub unsafe fn DIBuilder_createLocalVariable(
+            Builder: DIBuilderRef,
+            Tag: c_uint,
+            Scope: DIDescriptor,
+            Name: *c_char,
+            File: DIFile,
+            LineNo: c_uint,
+            Ty: DIType,
+            AlwaysPreserve: bool,
+            Flags: c_uint,
+            ArgNo: c_uint) -> DIVariable;
+
+        #[fast_ffi]
+        pub unsafe fn DIBuilder_createVectorType(
+            Builder: DIBuilderRef,
+            Size: c_ulonglong,
+            AlignInBits: c_ulonglong,
+            Ty: DIType,
+            Subscripts: DIArray) -> DIType;
+
+        #[fast_ffi]
+        pub unsafe fn DIBuilder_getOrCreateSubrange(
+            Builder: DIBuilderRef,
+            Lo: c_longlong,
+            Count: c_longlong) -> DISubrange;
+
+        #[fast_ffi]
+        pub unsafe fn DIBuilder_getOrCreateArray(
+            Builder: DIBuilderRef,
+            Ptr: *DIDescriptor,
+            Count: c_uint) -> DIArray;
+
+        #[fast_ffi]
+        pub unsafe fn DIBuilder_insertDeclare(
+            Builder: DIBuilderRef,
+            Val: ValueRef,
+            VarInfo: DIVariable,
+            InsertBefore: *c_void) -> *c_void;
     }
 }
 
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 53f2729c38e..580e7fa1900 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -3074,6 +3074,7 @@ pub fn trans_crate(sess: session::Session,
     // 1. http://llvm.org/bugs/show_bug.cgi?id=11479
     let llmod_id = link_meta.name.to_owned() + ".rc";
 
+            Some(debuginfo::mk_ctxt(llmod, copy llmod_id))
     // FIXME(#6511): get LLVM building with --enable-threads so this
     //               function can be called
     // if !llvm::LLVMRustStartMultithreading() {
@@ -3102,7 +3103,10 @@ pub fn trans_crate(sess: session::Session,
     fill_crate_map(ccx, ccx.crate_map);
     glue::emit_tydescs(ccx);
     write_abi_version(ccx);
-
+        if ccx.sess.opts.debuginfo {
+            debuginfo::finalize(ccx);
+        }
+        
     // Translate the metadata.
     write_metadata(ccx, crate);
     if ccx.sess.trans_stats() {
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index 87c33ce64f5..a01c2b89bf9 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -11,9 +11,9 @@
 use core::prelude::*;
 
 use driver::session;
-use lib::llvm::ValueRef;
 use lib::llvm::llvm;
-use middle::trans::context::task_llcx;
+use lib::llvm::{ValueRef, ModuleRef, ContextRef};
+use lib::llvm::debuginfo::*;
 use middle::trans::common::*;
 use middle::trans::machine;
 use middle::trans::type_of;
@@ -21,21 +21,17 @@ use middle::trans;
 use middle::ty;
 use util::ppaux::ty_to_str;
 
-use core::cast;
 use core::hashmap::HashMap;
 use core::libc;
-use core::option;
-use core::ptr;
-use core::str;
-use core::sys;
-use core::vec;
+use core::libc::c_uint;
+use core::str::as_c_str;
 use syntax::codemap::span;
+use syntax::parse::token::ident_interner;
 use syntax::{ast, codemap, ast_util, ast_map};
 
-static LLVMDebugVersion: int = (9 << 16);
+static LLVMDebugVersion: int = (12 << 16);
 
-static DW_LANG_RUST: int = 0x9000;
-static DW_VIRTUALITY_none: int = 0;
+static DW_LANG_RUST: int = 12; //0x9000;
 
 static CompileUnitTag: int = 17;
 static FileDescriptorTag: int = 41;
@@ -59,302 +55,185 @@ static DW_ATE_signed_char: int = 0x06;
 static DW_ATE_unsigned: int = 0x07;
 static DW_ATE_unsigned_char: int = 0x08;
 
-fn llstr(s: &str) -> ValueRef {
-    do str::as_c_str(s) |sbuf| {
-        unsafe {
-            llvm::LLVMMDStringInContext(task_llcx(),
-                                        sbuf,
-                                        s.len() as libc::c_uint)
-        }
-    }
-}
-fn lltag(lltag: int) -> ValueRef {
-    lli32(LLVMDebugVersion | lltag)
-}
-fn lli32(val: int) -> ValueRef {
-    C_i32(val as i32)
-}
-fn lli64(val: int) -> ValueRef {
-    C_i64(val as i64)
-}
-fn lli1(bval: bool) -> ValueRef {
-    C_i1(bval)
-}
-fn llmdnode(elems: &[ValueRef]) -> ValueRef {
-    unsafe {
-        llvm::LLVMMDNodeInContext(task_llcx(),
-                                  vec::raw::to_ptr(elems),
-                                  elems.len() as libc::c_uint)
-    }
-}
-fn llunused() -> ValueRef {
-    lli32(0x0)
-}
-fn llnull() -> ValueRef {
-    unsafe {
-        cast::transmute(ptr::null::<ValueRef>())
-    }
-}
-
-fn add_named_metadata(cx: &CrateContext, name: ~str, val: ValueRef) {
-    str::as_c_str(name, |sbuf| {
-        unsafe {
-            llvm::LLVMAddNamedMetadataOperand(cx.llmod, sbuf, val)
-        }
-    })
-}
-
 ////////////////
 
 pub struct DebugContext {
-    llmetadata: metadata_cache,
+    //llmetadata: metadata_cache,
     names: namegen,
-    crate_file: ~str
-}
-
-pub fn mk_ctxt(crate: ~str) -> DebugContext {
+    crate_file: ~str,
+    builder: DIBuilderRef,
+    
+    created_files: @mut HashMap<~str, DIFile>,
+    created_functions: @mut HashMap<ast::node_id, DISubprogram>,
+    created_blocks: @mut HashMap<ast::node_id, DILexicalBlock>,
+    created_types: @mut HashMap<uint, DIType>
+}
+
+/** Create new DebugContext */
+pub fn mk_ctxt(llmod: ModuleRef, crate: ~str, intr: @ident_interner) -> DebugContext {
+    debug!("mk_ctxt");
+    let builder = unsafe { llvm::DIBuilder_new(llmod) };
     DebugContext {
-        llmetadata: @mut HashMap::new(),
-        names: new_namegen(),
-        crate_file: crate
-    }
+        //llmetadata: @mut HashMap::new(),
+        names: new_namegen(intr),
+        crate_file: crate,
+        builder: builder,
+        created_files: @mut HashMap::new(),
+        created_functions: @mut HashMap::new(),
+        created_blocks: @mut HashMap::new(),
+        created_types: @mut HashMap::new(),
 }
-
-fn update_cache(cache: metadata_cache, mdtag: int, val: debug_metadata) {
-    let mut existing = match cache.pop(&mdtag) {
-        Some(arr) => arr, None => ~[]
-    };
-    existing.push(val);
-    cache.insert(mdtag, existing);
 }
 
-struct Metadata<T> {
-    node: ValueRef,
-    data: T
+#[inline(always)]
+fn get_builder(cx: @CrateContext) -> DIBuilderRef {
+    let dbg_cx = cx.dbg_cx.get_ref();
+    return dbg_cx.builder;
 }
 
-struct FileMetadata {
-    path: ~str
-}
-struct CompileUnitMetadata {
-    name: ~str
-}
-struct SubProgramMetadata {
-    id: ast::node_id
-}
-struct LocalVarMetadata {
-    id: ast::node_id
-}
-struct TyDescMetadata {
-    hash: uint
-}
-struct BlockMetadata {
-    start: codemap::Loc,
-    end: codemap::Loc
-}
-struct ArgumentMetadata {
-    id: ast::node_id
-}
-struct RetvalMetadata {
-    id: ast::node_id
-}
-
-type metadata_cache = @mut HashMap<int, ~[debug_metadata]>;
-
-enum debug_metadata {
-    file_metadata(@Metadata<FileMetadata>),
-    compile_unit_metadata(@Metadata<CompileUnitMetadata>),
-    subprogram_metadata(@Metadata<SubProgramMetadata>),
-    local_var_metadata(@Metadata<LocalVarMetadata>),
-    tydesc_metadata(@Metadata<TyDescMetadata>),
-    block_metadata(@Metadata<BlockMetadata>),
-    argument_metadata(@Metadata<ArgumentMetadata>),
-    retval_metadata(@Metadata<RetvalMetadata>),
+fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
+    return unsafe { 
+        llvm::DIBuilder_getOrCreateArray(builder, vec::raw::to_ptr(arr), arr.len() as u32) 
+    };
 }
 
-fn cast_safely<T:Copy,U>(val: T) -> U {
+/** Create any deferred debug metadata nodes */
+pub fn finalize(cx: @CrateContext) {
+    debug!("finalize");
+    create_compile_unit(cx);
     unsafe {
-        let val2 = val;
-        return cast::transmute(val2);
-    }
+        llvm::DIBuilder_finalize(get_builder(cx));
+        llvm::DIBuilder_delete(get_builder(cx));
+    };
 }
 
-fn md_from_metadata<T>(val: debug_metadata) -> T {
-    match val {
-      file_metadata(md) => cast_safely(md),
-      compile_unit_metadata(md) => cast_safely(md),
-      subprogram_metadata(md) => cast_safely(md),
-      local_var_metadata(md) => cast_safely(md),
-      tydesc_metadata(md) => cast_safely(md),
-      block_metadata(md) => cast_safely(md),
-      argument_metadata(md) => cast_safely(md),
-      retval_metadata(md) => cast_safely(md)
-    }
+fn filename_from_span(cx: @CrateContext, sp: codemap::span) -> ~str {
+    /*bad*/copy cx.sess.codemap.lookup_char_pos(sp.lo).file.name
 }
 
-fn cached_metadata<T:Copy>(cache: metadata_cache,
-                            mdtag: int,
-                            eq_fn: &fn(md: T) -> bool)
-                         -> Option<T> {
-    if cache.contains_key(&mdtag) {
-        let items = cache.get(&mdtag);
-        for items.each |item| {
-            let md: T = md_from_metadata::<T>(*item);
-            if eq_fn(copy md) {
-                return option::Some(copy md);
-            }
-        }
-    }
-    return option::None;
-}
-
-fn create_compile_unit(cx: &mut CrateContext) -> @Metadata<CompileUnitMetadata> {
-    let cache = get_cache(cx);
-    let crate_name = /*bad*/copy (/*bad*/copy cx.dbg_cx).get().crate_file;
-    let tg = CompileUnitTag;
-    match cached_metadata::<@Metadata<CompileUnitMetadata>>(cache, tg,
-                        |md| md.data.name == crate_name) {
-      option::Some(md) => return md,
-      option::None => ()
-    }
+//fn filename_from_span<'cx>(cx: &'cx CrateContext, sp: codemap::span) -> &'cx str {
+//    let fname: &str = cx.sess.codemap.lookup_char_pos(sp.lo).file.name;
+//  return fname;
+//}
 
-    let (_, work_dir) = get_file_path_and_dir(
-        cx.sess.working_dir.to_str(), crate_name);
-    let unit_metadata = ~[lltag(tg),
-                         llunused(),
-                         lli32(DW_LANG_RUST),
-                         llstr(crate_name),
-                         llstr(work_dir),
-                         llstr(env!("CFG_VERSION")),
-                         lli1(true), // deprecated: main compile unit
-                         lli1(cx.sess.opts.optimize != session::No),
-                         llstr(""), // flags (???)
-                         lli32(0) // runtime version (???)
-                        ];
-    let unit_node = llmdnode(unit_metadata);
-    add_named_metadata(cx, ~"llvm.dbg.cu", unit_node);
-    let mdval = @Metadata {
-        node: unit_node,
-        data: CompileUnitMetadata {
-            name: crate_name
-        }
+fn get_file_path_and_dir(work_dir: &str, full_path: &str) -> (~str, ~str) {
+    let full_path = 
+        if str::starts_with(full_path, work_dir) {
+            str::slice(full_path, str::len(work_dir) + 1u,
+                       str::len(full_path)).to_owned()
+        } else {
+            full_path.to_owned()
     };
-    update_cache(cache, tg, compile_unit_metadata(mdval));
-
-    return mdval;
+    
+    return (full_path, work_dir.to_owned());
 }
 
-fn get_cache(cx: &CrateContext) -> metadata_cache {
-    cx.dbg_cx.get_ref().llmetadata
-}
-
-fn get_file_path_and_dir(work_dir: &str, full_path: &str) -> (~str, ~str) {
-    (if full_path.starts_with(work_dir) {
-        full_path.slice(work_dir.len() + 1u,
-                   full_path.len()).to_owned()
-    } else {
-        full_path.to_owned()
-    }, work_dir.to_owned())
-}
+fn create_compile_unit(cx: @CrateContext) {
+    let crate_name: &str = cx.dbg_cx.get_ref().crate_file;
 
-fn create_file(cx: &mut CrateContext, full_path: ~str)
-    -> @Metadata<FileMetadata> {
-    let cache = get_cache(cx);;
-    let tg = FileDescriptorTag;
-    match cached_metadata::<@Metadata<FileMetadata>>(
-        cache, tg, |md| md.data.path == full_path) {
-        option::Some(md) => return md,
-        option::None => ()
+    let (_, work_dir) = get_file_path_and_dir(
+        cx.sess.working_dir.to_str(), crate_name);
+        
+    let producer = fmt!("rustc version %s", env!("CFG_VERSION"));
+
+    do as_c_str(crate_name) |crate_name| {
+    do as_c_str(work_dir) |work_dir| {
+    do as_c_str(producer) |producer| {
+    do as_c_str("") |flags| {
+    do as_c_str("") |split_name| { unsafe {
+        llvm::DIBuilder_createCompileUnit(get_builder(cx),
+            DW_LANG_RUST as c_uint, crate_name, work_dir, producer,
+            cx.sess.opts.optimize != session::No,
+            flags, 0, split_name);
+    }}}}}};
+}
+
+fn create_file(cx: @CrateContext, full_path: &str) -> DIFile {
+    let mut dbg_cx = cx.dbg_cx.get_ref();
+
+    match dbg_cx.created_files.find(&full_path.to_owned()) {
+        Some(file_md) => return *file_md,
+        None => ()
     }
 
+    debug!("create_file: %s", full_path);
+
     let (file_path, work_dir) =
         get_file_path_and_dir(cx.sess.working_dir.to_str(),
                               full_path);
-    let unit_node = create_compile_unit(cx).node;
-    let file_md = ~[lltag(tg),
-                   llstr(file_path),
-                   llstr(work_dir),
-                   unit_node];
-    let val = llmdnode(file_md);
-    let mdval = @Metadata {
-        node: val,
-        data: FileMetadata {
-            path: full_path
-        }
-    };
-    update_cache(cache, tg, file_metadata(mdval));
-    return mdval;
+
+    let file_md =
+        do as_c_str(file_path) |file_path| {
+        do as_c_str(work_dir) |work_dir| { unsafe {
+            llvm::DIBuilder_createFile(get_builder(cx), file_path, work_dir)
+        }}};
+
+    dbg_cx.created_files.insert(full_path.to_owned(), file_md);
+    return file_md;
 }
 
 fn line_from_span(cm: @codemap::CodeMap, sp: span) -> uint {
     cm.lookup_char_pos(sp.lo).line
 }
 
-fn create_block(mut cx: block) -> @Metadata<BlockMetadata> {
-    let cache = get_cache(cx.ccx());
-    while cx.node_info.is_none() {
-        match cx.parent {
-          Some(b) => cx = b,
+fn create_block(bcx: block) -> DILexicalBlock {
+    let mut bcx = bcx;
+    let mut dbg_cx = bcx.ccx().dbg_cx.get_ref();    
+
+    while bcx.node_info.is_none() {
+        match bcx.parent {
+          Some(b) => bcx = b,
           None => fail!()
         }
     }
-    let sp = cx.node_info.get().span;
-
-    let start = cx.sess().codemap.lookup_char_pos(sp.lo);
-    let fname = /*bad*/copy start.file.name;
-    let end = cx.sess().codemap.lookup_char_pos(sp.hi);
-    let tg = LexicalBlockTag;
-    /*match cached_metadata::<@Metadata<BlockMetadata>>(
-        cache, tg,
-        {|md| start == md.data.start && end == md.data.end}) {
-      option::Some(md) { return md; }
-      option::None {}
-    }*/
-
-    let parent = match cx.parent {
-        None => create_function(cx.fcx).node,
-        Some(bcx) => create_block(bcx).node
-    };
-    let file_node = create_file(cx.ccx(), /* bad */ fname.to_owned());
-    let unique_id = match cache.find(&LexicalBlockTag) {
-      option::Some(v) => v.len() as int,
-      option::None => 0
+    let sp = bcx.node_info.get().span;
+    let id = bcx.node_info.get().id;
+
+    match dbg_cx.created_blocks.find(&id) {
+        Some(block) => return *block,
+        None => ()
+    }
+
+    debug!("create_block: %s", bcx.sess().codemap.span_to_str(sp));
+
+    let start = bcx.sess().codemap.lookup_char_pos(sp.lo);
+    let end = bcx.sess().codemap.lookup_char_pos(sp.hi);
+    
+    let parent = match bcx.parent {
+        None => create_function(bcx.fcx),
+        Some(b) => create_block(b)
     };
-    let lldata = ~[lltag(tg),
-                  parent,
-                  lli32(start.line.to_int()),
-                  lli32(start.col.to_int()),
-                  file_node.node,
-                  lli32(unique_id)
-                 ];
-    let val = llmdnode(lldata);
-    let mdval = @Metadata {
-        node: val,
-        data: BlockMetadata {
-            start: start,
-            end: end
-        }
+
+    let file_md = create_file(bcx.ccx(), start.file.name);
+    
+    let block_md = unsafe {
+        llvm::LLVMDIBuilderCreateLexicalBlock(
+            dcx.builder,
+            parent, file_md,
+            start.line.to_int() as c_uint, start.col.to_int() as c_uint) 
     };
-    //update_cache(cache, tg, block_metadata(mdval));
-    return mdval;
+
+    dbg_cx.created_blocks.insert(id, block_md);
+
+    return block_md;
 }
 
-fn size_and_align_of(cx: &mut CrateContext, t: ty::t) -> (int, int) {
+fn size_and_align_of(cx: @CrateContext, t: ty::t) -> (uint, uint) {
     let llty = type_of::type_of(cx, t);
-    (machine::llsize_of_real(cx, llty) as int,
-     machine::llalign_of_pref(cx, llty) as int)
+    (machine::llsize_of_real(cx, llty),
+     machine::llalign_of_pref(cx, llty))
 }
 
-fn create_basic_type(cx: &mut CrateContext, t: ty::t, span: span)
-    -> @Metadata<TyDescMetadata> {
-    let cache = get_cache(cx);
-    let tg = BasicTypeDescriptorTag;
-    match cached_metadata::<@Metadata<TyDescMetadata>>(
-        cache, tg, |md| ty::type_id(t) == md.data.hash) {
-      option::Some(md) => return md,
-      option::None => ()
+fn create_basic_type(cx: @CrateContext, t: ty::t, span: span) -> DIType{
+    let mut dbg_cx = cx.dbg_cx.get_ref();
+    let ty_id = ty::type_id(t);
+    match dbg_cx.created_types.find(&ty_id) {
+        Some(ty_md) => return *ty_md,
+        None => ()
     }
 
+    debug!("create_basic_type: %?", ty::get(t));
+
     let (name, encoding) = match ty::get(t).sty {
         ty::ty_nil | ty::ty_bot => (~"uint", DW_ATE_unsigned),
         ty::ty_bool => (~"bool", DW_ATE_boolean),
@@ -378,383 +257,255 @@ fn create_basic_type(cx: &mut CrateContext, t: ty::t, span: span)
             ast::ty_f32 => (~"f32", DW_ATE_float),
             ast::ty_f64 => (~"f64", DW_ATE_float)
         },
-        _ => cx.sess.bug("debuginfo::create_basic_type - t is invalid type")
+        _ => cx.sess.bug(~"debuginfo::create_basic_type - t is invalid type")
     };
 
-    let fname = filename_from_span(cx, span);
-    let file_node = create_file(cx, fname.to_owned());
-    let cu_node = create_compile_unit(cx);
     let (size, align) = size_and_align_of(cx, t);
-    let lldata = ~[lltag(tg),
-                  cu_node.node,
-                  llstr(name),
-                  file_node.node,
-                  lli32(0), //XXX source line
-                  lli64(size * 8),  // size in bits
-                  lli64(align * 8), // alignment in bits
-                  lli64(0), //XXX offset?
-                  lli32(0), //XXX flags?
-                  lli32(encoding)];
-    let llnode = llmdnode(lldata);
-    let mdval = @Metadata {
-        node: llnode,
-        data: TyDescMetadata {
-            hash: ty::type_id(t)
-        }
-    };
-    update_cache(cache, tg, tydesc_metadata(mdval));
-    add_named_metadata(cx, ~"llvm.dbg.ty", llnode);
-    return mdval;
+    let ty_md = do as_c_str(name) |name| { unsafe {
+            llvm::LLVMDIBuilderCreateBasicType(
+                dcx.builder, name,
+                size * 8 as u64, align * 8 as u64, encoding as c_uint)
+        }};
+
+    dbg_cx.created_types.insert(ty_id, ty_md);
+    return ty_md;
 }
 
-fn create_pointer_type(cx: &mut CrateContext, t: ty::t, span: span,
-                       pointee: @Metadata<TyDescMetadata>)
-    -> @Metadata<TyDescMetadata> {
-    let tg = PointerTypeTag;
-    /*let cache = cx.llmetadata;
-    match cached_metadata::<@Metadata<TyDescMetadata>>(
-        cache, tg, {|md| ty::hash_ty(t) == ty::hash_ty(md.data.hash)}) {
-      option::Some(md) { return md; }
-      option::None {}
-    }*/
+fn create_pointer_type(cx: @CrateContext, t: ty::t, span: span, pointee: DIType) -> DIType {
     let (size, align) = size_and_align_of(cx, t);
-    let fname = filename_from_span(cx, span);
-    let file_node = create_file(cx, fname.to_owned());
-    //let cu_node = create_compile_unit(cx, fname);
     let name = ty_to_str(cx.tcx, t);
-    let llnode = create_derived_type(tg, file_node.node, name, 0, size * 8,
-                                     align * 8, 0, pointee.node);
-    let mdval = @Metadata {
-        node: llnode,
-        data: TyDescMetadata {
-            hash: ty::type_id(t)
-        }
-    };
-    //update_cache(cache, tg, tydesc_metadata(mdval));
-    add_named_metadata(cx, ~"llvm.dbg.ty", llnode);
-    return mdval;
-}
-
-struct StructCtxt {
-    file: ValueRef,
-    name: @str,
-    line: int,
-    members: ~[ValueRef],
-    total_size: int,
-    align: int
-}
-
-fn finish_structure(cx: @mut StructCtxt) -> ValueRef {
-    return create_composite_type(StructureTypeTag,
-                                 cx.name,
-                                 cx.file,
-                                 cx.line,
-                                 cx.total_size,
-                                 cx.align,
-                                 0,
-                                 None,
-                                 Some(/*bad*/copy cx.members));
-}
-
-fn create_structure(file: @Metadata<FileMetadata>, name: @str, line: int)
-                 -> @mut StructCtxt {
-    let cx = @mut StructCtxt {
-        file: file.node,
-        name: name,
-        line: line,
-        members: ~[],
-        total_size: 0,
-        align: 64 //XXX different alignment per arch?
-    };
-    return cx;
-}
+    let ptr_md = do as_c_str(name) |name| { unsafe {
+        llvm::DIBuilder_createPointerType(get_builder(cx), 
+                pointee, size * 8 as u64, align * 8 as u64, name)
+    }};
+    return ptr_md;
+}
+
+struct StructContext {
+    cx: @CrateContext,
+    file: DIFile,
+    name: ~str,
+    line: uint,
+    members: ~[DIDerivedType],
+    total_size: uint,
+    align: uint
+}
+
+impl StructContext {
+    fn create(cx: @CrateContext, file: DIFile, name: ~str, line: uint) -> ~StructContext {
+        let scx = ~StructContext {
+            cx: cx,
+            file: file,
+            name: name,
+            line: line,
+            members: ~[],
+            total_size: 0,
+            align: 64 //XXX different alignment per arch?
+        };
+        return scx;
+    }
 
-fn create_derived_type(type_tag: int, file: ValueRef, name: &str, line: int,
-                       size: int, align: int, offset: int, ty: ValueRef)
-    -> ValueRef {
-    let lldata = ~[lltag(type_tag),
-                  file,
-                  llstr(name),
-                  file,
-                  lli32(line),
-                  lli64(size),
-                  lli64(align),
-                  lli64(offset),
-                  lli32(0),
-                  ty];
-    return llmdnode(lldata);
-}
+    fn add_member(&mut self, name: &str, line: uint, size: uint, align: uint, ty: DIType) {
+        let mem_t = do as_c_str(name) |name| { unsafe {
+            llvm::DIBuilder_createMemberType(get_builder(self.cx), 
+                ptr::null(), name, self.file, line as c_uint,
+                size * 8 as u64, align * 8 as u64, self.total_size as u64, 
+                0, ty)
+            }};
+        // XXX What about member alignment???
+        self.members.push(mem_t);
+        self.total_size += size * 8;
+    }
 
-fn add_member(cx: @mut StructCtxt,
-              name: &str,
-              line: int,
-              size: int,
-              align: int,
-              ty: ValueRef) {
-    cx.members.push(create_derived_type(MemberTag, cx.file, name, line,
-                                        size * 8, align * 8, cx.total_size,
-                                        ty));
-    cx.total_size += size * 8;
+    fn finalize(&self) -> DICompositeType {
+        let members_md = create_DIArray(get_builder(self.cx), self.members);
+
+        let struct_md =
+            do as_c_str(self.name) |name| { unsafe {
+                llvm::LLVMDIBuilderCreateStructType(
+                    dcx.builder, ptr::null(), name, 
+                    self.file, self.line as c_uint,
+                    self.total_size as u64, self.align as u64, 0, ptr::null(),
+                    members_md, 0, ptr::null())
+            }};
+        return struct_md;
+    }
 }
 
-fn create_struct(cx: &mut CrateContext, t: ty::t, fields: ~[ty::field],
-                 span: span) -> @Metadata<TyDescMetadata> {
+fn create_struct(cx: @CrateContext, t: ty::t, fields: ~[ty::field], span: span) -> DICompositeType {
     let fname = filename_from_span(cx, span);
-    let file_node = create_file(cx, fname.to_owned());
-    let scx = create_structure(file_node, (ty_to_str(cx.tcx, t)).to_managed(),
-                               line_from_span(cx.sess.codemap, span) as int);
+    let file_md = create_file(cx, fname);
+    let line = line_from_span(cx.sess.codemap, span);
+
+    let mut scx = StructContext::create(cx, file_md, ty_to_str(cx.tcx, t), line);
     for fields.each |field| {
         let field_t = field.mt.ty;
         let ty_md = create_ty(cx, field_t, span);
         let (size, align) = size_and_align_of(cx, field_t);
-        add_member(scx, cx.sess.str_of(field.ident),
-                   line_from_span(cx.sess.codemap, span) as int,
-                   size as int, align as int, ty_md.node);
+        scx.add_member(cx.sess.str_of(field.ident),
+                   line_from_span(cx.sess.codemap, span),
+                   size, align, ty_md);
     }
-    let mdval = @Metadata {
-        node: finish_structure(scx),
-        data: TyDescMetadata {
-            hash: ty::type_id(t)
-        }
-    };
-    return mdval;
+    return scx.finalize();
 }
 
-fn create_tuple(cx: &mut CrateContext, t: ty::t, elements: &[ty::t], span: span)
-    -> @Metadata<TyDescMetadata> {
+// returns (void* type as a ValueRef, size in bytes, align in bytes)
+fn voidptr() -> (DIDerivedType, uint, uint) {
+    let size = sys::size_of::<ValueRef>();
+    let align = sys::min_align_of::<ValueRef>();
+    let vp = ptr::null();
+    /*
+    let vp = create_derived_type(PointerTypeTag, null, ~"", 0,
+                                 size, align, 0, null);
+    */
+    return (vp, size, align);
+}
+
+fn create_tuple(cx: @CrateContext, t: ty::t, elements: &[ty::t], span: span) -> DICompositeType {
     let fname = filename_from_span(cx, span);
-    let file_node = create_file(cx, fname.to_owned());
-    let scx = create_structure(file_node,
-                               cx.sess.str_of(
-                                   ((/*bad*/copy cx.dbg_cx).get().names)
-                                   ("tuple")),
-                               line_from_span(cx.sess.codemap, span) as int);
+    let file_md = create_file(cx, fname);
+
+    let name = (cx.sess.str_of((dcx.names)("tuple"))).to_owned();
+    let mut scx = StructContext::create(cx, file_md, name, loc.line);
+
     for elements.each |element| {
         let ty_md = create_ty(cx, *element, span);
         let (size, align) = size_and_align_of(cx, *element);
-        add_member(scx, "", line_from_span(cx.sess.codemap, span) as int,
-                   size as int, align as int, ty_md.node);
+        scx.add_member("", line_from_span(cx.sess.codemap, span),
+                   size, align, ty_md);
     }
-    let mdval = @Metadata {
-        node: finish_structure(scx),
-        data: TyDescMetadata {
-            hash: ty::type_id(t)
-        }
-    };
-    return mdval;
-}
-
-// returns (void* type as a ValueRef, size in bytes, align in bytes)
-fn voidptr() -> (ValueRef, int, int) {
-    let null = ptr::null();
-    let size = sys::size_of::<ValueRef>() as int;
-    let align = sys::min_align_of::<ValueRef>() as int;
-    let vp = create_derived_type(PointerTypeTag, null, "", 0,
-                                 size, align, 0, null);
-    return (vp, size, align);
+    return scx.finalize();
 }
 
-fn create_boxed_type(cx: &mut CrateContext, contents: ty::t,
-                     span: span, boxed: @Metadata<TyDescMetadata>)
-    -> @Metadata<TyDescMetadata> {
-    //let tg = StructureTypeTag;
-    /*let cache = cx.llmetadata;
-    match cached_metadata::<@Metadata<TyDescMetadata>>(
-        cache, tg, {|md| ty::hash_ty(contents) == ty::hash_ty(md.data.hash)}) {
-      option::Some(md) { return md; }
-      option::None {}
-    }*/
+fn create_boxed_type(cx: @CrateContext, contents: ty::t,
+                     span: span, boxed: DIType) -> DICompositeType {
     let fname = filename_from_span(cx, span);
-    let file_node = create_file(cx, fname.to_owned());
-    //let cu_node = create_compile_unit_metadata(cx, fname);
+    let file_md = create_file(cx, fname);
     let int_t = ty::mk_int();
     let refcount_type = create_basic_type(cx, int_t, span);
     let name = ty_to_str(cx.tcx, contents);
-    let scx = create_structure(file_node, (fmt!("box<%s>", name)).to_managed(), 0);
-    add_member(scx, "refcnt", 0, sys::size_of::<uint>() as int,
-               sys::min_align_of::<uint>() as int, refcount_type.node);
+
+    let mut scx = StructContext::create(cx, file_md, fmt!("box<%s>", name), 0);
+    scx.add_member("refcnt", 0, sys::size_of::<uint>(),
+               sys::min_align_of::<uint>(), refcount_type);
     // the tydesc and other pointers should be irrelevant to the
     // debugger, so treat them as void* types
     let (vp, vpsize, vpalign) = voidptr();
-    add_member(scx, "tydesc", 0, vpsize, vpalign, vp);
-    add_member(scx, "prev", 0, vpsize, vpalign, vp);
-    add_member(scx, "next", 0, vpsize, vpalign, vp);
+    scx.add_member("tydesc", 0, vpsize, vpalign, vp);
+    scx.add_member("prev", 0, vpsize, vpalign, vp);
+    scx.add_member("next", 0, vpsize, vpalign, vp);
     let (size, align) = size_and_align_of(cx, contents);
-    add_member(scx, "boxed", 0, size, align, boxed.node);
-    let llnode = finish_structure(scx);
-    let mdval = @Metadata {
-        node: llnode,
-        data: TyDescMetadata {
-            hash: ty::type_id(contents)
-        }
-    };
-    //update_cache(cache, tg, tydesc_metadata(mdval));
-    add_named_metadata(cx, ~"llvm.dbg.ty", llnode);
-    return mdval;
-}
-
-fn create_composite_type(type_tag: int, name: &str, file: ValueRef,
-                         line: int, size: int, align: int, offset: int,
-                         derived: Option<ValueRef>,
-                         members: Option<~[ValueRef]>)
-    -> ValueRef {
-    let lldata = ~[lltag(type_tag),
-                  file,
-                  llstr(name), // type name
-                  file, // source file definition
-                  lli32(line), // source line definition
-                  lli64(size), // size of members
-                  lli64(align), // align
-                  lli32/*64*/(offset), // offset
-                  lli32(0), // flags
-                  if derived.is_none() {
-                      llnull()
-                  } else { // derived from
-                      derived.get()
-                  },
-                  if members.is_none() {
-                      llnull()
-                  } else { //members
-                      llmdnode(members.get())
-                  },
-                  lli32(0),  // runtime language
-                  llnull()
-                 ];
-    return llmdnode(lldata);
+    scx.add_member("boxed", 0, size, align, boxed);
+    return scx.finalize();
 }
 
-fn create_fixed_vec(cx: &mut CrateContext, vec_t: ty::t, elem_t: ty::t,
-                    len: int, span: span) -> @Metadata<TyDescMetadata> {
-    let t_md = create_ty(cx, elem_t, span);
+fn create_fixed_vec(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t,
+                    len: uint, span: span) -> DIType {
+    let elem_ty_md = create_ty(cx, elem_t, span);
     let fname = filename_from_span(cx, span);
-    let file_node = create_file(cx, fname.to_owned());
+    let file_md = create_file(cx, fname);
     let (size, align) = size_and_align_of(cx, elem_t);
-    let subrange = llmdnode([lltag(SubrangeTag), lli64(0), lli64(len - 1)]);
-    let name = fmt!("[%s]", ty_to_str(cx.tcx, elem_t));
-    let array = create_composite_type(ArrayTypeTag, name, file_node.node, 0,
-                                      size * len, align, 0, Some(t_md.node),
-                                      Some(~[subrange]));
-    @Metadata {
-        node: array,
-        data: TyDescMetadata {
-            hash: ty::type_id(vec_t)
-        }
-    }
+
+    let subrange = unsafe {
+        llvm::DIBuilder_getOrCreateSubrange(get_builder(cx), 0_i64, (len-1) as i64) };
+
+    let subscripts = create_DIArray(get_builder(cx), [subrange]);
+    return unsafe {
+        llvm::DIBuilder_createVectorType(get_builder(cx), 
+            size * len as u64, align as u64, elem_ty_md, subscripts) 
+    };
 }
 
-fn create_boxed_vec(cx: &mut CrateContext, vec_t: ty::t, elem_t: ty::t,
-                    vec_ty_span: codemap::span)
-    -> @Metadata<TyDescMetadata> {
+fn create_boxed_vec(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t,
+                    vec_ty_span: codemap::span) -> DICompositeType {
     let fname = filename_from_span(cx, vec_ty_span);
-    let file_node = create_file(cx, fname.to_owned());
+    let file_md = create_file(cx, fname);
     let elem_ty_md = create_ty(cx, elem_t, vec_ty_span);
-    let vec_scx = create_structure(file_node,
-                               ty_to_str(cx.tcx, vec_t).to_managed(), 0);
+
+    let mut vec_scx = StructContext::create(cx, file_md, ty_to_str(cx.tcx, vec_t), 0);
+
     let size_t_type = create_basic_type(cx, ty::mk_uint(), vec_ty_span);
-    add_member(vec_scx, "fill", 0, sys::size_of::<libc::size_t>() as int,
-               sys::min_align_of::<libc::size_t>() as int, size_t_type.node);
-    add_member(vec_scx, "alloc", 0, sys::size_of::<libc::size_t>() as int,
-               sys::min_align_of::<libc::size_t>() as int, size_t_type.node);
-    let subrange = llmdnode([lltag(SubrangeTag), lli64(0), lli64(0)]);
+    vec_scx.add_member("fill", 0, sys::size_of::<libc::size_t>(),
+               sys::min_align_of::<libc::size_t>(), size_t_type);
+    vec_scx.add_member("alloc", 0, sys::size_of::<libc::size_t>(),
+               sys::min_align_of::<libc::size_t>(), size_t_type);
+    let subrange = unsafe { llvm::DIBuilder_getOrCreateSubrange(get_builder(cx), 0_i64, 0_i64) };
     let (arr_size, arr_align) = size_and_align_of(cx, elem_t);
     let name = fmt!("[%s]", ty_to_str(cx.tcx, elem_t));
-    let data_ptr = create_composite_type(ArrayTypeTag, name, file_node.node, 0,
-                                         arr_size, arr_align, 0,
-                                         Some(elem_ty_md.node),
-                                         Some(~[subrange]));
-    add_member(vec_scx, "data", 0, 0, // clang says the size should be 0
-               sys::min_align_of::<u8>() as int, data_ptr);
-    let llnode = finish_structure(vec_scx);
-    let vec_md = @Metadata {
-        node: llnode,
-        data: TyDescMetadata {
-            hash: ty::type_id(vec_t)
-        }
-    };
 
-    let box_scx = create_structure(file_node, (fmt!("box<%s>", name)).to_managed(), 0);
+    let subscripts = create_DIArray(get_builder(cx), [subrange]);
+    let data_ptr = unsafe { llvm::DIBuilder_createVectorType(get_builder(cx), 
+                arr_size as u64, arr_align as u64, elem_ty_md, subscripts) };
+    vec_scx.add_member("data", 0, 0, // clang says the size should be 0
+               sys::min_align_of::<u8>(), data_ptr);
+    let vec_md = vec_scx.finalize();
+
+    let mut box_scx = StructContext::create(cx, file_md, fmt!("box<%s>", name), 0);
     let int_t = ty::mk_int();
     let refcount_type = create_basic_type(cx, int_t, vec_ty_span);
-    add_member(box_scx, "refcnt", 0, sys::size_of::<uint>() as int,
-               sys::min_align_of::<uint>() as int, refcount_type.node);
+    box_scx.add_member("refcnt", 0, sys::size_of::<uint>(),
+               sys::min_align_of::<uint>(), refcount_type);
     let (vp, vpsize, vpalign) = voidptr();
-    add_member(box_scx, "tydesc", 0, vpsize, vpalign, vp);
-    add_member(box_scx, "prev", 0, vpsize, vpalign, vp);
-    add_member(box_scx, "next", 0, vpsize, vpalign, vp);
-    let size = 2 * sys::size_of::<int>() as int;
-    let align = sys::min_align_of::<int>() as int;
-    add_member(box_scx, "boxed", 0, size, align, vec_md.node);
-    let llnode = finish_structure(box_scx);
-    let mdval = @Metadata {
-        node: llnode,
-        data: TyDescMetadata {
-            hash: ty::type_id(elem_t)
-        }
-    };
+    box_scx.add_member("tydesc", 0, vpsize, vpalign, vp);
+    box_scx.add_member("prev", 0, vpsize, vpalign, vp);
+    box_scx.add_member("next", 0, vpsize, vpalign, vp);
+    let size = 2 * sys::size_of::<int>();
+    let align = sys::min_align_of::<int>();
+    box_scx.add_member("boxed", 0, size, align, vec_md);
+    let mdval = box_scx.finalize();
     return mdval;
 }
 
-fn create_vec_slice(cx: &mut CrateContext, vec_t: ty::t, elem_t: ty::t, span: span)
-    -> @Metadata<TyDescMetadata> {
+fn create_vec_slice(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t, span: span) -> DICompositeType {
     let fname = filename_from_span(cx, span);
-    let file_node = create_file(cx, fname.to_owned());
+    let file_md = create_file(cx, fname);
     let elem_ty_md = create_ty(cx, elem_t, span);
     let uint_type = create_basic_type(cx, ty::mk_uint(), span);
     let elem_ptr = create_pointer_type(cx, elem_t, span, elem_ty_md);
-    let scx = create_structure(file_node, ty_to_str(cx.tcx, vec_t).to_managed(), 0);
+
+    let mut scx = StructContext::create(cx, file_md, ty_to_str(cx.tcx, vec_t), 0);
     let (_, ptr_size, ptr_align) = voidptr();
-    add_member(scx, "vec", 0, ptr_size, ptr_align, elem_ptr.node);
-    add_member(scx, "length", 0, sys::size_of::<uint>() as int,
-               sys::min_align_of::<uint>() as int, uint_type.node);
-    let llnode = finish_structure(scx);
-    let mdval = @Metadata {
-        node: llnode,
-        data: TyDescMetadata {
-            hash: ty::type_id(vec_t)
-        }
-    };
-    return mdval;
+    scx.add_member("vec", 0, ptr_size, ptr_align, elem_ptr);
+    scx.add_member("length", 0, sys::size_of::<uint>(),
+               sys::min_align_of::<uint>(), uint_type);
+    return scx.finalize();
 }
 
-fn create_fn_ty(cx: &mut CrateContext, fn_ty: ty::t, inputs: ~[ty::t], output: ty::t,
-                span: span) -> @Metadata<TyDescMetadata> {
+fn create_fn_ty(cx: @CrateContext, fn_ty: ty::t, inputs: ~[ty::t], output: ty::t,
+                span: span) -> DICompositeType {
     let fname = filename_from_span(cx, span);
-    let file_node = create_file(cx, fname.to_owned());
+    let file_md = create_file(cx, fname);
     let (vp, _, _) = voidptr();
     let output_md = create_ty(cx, output, span);
     let output_ptr_md = create_pointer_type(cx, output, span, output_md);
-    let inputs_vals = do inputs.map |arg| { create_ty(cx, *arg, span).node };
-    let members = ~[output_ptr_md.node, vp] + inputs_vals;
-    let llnode = create_composite_type(SubroutineTag, "", file_node.node,
-                                       0, 0, 0, 0, None, Some(members));
-    let mdval = @Metadata {
-        node: llnode,
-        data: TyDescMetadata {
-            hash: ty::type_id(fn_ty)
-        }
+    let inputs_vals = do inputs.map |arg| { create_ty(cx, *arg, span) };
+    let members = ~[output_ptr_md, vp] + inputs_vals;
+
+    return unsafe {
+        llvm::DIBuilder_createSubroutineType(get_builder(cx), file_md, 
+            create_DIArray(get_builder(cx), members)) 
     };
-    return mdval;
 }
 
-fn create_ty(cx: &mut CrateContext, t: ty::t, span: span)
-    -> @Metadata<TyDescMetadata> {
+fn create_ty(cx: @CrateContext, t: ty::t, span: span) -> DIType {
+    let mut dbg_cx = cx.dbg_cx.get_ref();
+    let ty_id = ty::type_id(t);
+    match dbg_cx.created_types.find(&ty_id) {
+        Some(ty_md) => return *ty_md,
+        None => ()
+    }
+
     debug!("create_ty: %?", ty::get(t));
-    /*let cache = get_cache(cx);
-    match cached_metadata::<@Metadata<TyDescMetadata>>(
-        cache, tg, {|md| t == md.data.hash}) {
-      option::Some(md) { return md; }
-      option::None {}
-    }*/
 
     let sty = copy ty::get(t).sty;
-    match sty {
+    let ty_md = match sty {
         ty::ty_nil | ty::ty_bot | ty::ty_bool | ty::ty_int(_) | ty::ty_uint(_)
         | ty::ty_float(_) => create_basic_type(cx, t, span),
         ty::ty_estr(ref vstore) => {
             let i8_t = ty::mk_i8();
             match *vstore {
                 ty::vstore_fixed(len) => {
-                    create_fixed_vec(cx, t, i8_t, len as int + 1, span)
+                    create_fixed_vec(cx, t, i8_t, len + 1, span)
                 },
                 ty::vstore_uniq | ty::vstore_box => {
                     let box_md = create_boxed_vec(cx, t, i8_t, span);
@@ -776,7 +527,7 @@ fn create_ty(cx: &mut CrateContext, t: ty::t, span: span)
         ty::ty_evec(ref mt, ref vstore) => {
             match *vstore {
                 ty::vstore_fixed(len) => {
-                    create_fixed_vec(cx, t, mt.ty, len as int, span)
+                    create_fixed_vec(cx, t, mt.ty, len, span)
                 },
                 ty::vstore_uniq | ty::vstore_box => {
                     let box_md = create_boxed_vec(cx, t, mt.ty, span);
@@ -812,30 +563,17 @@ fn create_ty(cx: &mut CrateContext, t: ty::t, span: span)
         ty::ty_tup(ref elements) => {
             create_tuple(cx, t, *elements, span)
         },
-        _ => cx.sess.bug("debuginfo: unexpected type in create_ty")
-    }
-}
-
-fn filename_from_span(cx: &CrateContext, sp: codemap::span) -> @str {
-    cx.sess.codemap.lookup_char_pos(sp.lo).file.name
-}
+        _ => cx.sess.bug(~"debuginfo: unexpected type in create_ty")
+    };
 
-fn create_var(type_tag: int, context: ValueRef, name: &str, file: ValueRef,
-              line: int, ret_ty: ValueRef) -> ValueRef {
-    let lldata = ~[lltag(type_tag),
-                  context,
-                  llstr(name),
-                  file,
-                  lli32(line),
-                  ret_ty,
-                  lli32(0)
-                 ];
-    return llmdnode(lldata);
+    dbg_cx.created_types.insert(ty_id, ty_md);
+    return ty_md;
 }
 
-pub fn create_local_var(bcx: block, local: @ast::local)
-    -> @Metadata<LocalVarMetadata> {
+pub fn create_local_var(bcx: block, local: @ast::local) -> DIVariable {
+    debug!("create_local_var");
     let cx = bcx.ccx();
+    /*
     let cache = get_cache(cx);
     let tg = AutoVariableTag;
     match cached_metadata::<@Metadata<LocalVarMetadata>>(
@@ -843,49 +581,56 @@ pub fn create_local_var(bcx: block, local: @ast::local)
       option::Some(md) => return md,
       option::None => ()
     }
+    */
 
     let name = match local.node.pat.node {
       ast::pat_ident(_, pth, _) => ast_util::path_to_ident(pth),
       // FIXME this should be handled (#2533)
       _ => fail!("no single variable name for local")
     };
-    let loc = cx.sess.codemap.lookup_char_pos(local.span.lo);
+    let name: &str = cx.sess.str_of(ident);
+    debug!("create_local_var: %s", name);
+
+    let loc = span_start(cx, local.span);
     let ty = node_id_type(bcx, local.node.id);
     let tymd = create_ty(cx, ty, local.node.ty.span);
-    let filemd = create_file(cx, /*bad*/ loc.file.name.to_owned());
+    let filemd = create_file(cx, /*bad*/copy loc.file.name);
     let context = match bcx.parent {
-        None => create_function(bcx.fcx).node,
-        Some(_) => create_block(bcx).node
+        None => create_function(bcx.fcx),
+        Some(_) => create_block(bcx)
     };
-    let mdnode = create_var(tg, context, cx.sess.str_of(name),
-                            filemd.node, loc.line as int, tymd.node);
-    let mdval = @Metadata {
-        node: mdnode,
-        data: LocalVarMetadata {
-            id: local.node.id
-        }
-    };
-    update_cache(cache, AutoVariableTag, local_var_metadata(mdval));
-
-    // FIXME(#6814) Should use `pat_util::pat_bindings` for pats like (a, b) etc
-    let llptr = match bcx.fcx.lllocals.find_copy(&local.node.pat.id) {
-        Some(v) => v,
-        None => {
-            bcx.tcx().sess.span_bug(
-                local.span,
-                fmt!("No entry in lllocals table for %?", local.node.id));
+
+    let mdval = do as_c_str(*cx.sess.str_of(name)) |name| { unsafe {
+        llvm::DIBuilder_createLocalVariable(get_builder(cx), AutoVariableTag as u32,
+                 ptr::null(), name, filemd, loc.line as c_uint, tymd, false, 0, 0)
+        }};
+
+    let llptr = match bcx.fcx.lllocals.find(&local.node.id) {
+      option::Some(&local_mem(v)) => v,
+      option::Some(_) => {
+        bcx.tcx().sess.span_bug(local.span, "local is bound to something weird");
         }
+      option::None => {
+        match bcx.fcx.lllocals.get_copy(&local.node.pat.id) {
+          local_imm(v) => v,
+          _ => bcx.tcx().sess.span_bug(local.span, "local is bound to something weird")
+    }
+      }
     };
-    let declargs = ~[llmdnode([llptr]), mdnode];
-    trans::build::Call(bcx, cx.intrinsics.get_copy(&("llvm.dbg.declare")),
+    /*
+    llvm::DIBuilder_insertDeclare(get_builder(cx), llptr, mdval, 
+
+    let declargs = ~[llmdnode(~[llptr]), mdnode];
+    trans::build::Call(bcx, *cx.intrinsics.get(&~"llvm.dbg.declare"),
                        declargs);
+    */
     return mdval;
-}
+    }
 
-pub fn create_arg(bcx: block, arg: ast::arg, sp: span)
-    -> Option<@Metadata<ArgumentMetadata>> {
-    let fcx = bcx.fcx;
-    let cx = fcx.ccx;
+pub fn create_arg(bcx: block, arg: ast::arg, sp: span) -> Option<DIVariable> {
+    debug!("create_arg");
+    let fcx = bcx.fcx, cx = *fcx.ccx;
+    /*
     let cache = get_cache(cx);
     let tg = ArgVariableTag;
     match cached_metadata::<@Metadata<ArgumentMetadata>>(
@@ -893,6 +638,7 @@ pub fn create_arg(bcx: block, arg: ast::arg, sp: span)
       option::Some(md) => return Some(md),
       option::None => ()
     }
+    */
 
     let loc = cx.sess.codemap.lookup_char_pos(sp.lo);
     if "<intrinsic>" == loc.file.name {
@@ -900,35 +646,30 @@ pub fn create_arg(bcx: block, arg: ast::arg, sp: span)
     }
     let ty = node_id_type(bcx, arg.id);
     let tymd = create_ty(cx, ty, arg.ty.span);
-    let filemd = create_file(cx, /* bad */ loc.file.name.to_owned());
+    let filemd = create_file(cx, /*bad*/copy loc.file.name);
     let context = create_function(bcx.fcx);
 
     match arg.pat.node {
         ast::pat_ident(_, path, _) => {
             // XXX: This is wrong; it should work for multiple bindings.
-            let mdnode = create_var(
-                tg,
-                context.node,
-                cx.sess.str_of(*path.idents.last()),
-                filemd.node,
-                loc.line as int,
-                tymd.node
-            );
-
-            let mdval = @Metadata {
-                node: mdnode,
-                data: ArgumentMetadata {
-                    id: arg.id
-                }
+            let ident = path.idents.last();
+            let name: &str = cx.sess.str_of(*ident);
+            let mdnode = do as_c_str(name) |name| { unsafe {
+                llvm::LLVMDIBuilderCreateLocalVariable(dcx.builder,
+                    ArgVariableTag as u32, context, name,
+                    filemd, loc.line as c_uint, tymd, false, 0, 0)
+                    // XXX need to pass a real argument number
+            }};
+
+            let llptr = match fcx.llargs.get_copy(&arg.id) {
+              local_mem(v) | local_imm(v) => v,
             };
-            update_cache(cache, tg, argument_metadata(mdval));
-
-            let llptr = fcx.llargs.get_copy(&arg.id);
-            let declargs = ~[llmdnode([llptr]), mdnode];
-            trans::build::Call(bcx,
-                               cx.intrinsics.get_copy(&("llvm.dbg.declare")),
-                               declargs);
-            return Some(mdval);
+            
+            /*
+            llvm::DIBuilder_insertDeclare(get_builder(cx), mdnode, llptr, mdnode
+            */
+            
+            return Some(mdnode);
         }
         _ => {
             return None;
@@ -936,32 +677,27 @@ pub fn create_arg(bcx: block, arg: ast::arg, sp: span)
     }
 }
 
-pub fn update_source_pos(cx: block, s: span) {
-    if !cx.sess().opts.debuginfo || (*s.lo == 0 && *s.hi == 0) {
-        return;
-    }
-    let cm = cx.sess().codemap;
-    let blockmd = create_block(cx);
-    let loc = cm.lookup_char_pos(s.lo);
-    let scopedata = ~[lli32(loc.line.to_int()),
-                     lli32(loc.col.to_int()),
-                     blockmd.node,
-                     llnull()];
-    let dbgscope = llmdnode(scopedata);
+fn create_debug_loc(line: int, col: int, scope: DIScope) -> DILocation {
+    let elems = ~[C_i32(line as i32), C_i32(col as i32), scope, ptr::null()];
     unsafe {
-        llvm::LLVMSetCurrentDebugLocation(trans::build::B(cx), dbgscope);
+        return llvm::LLVMMDNode(vec::raw::to_ptr(elems), elems.len() as libc::c_uint);
     }
 }
 
-pub fn create_function(fcx: fn_ctxt) -> @Metadata<SubProgramMetadata> {
-    let mut cx = fcx.ccx;
-
-    debug!("~~");
+    let cm = bcx.sess().codemap;
+    let blockmd = create_block(bcx);
+    let loc = cm.lookup_char_pos(sp.lo);
+    let dbgscope = create_debug_loc(loc.line.to_int(), loc.col.to_int(), blockmd);
+    unsafe {
+        llvm::LLVMSetCurrentDebugLocation(trans::build::B(bcx), dbgscope);
+    }
+}
 
+pub fn create_function(fcx: fn_ctxt) -> DISubprogram {
+    let cx = *fcx.ccx;
+    let mut dbg_cx = cx.dbg_cx.get_ref();
     let fcx = &mut *fcx;
-
     let sp = fcx.span.get();
-    debug!("%s", cx.sess.codemap.span_to_str(sp));
 
     let (ident, ret_ty, id) = match cx.tcx.items.get_copy(&fcx.id) {
       ast_map::node_item(item, _) => {
@@ -978,7 +714,6 @@ pub fn create_function(fcx: fn_ctxt) -> @Metadata<SubProgramMetadata> {
       ast_map::node_expr(expr) => {
         match expr.node {
           ast::expr_fn_block(ref decl, _) => {
-            let dbg_cx = cx.dbg_cx.get_ref();
             ((dbg_cx.names)("fn"), decl.output, expr.id)
           }
           _ => fcx.ccx.sess.span_bug(expr.span,
@@ -988,62 +723,46 @@ pub fn create_function(fcx: fn_ctxt) -> @Metadata<SubProgramMetadata> {
       _ => fcx.ccx.sess.bug("create_function: unexpected sort of node")
     };
 
-    debug!("%?", ident);
-    debug!("%?", id);
-
-    let cache = get_cache(cx);
-    match cached_metadata::<@Metadata<SubProgramMetadata>>(
-        cache, SubprogramTag, |md| md.data.id == id) {
-      option::Some(md) => return md,
-      option::None => ()
+    match dbg_cx.created_functions.find(&id) {
+        Some(fn_md) => return *fn_md,
+        None => ()
     }
 
+    debug!("create_function: %s, %s", cx.sess.str_of(ident), cx.sess.codemap.span_to_str(span));
+
     let loc = cx.sess.codemap.lookup_char_pos(sp.lo);
-    let file_node = create_file(cx, loc.file.name.to_owned()).node;
-    let ty_node = if cx.sess.opts.extra_debuginfo {
+    let file_md = create_file(cx, loc.file.name);
+
+    let ret_ty_md = if cx.sess.opts.extra_debuginfo {
         match ret_ty.node {
-          ast::ty_nil => llnull(),
+          ast::ty_nil => ptr::null(),
           _ => create_ty(cx, ty::node_id_to_type(cx.tcx, id),
-                         ret_ty.span).node
+                         ret_ty.span)
         }
     } else {
-        llnull()
+        ptr::null()
     };
-    let sub_node = create_composite_type(SubroutineTag, "", file_node, 0, 0,
-                                         0, 0, option::None,
-                                         option::Some(~[ty_node]));
-
-    let fn_metadata = ~[lltag(SubprogramTag),
-                       llunused(),
-                       file_node,
-                       llstr(cx.sess.str_of(ident)),
-                        //XXX fully-qualified C++ name:
-                       llstr(cx.sess.str_of(ident)),
-                       llstr(""), //XXX MIPS name?????
-                       file_node,
-                       lli32(loc.line as int),
-                       sub_node,
-                       lli1(false), //XXX static (check export)
-                       lli1(true), // defined in compilation unit
-                       lli32(DW_VIRTUALITY_none), // virtual-ness
-                       lli32(0i), //index into virt func
-                       /*llnull()*/ lli32(0), // base type with vtbl
-                       lli32(256), // flags
-                       lli1(cx.sess.opts.optimize != session::No),
-                       fcx.llfn
-                       //list of template params
-                       //func decl descriptor
-                       //list of func vars
-                      ];
-    let val = llmdnode(fn_metadata);
-    add_named_metadata(cx, ~"llvm.dbg.sp", val);
-    let mdval = @Metadata {
-        node: val,
-        data: SubProgramMetadata {
-            id: id
-        }
-    };
-    update_cache(cache, SubprogramTag, subprogram_metadata(mdval));
 
-    return mdval;
+    let fn_ty = unsafe {
+        llvm::DIBuilder_createSubroutineType(get_builder(cx),
+            file_md, create_DIArray(get_builder(cx), [ret_ty_md]))
+        };
+
+    let fn_md =
+        do as_c_str(cx.sess.str_of(ident)) |name| {
+        do as_c_str(cx.sess.str_of(ident)) |linkage| { unsafe {
+            llvm::LLVMDIBuilderCreateFunction(
+                dcx.builder,
+                file_md,
+                name, linkage,
+                file_md, loc.line as c_uint,
+                fn_ty, false, true,
+                loc.line as c_uint,
+                FlagPrototyped as c_uint,
+                cx.sess.opts.optimize != session::No,
+                fcx.llfn, ptr::null(), ptr::null())
+            }}};
+
+    dbg_cx.created_functions.insert(id, fn_md);
+    return fn_md;
 }
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index ba87624e2dd..315e7c4bcb1 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -560,3 +560,204 @@ extern "C" bool LLVMRustStartMultithreading() {
     assert(lock.release());
     return ret;
 }
+
+
+typedef DIBuilder* DIBuilderRef;
+
+template<typename DIT>
+DIT unwrapDI(LLVMValueRef ref) { return DIT(ref ? unwrap<MDNode>(ref) : NULL); }
+
+extern "C" DIBuilderRef DIBuilder_new(LLVMModuleRef M) {
+    return new DIBuilder(*unwrap(M));
+}
+
+extern "C" void DIBuilder_delete(DIBuilderRef Builder) {
+    delete Builder;
+}
+
+extern "C" void DIBuilder_finalize(DIBuilderRef Builder) {
+    Builder->finalize();
+}
+
+extern "C" void DIBuilder_createCompileUnit(
+    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);
+}
+
+extern "C" LLVMValueRef DIBuilder_createFile(
+    DIBuilderRef Builder,
+    const char* Filename,
+    const char* Directory) {
+    return wrap(Builder->createFile(Filename, Directory));
+}
+
+extern "C" LLVMValueRef DIBuilder_createSubroutineType(
+    DIBuilderRef Builder,
+    LLVMValueRef File, 
+    LLVMValueRef ParameterTypes) {
+    return wrap(Builder->createSubroutineType(
+        unwrapDI<DIFile>(File), 
+        unwrapDI<DIArray>(ParameterTypes)));
+}
+
+extern "C" LLVMValueRef DIBuilder_createFunction(
+    DIBuilderRef Builder,
+    LLVMValueRef Scope, 
+    const char* Name,
+    const char* LinkageName,
+    LLVMValueRef File,  
+    unsigned LineNo,
+    LLVMValueRef Ty, 
+    bool isLocalToUnit,
+    bool isDefinition,
+    unsigned ScopeLine,
+    unsigned Flags,
+    bool isOptimized,
+    LLVMValueRef Fn,
+    LLVMValueRef TParam,
+    LLVMValueRef Decl) {
+    return wrap(Builder->createFunction(
+        unwrapDI<DIScope>(Scope), Name, LinkageName, 
+        unwrapDI<DIFile>(File), LineNo, 
+        unwrapDI<DIType>(Ty), isLocalToUnit, isDefinition, ScopeLine, 
+        Flags, isOptimized,
+        unwrap<Function>(Fn), 
+        unwrapDI<MDNode*>(TParam),
+        unwrapDI<MDNode*>(Decl)));
+}
+
+extern "C" LLVMValueRef DIBuilder_createBasicType(
+    DIBuilderRef Builder,
+    const char* Name,
+    uint64_t SizeInBits,
+    uint64_t AlignInBits,
+    unsigned Encoding) {
+    return wrap(Builder->createBasicType(
+        Name, SizeInBits, 
+        AlignInBits, Encoding));
+}
+    
+extern "C" LLVMValueRef DIBuilder_createPointerType(
+    DIBuilderRef Builder,
+    LLVMValueRef PointeeTy,
+    uint64_t SizeInBits,
+    uint64_t AlignInBits,
+    const char* Name) {
+    return wrap(Builder->createPointerType(
+        unwrapDI<DIType>(PointeeTy), SizeInBits, AlignInBits, Name));
+}
+
+extern "C" LLVMValueRef DIBuilder_createStructType(
+    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(
+        unwrapDI<DIDescriptor>(Scope), Name, 
+        unwrapDI<DIFile>(File), LineNumber, 
+        SizeInBits, AlignInBits, Flags, 
+        unwrapDI<DIType>(DerivedFrom), 
+        unwrapDI<DIArray>(Elements), RunTimeLang, 
+        unwrapDI<MDNode*>(VTableHolder)));
+}
+
+extern "C" LLVMValueRef DIBuilder_createMemberType(
+    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(
+        unwrapDI<DIDescriptor>(Scope), Name, 
+        unwrapDI<DIFile>(File), LineNo,
+        SizeInBits, AlignInBits, OffsetInBits, Flags, 
+        unwrapDI<DIType>(Ty)));
+}
+    
+extern "C" LLVMValueRef DIBuilder_createLexicalBlock(
+    DIBuilderRef Builder,
+    LLVMValueRef Scope,
+    LLVMValueRef File,
+    unsigned Line,
+    unsigned Col) {
+    return wrap(Builder->createLexicalBlock(
+        unwrapDI<DIDescriptor>(Scope), 
+        unwrapDI<DIFile>(File), Line, Col));
+}
+    
+extern "C" LLVMValueRef DIBuilder_createLocalVariable(
+    DIBuilderRef Builder,
+    unsigned Tag,
+    LLVMValueRef Scope,
+    const char* Name,
+    LLVMValueRef File,
+    unsigned LineNo,
+    LLVMValueRef Ty,
+    bool AlwaysPreserve,
+    unsigned Flags,
+    unsigned ArgNo) {
+    return wrap(Builder->createLocalVariable(Tag, 
+        unwrapDI<DIDescriptor>(Scope), Name, 
+        unwrapDI<DIFile>(File), 
+        LineNo, 
+        unwrapDI<DIType>(Ty), AlwaysPreserve, Flags, ArgNo));
+}
+
+extern "C" LLVMValueRef DIBuilder_createVectorType(
+    DIBuilderRef Builder,
+    uint64_t Size,  
+    uint64_t AlignInBits,  
+    LLVMValueRef Ty, 
+    LLVMValueRef Subscripts) {
+    return wrap(Builder->createVectorType(Size, AlignInBits,
+        unwrapDI<DIType>(Ty), 
+        unwrapDI<DIArray>(Subscripts)));
+}
+
+extern "C" LLVMValueRef DIBuilder_getOrCreateSubrange(
+    DIBuilderRef Builder, 
+    int64_t Lo, 
+    int64_t Count) {
+    return wrap(Builder->getOrCreateSubrange(Lo, Count));
+}
+
+extern "C" LLVMValueRef DIBuilder_getOrCreateArray(
+    DIBuilderRef Builder,
+    LLVMValueRef* Ptr, 
+    unsigned Count) {
+    return wrap(Builder->getOrCreateArray(
+        ArrayRef<Value*>(reinterpret_cast<Value**>(Ptr), Count)));
+}
+
+extern "C" LLVMValueRef DIBuilder_insertDeclare(
+    DIBuilderRef Builder,
+    LLVMValueRef Val,
+    LLVMValueRef VarInfo,
+    LLVMValueRef InsertBefore) {
+    return wrap(Builder->insertDeclare(
+        unwrap(Val), 
+        unwrapDI<DIVariable>(VarInfo), 
+        unwrap<Instruction>(InsertBefore)));
+}
diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in
index f5397165781..71d574aecbe 100644
--- a/src/rustllvm/rustllvm.def.in
+++ b/src/rustllvm/rustllvm.def.in
@@ -588,3 +588,20 @@ LLVMInlineAsm
 LLVMInitializePasses
 LLVMAddPass
 LLVMCreatePass
+DIBuilder_new
+DIBuilder_delete
+DIBuilder_finalize
+DIBuilder_createCompileUnit
+DIBuilder_createLocalVariable
+DIBuilder_createFunction
+DIBuilder_createFile
+DIBuilder_createLexicalBlock
+DIBuilder_createBasicType
+DIBuilder_createPointerType
+DIBuilder_createMemberType
+DIBuilder_createStructType
+DIBuilder_getOrCreateSubrange
+DIBuilder_createVectorType
+DIBuilder_createSubroutineType
+DIBuilder_getOrCreateArray
+DIBuilder_insertDeclare
diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h
index 6f11202800c..d4202abd285 100644
--- a/src/rustllvm/rustllvm.h
+++ b/src/rustllvm/rustllvm.h
@@ -43,6 +43,8 @@
 #include "llvm/Transforms/IPO.h"
 #include "llvm/Transforms/Instrumentation.h"
 #include "llvm/Transforms/Vectorize.h"
+#include "llvm/DebugInfo.h"
+#include "llvm/DIBuilder.h"
 #include "llvm-c/Core.h"
 #include "llvm-c/BitReader.h"
 #include "llvm-c/ExecutionEngine.h"