about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/lib/llvm.rs39
-rw-r--r--src/librustc/metadata/csearch.rs2
-rw-r--r--src/librustc/metadata/decoder.rs19
-rw-r--r--src/librustc/middle/trans/adt.rs2
-rw-r--r--src/librustc/middle/trans/base.rs10
-rw-r--r--src/librustc/middle/trans/debuginfo.rs1316
-rw-r--r--src/librustc/middle/trans/machine.rs6
-rw-r--r--src/librustc/middle/ty.rs141
-rw-r--r--src/librustc/middle/typeck/check/mod.rs112
-rw-r--r--src/rustllvm/RustWrapper.cpp138
-rw-r--r--src/rustllvm/rustllvm.def.in3
-rw-r--r--src/test/debug-info/borrowed-basic.rs (renamed from src/test/debug-info/reference-to-basic.rs)35
-rw-r--r--src/test/debug-info/borrowed-c-style-enum.rs42
-rw-r--r--src/test/debug-info/borrowed-enum.rs62
-rw-r--r--src/test/debug-info/borrowed-managed-basic.rs (renamed from src/test/debug-info/reference-to-managed-basic.rs)30
-rw-r--r--src/test/debug-info/borrowed-struct.rs (renamed from src/test/debug-info/reference-to-struct.rs)23
-rw-r--r--src/test/debug-info/borrowed-tuple.rs (renamed from src/test/debug-info/reference-to-tuple.rs)13
-rw-r--r--src/test/debug-info/borrowed-unique-basic.rs (renamed from src/test/debug-info/reference-to-unique-basic.rs)33
-rw-r--r--src/test/debug-info/box.rs10
-rw-r--r--src/test/debug-info/boxed-struct.rs59
-rw-r--r--src/test/debug-info/boxed-vec.rs36
-rw-r--r--src/test/debug-info/c-style-enum-in-composite.rs119
-rw-r--r--src/test/debug-info/c-style-enum.rs70
-rw-r--r--src/test/debug-info/destructured-local.rs5
-rw-r--r--src/test/debug-info/evec-in-struct.rs88
-rw-r--r--src/test/debug-info/function-arguments.rs3
-rw-r--r--src/test/debug-info/managed-enum.rs63
-rw-r--r--src/test/debug-info/managed-pointer-within-unique-vec.rs37
-rw-r--r--src/test/debug-info/managed-pointer-within-unique.rs47
-rw-r--r--src/test/debug-info/nil-enum.rs40
-rw-r--r--src/test/debug-info/option-like-enum.rs71
-rw-r--r--src/test/debug-info/packed-struct-with-destructor.rs219
-rw-r--r--src/test/debug-info/packed-struct.rs104
-rw-r--r--src/test/debug-info/simple-tuple.rs14
-rw-r--r--src/test/debug-info/struct-in-enum.rs69
-rw-r--r--src/test/debug-info/struct-style-enum.rs73
-rw-r--r--src/test/debug-info/struct-with-destructor.rs49
-rw-r--r--src/test/debug-info/tuple-in-tuple.rs14
-rw-r--r--src/test/debug-info/tuple-style-enum.rs73
-rw-r--r--src/test/debug-info/unique-enum.rs63
-rw-r--r--src/test/debug-info/vec-slices.rs72
-rw-r--r--src/test/debug-info/vec.rs18
-rw-r--r--src/test/run-pass/issue-7712.rs27
43 files changed, 2728 insertions, 741 deletions
diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs
index aeb2017c9d6..7acd9545efd 100644
--- a/src/librustc/lib/llvm.rs
+++ b/src/librustc/lib/llvm.rs
@@ -1635,6 +1635,14 @@ pub mod llvm {
         #[fast_ffi]
         pub unsafe fn LLVMABIAlignmentOfType(TD: TargetDataRef,
                                   Ty: TypeRef) -> c_uint;
+
+        /** Computes the byte offset of the indexed struct element for a target. */
+        #[fast_ffi]
+        pub unsafe fn LLVMOffsetOfElement(TD: TargetDataRef,
+                                          StructTy: TypeRef,
+                                          Element: c_uint)
+                                       -> c_ulonglong;
+
         /**
          * Returns the minimum alignment of a type when part of a call frame.
          */
@@ -2089,6 +2097,37 @@ pub mod llvm {
             Val: ValueRef,
             VarInfo: DIVariable,
             InsertBefore: ValueRef) -> ValueRef;
+
+        #[fast_ffi]
+        pub unsafe fn LLVMDIBuilderCreateEnumerator(
+            Builder: DIBuilderRef,
+            Name: *c_char,
+            Val: c_ulonglong) -> ValueRef;
+
+        #[fast_ffi]
+        pub unsafe fn LLVMDIBuilderCreateEnumerationType(
+            Builder: DIBuilderRef,
+            Scope: ValueRef,
+            Name: *c_char,
+            File: ValueRef,
+            LineNumber: c_uint,
+            SizeInBits: c_ulonglong,
+            AlignInBits: c_ulonglong,
+            Elements: ValueRef,
+            ClassType: ValueRef) -> ValueRef;
+
+        #[fast_ffi]
+        pub unsafe fn LLVMDIBuilderCreateUnionType(
+            Builder: DIBuilderRef,
+            Scope: ValueRef,
+            Name: *c_char,
+            File: ValueRef,
+            LineNumber: c_uint,
+            SizeInBits: c_ulonglong,
+            AlignInBits: c_ulonglong,
+            Flags: c_uint ,
+            Elements: ValueRef,
+            RunTimeLang: c_uint) -> ValueRef;
     }
 }
 
diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs
index 993649492a4..6fd0ca06474 100644
--- a/src/librustc/metadata/csearch.rs
+++ b/src/librustc/metadata/csearch.rs
@@ -90,7 +90,7 @@ pub fn maybe_get_item_ast(tcx: ty::ctxt, def: ast::def_id,
 }
 
 pub fn get_enum_variants(tcx: ty::ctxt, def: ast::def_id)
-                      -> ~[ty::VariantInfo] {
+                      -> ~[@ty::VariantInfo] {
     let cstore = tcx.cstore;
     let cdata = cstore::get_crate_data(cstore, def.crate);
     return decoder::get_enum_variants(cstore.intr, cdata, def.node, tcx)
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index a77c6c6ab52..15ffccfe70d 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -737,11 +737,11 @@ pub fn maybe_get_item_ast(cdata: cmd, tcx: ty::ctxt,
 }
 
 pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id,
-                     tcx: ty::ctxt) -> ~[ty::VariantInfo] {
+                     tcx: ty::ctxt) -> ~[@ty::VariantInfo] {
     let data = cdata.data;
     let items = reader::get_doc(reader::Doc(data), tag_items);
     let item = find_item(id, items);
-    let mut infos: ~[ty::VariantInfo] = ~[];
+    let mut infos: ~[@ty::VariantInfo] = ~[];
     let variant_ids = enum_variant_ids(item, cdata);
     let mut disr_val = 0;
     for variant_ids.iter().advance |did| {
@@ -757,11 +757,16 @@ pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id,
           Some(val) => { disr_val = val; }
           _         => { /* empty */ }
         }
-        infos.push(@ty::VariantInfo_{args: arg_tys,
-                       ctor_ty: ctor_ty, name: name,
-                  // I'm not even sure if we encode visibility
-                  // for variants -- TEST -- tjc
-                  id: *did, disr_val: disr_val, vis: ast::inherited});
+        infos.push(@ty::VariantInfo{
+            args: arg_tys,
+            arg_names: None,
+            ctor_ty: ctor_ty,
+            name: name,
+            // I'm not even sure if we encode visibility
+            // for variants -- TEST -- tjc
+            id: *did,
+            disr_val: disr_val,
+            vis: ast::inherited});
         disr_val += 1;
     }
     return infos;
diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs
index 821242d64c9..fd38ec39bb1 100644
--- a/src/librustc/middle/trans/adt.rs
+++ b/src/librustc/middle/trans/adt.rs
@@ -94,7 +94,7 @@ pub enum Repr {
 }
 
 /// For structs, and struct-like parts of anything fancier.
-struct Struct {
+pub struct Struct {
     size: u64,
     align: u64,
     packed: bool,
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 6741637ae9a..cd07453a60b 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -670,7 +670,7 @@ pub fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
     let _icx = push_ctxt("iter_structural_ty");
 
     fn iter_variant(cx: block, repr: &adt::Repr, av: ValueRef,
-                    variant: ty::VariantInfo,
+                    variant: @ty::VariantInfo,
                     tps: &[ty::t], f: val_and_ty_fn) -> block {
         let _icx = push_ctxt("iter_variant");
         let tcx = cx.tcx();
@@ -1141,7 +1141,7 @@ pub fn trans_stmt(cx: block, s: &ast::stmt) -> block {
                     bcx = init_local(bcx, *local);
                     if cx.sess().opts.extra_debuginfo
                         && fcx_has_nonzero_span(bcx.fcx) {
-                        debuginfo::create_local_var(bcx, *local);
+                        debuginfo::create_local_var_metadata(bcx, *local);
                     }
                 }
                 ast::decl_item(i) => trans_item(cx.fcx.ccx, i)
@@ -1773,7 +1773,7 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
         bcx = _match::store_arg(bcx, args[arg_n].pat, llarg);
 
         if fcx.ccx.sess.opts.extra_debuginfo && fcx_has_nonzero_span(fcx) {
-            debuginfo::create_arg(bcx, &args[arg_n], args[arg_n].ty.span);
+            debuginfo::create_argument_metadata(bcx, &args[arg_n], args[arg_n].ty.span);
         }
     }
 
@@ -1947,7 +1947,7 @@ pub fn trans_fn(ccx: @mut CrateContext,
                   |fcx| {
                       if ccx.sess.opts.extra_debuginfo
                           && fcx_has_nonzero_span(fcx) {
-                          debuginfo::create_function(fcx);
+                          debuginfo::create_function_metadata(fcx);
                       }
                   },
                   |_bcx| { });
@@ -2109,7 +2109,7 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
 }
 
 pub fn trans_enum_def(ccx: @mut CrateContext, enum_definition: &ast::enum_def,
-                      id: ast::node_id, vi: @~[ty::VariantInfo],
+                      id: ast::node_id, vi: @~[@ty::VariantInfo],
                       i: &mut uint) {
     for enum_definition.variants.iter().advance |variant| {
         let disr_val = vi[*i].disr_val;
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index 00b59d187bf..0e75e4e85c2 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -27,11 +27,18 @@ where possible. This will hopefully ease the adaption of this module to future L
 
 The public API of the module is a set of functions that will insert the correct metadata into the
 LLVM IR when called with the right parameters. The module is thus driven from an outside client with
-functions like `debuginfo::create_local_var(bcx: block, local: @ast::local)`.
+functions like `debuginfo::local_var_metadata(bcx: block, local: &ast::local)`.
 
-Internally the module will try to reuse already created metadata by utilizing a cache. All private
-state used by the module is stored within a DebugContext struct, which in turn is contained in the
-CrateContext.
+Internally the module will try to reuse already created metadata by utilizing a cache. The way to
+get a shared metadata node when needed is thus to just call the corresponding function in this
+module:
+
+    let file_metadata = file_metadata(crate_context, path);
+
+The function will take care of probing the cache for an existing node for that exact file path.
+
+All private state used by the module is stored within a DebugContext struct, which in turn is
+contained in the CrateContext.
 
 
 This file consists of three conceptual sections:
@@ -44,31 +51,29 @@ This file consists of three conceptual sections:
 
 use driver::session;
 use lib::llvm::llvm;
-use lib::llvm::{ValueRef, ModuleRef, ContextRef};
+use lib::llvm::{ModuleRef, ContextRef};
 use lib::llvm::debuginfo::*;
 use middle::trans::common::*;
 use middle::trans::machine;
 use middle::trans::type_of;
+use middle::trans::type_::Type;
+use middle::trans::adt;
 use middle::trans;
 use middle::ty;
 use util::ppaux::ty_to_str;
 
 use std::hashmap::HashMap;
-use std::libc;
-use std::libc::{c_uint, c_ulonglong};
-use std::cmp;
+use std::libc::{c_uint, c_ulonglong, c_longlong};
 use std::ptr;
 use std::str::as_c_str;
-use std::sys;
 use std::vec;
 use syntax::codemap::span;
 use syntax::{ast, codemap, ast_util, ast_map};
-use syntax::parse::token;
 
 static DW_LANG_RUST: int = 0x9000;
 
-static AutoVariableTag: int = 256;
-static ArgVariableTag: int = 257;
+static DW_TAG_auto_variable: int = 0x100;
+static DW_TAG_arg_variable: int = 0x101;
 
 static DW_ATE_boolean: int = 0x02;
 static DW_ATE_float: int = 0x04;
@@ -118,7 +123,7 @@ impl DebugContext {
 /// Create any deferred debug metadata nodes
 pub fn finalize(cx: @mut CrateContext) {
     debug!("finalize");
-    create_compile_unit(cx);
+    compile_unit_metadata(cx);
     unsafe {
         llvm::LLVMDIBuilderFinalize(DIB(cx));
         llvm::LLVMDIBuilderDispose(DIB(cx));
@@ -129,7 +134,7 @@ pub fn finalize(cx: @mut CrateContext) {
 ///
 /// Adds the created metadata nodes directly to the crate's IR.
 /// The return value should be ignored if called from outside of the debuginfo module.
-pub fn create_local_var(bcx: block, local: @ast::local) -> DIVariable {
+pub fn create_local_var_metadata(bcx: block, local: @ast::local) -> DIVariable {
     let cx = bcx.ccx();
 
     let ident = match local.node.pat.node {
@@ -140,24 +145,35 @@ pub fn create_local_var(bcx: block, local: @ast::local) -> DIVariable {
         return ptr::null();
       }
     };
+
     let name: &str = cx.sess.str_of(ident);
-    debug!("create_local_var: %s", name);
+    debug!("create_local_var_metadata: %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, loc.file.name);
+    let type_metadata = type_metadata(cx, ty, local.node.ty.span);
+    let file_metadata = file_metadata(cx, loc.file.name);
+
     let context = match bcx.parent {
-        None => create_function(bcx.fcx),
-        Some(_) => create_block(bcx)
+        None => create_function_metadata(bcx.fcx),
+        Some(_) => lexical_block_metadata(bcx)
     };
 
-    let var_md = do as_c_str(name) |name| { unsafe {
-        llvm::LLVMDIBuilderCreateLocalVariable(
-            DIB(cx), AutoVariableTag as u32,
-            context, name, filemd,
-            loc.line as c_uint, tymd, false, 0, 0)
-        }};
+    let var_metadata = do as_c_str(name) |name| {
+        unsafe {
+            llvm::LLVMDIBuilderCreateLocalVariable(
+                DIB(cx),
+                DW_TAG_auto_variable as u32,
+                context,
+                name,
+                file_metadata,
+                loc.line as c_uint,
+                type_metadata,
+                false,
+                0,
+                0)
+        }
+    };
 
     // 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) {
@@ -169,24 +185,25 @@ pub fn create_local_var(bcx: block, local: @ast::local) -> DIVariable {
         }
     };
 
-    set_debug_location(cx, create_block(bcx), loc.line, loc.col.to_uint());
+    set_debug_location(cx, lexical_block_metadata(bcx), loc.line, loc.col.to_uint());
     unsafe {
-        let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(DIB(cx), llptr, var_md, bcx.llbb);
+        let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(DIB(cx), llptr, var_metadata, bcx.llbb);
         llvm::LLVMSetInstDebugLocation(trans::build::B(bcx), instr);
     }
 
-    return var_md;
+    return var_metadata;
 }
 
 /// Creates debug information for the given function argument.
 ///
 /// Adds the created metadata nodes directly to the crate's IR.
 /// The return value should be ignored if called from outside of the debuginfo module.
-pub fn create_arg(bcx: block, arg: &ast::arg, span: span) -> Option<DIVariable> {
-    debug!("create_arg");
+pub fn create_argument_metadata(bcx: block, arg: &ast::arg, span: span) -> Option<DIVariable> {
+    debug!("create_argument_metadata");
     if true {
-        // XXX create_arg disabled for now because "node_id_type(bcx, arg.id)" below blows
-        // up: "error: internal compiler error: node_id_to_type: no type for node `arg (id=10)`"
+        // XXX create_argument_metadata disabled for now because "node_id_type(bcx, arg.id)" below
+        // blows up:
+        // "error: internal compiler error: node_id_to_type: no type for node `arg (id=10)`"
         return None;
     }
 
@@ -199,38 +216,40 @@ pub fn create_arg(bcx: block, arg: &ast::arg, span: span) -> Option<DIVariable>
     }
 
     let ty = node_id_type(bcx, arg.id);
-    let tymd = create_ty(cx, ty, arg.ty.span);
-    let filemd = create_file(cx, loc.file.name);
-    let context = create_function(fcx);
+    let type_metadata = type_metadata(cx, ty, arg.ty.span);
+    let file_metadata = file_metadata(cx, loc.file.name);
+    let context = create_function_metadata(fcx);
 
     match arg.pat.node {
         ast::pat_ident(_, ref path, _) => {
             // XXX: This is wrong; it should work for multiple bindings.
             let ident = path.idents.last();
             let name: &str = cx.sess.str_of(*ident);
-            let mdnode = do as_c_str(name) |name| { unsafe {
-                llvm::LLVMDIBuilderCreateLocalVariable(
-                    DIB(cx),
-                    ArgVariableTag as u32,
-                    context,
-                    name,
-                    filemd,
-                    loc.line as c_uint,
-                    tymd,
-                    false,
-                    0,
-                    0)
+            let var_metadata = do as_c_str(name) |name| {
+                unsafe {
+                    llvm::LLVMDIBuilderCreateLocalVariable(
+                        DIB(cx),
+                        DW_TAG_arg_variable as u32,
+                        context,
+                        name,
+                        file_metadata,
+                        loc.line as c_uint,
+                        type_metadata,
+                        false,
+                        0,
+                        0)
                     // XXX need to pass in a real argument number
-            }};
+                }
+            };
 
             let llptr = fcx.llargs.get_copy(&arg.id);
-            set_debug_location(cx, create_block(bcx), loc.line, loc.col.to_uint());
+            set_debug_location(cx, lexical_block_metadata(bcx), loc.line, loc.col.to_uint());
             unsafe {
                 let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
-                        DIB(cx), llptr, mdnode, bcx.llbb);
+                        DIB(cx), llptr, var_metadata, bcx.llbb);
                 llvm::LLVMSetInstDebugLocation(trans::build::B(bcx), instr);
             }
-            return Some(mdnode);
+            return Some(var_metadata);
         }
         _ => {
             return None;
@@ -247,59 +266,81 @@ pub fn update_source_pos(bcx: block, span: span) {
     }
     debug!("update_source_pos: %s", bcx.sess().codemap.span_to_str(span));
     let loc = span_start(bcx.ccx(), span);
-    set_debug_location(bcx.ccx(), create_block(bcx), loc.line, loc.col.to_uint())
+    set_debug_location(bcx.ccx(), lexical_block_metadata(bcx), loc.line, loc.col.to_uint())
 }
 
 /// Creates debug information for the given function.
 ///
 /// Adds the created metadata nodes directly to the crate's IR.
 /// The return value should be ignored if called from outside of the debuginfo module.
-pub fn create_function(fcx: fn_ctxt) -> DISubprogram {
+pub fn create_function_metadata(fcx: fn_ctxt) -> DISubprogram {
     let cx = fcx.ccx;
     let fcx = &mut *fcx;
     let span = fcx.span.get();
 
     let fnitem = cx.tcx.items.get_copy(&fcx.id);
     let (ident, ret_ty, id) = match fnitem {
-      ast_map::node_item(ref item, _) => {
-        match item.node {
-          ast::item_fn(ast::fn_decl { output: ref ty, _}, _, _, _, _) => {
-            (item.ident, ty, item.id)
-          }
-          _ => fcx.ccx.sess.span_bug(item.span, "create_function: item bound to non-function")
+        ast_map::node_item(ref item, _) => {
+            match item.node {
+                ast::item_fn(ast::fn_decl { output: ref ty, _}, _, _, _, _) => {
+                    (item.ident, ty, item.id)
+                }
+                _ => fcx.ccx.sess.span_bug(item.span,
+                                           "create_function_metadata: item bound to non-function")
+            }
         }
-      }
-      ast_map::node_method(@ast::method { decl: ast::fn_decl { output: ref ty, _ },
-                           id: id, ident: ident, _}, _, _) => {
-          (ident, ty, id)
-      }
-      ast_map::node_expr(ref expr) => {
-        match expr.node {
-          ast::expr_fn_block(ref decl, _) => {
-            let name = gensym_name("fn");
-            (name, &decl.output, expr.id)
-          }
-          _ => fcx.ccx.sess.span_bug(expr.span,
-                  "create_function: expected an expr_fn_block here")
+        ast_map::node_method(
+            @ast::method {
+                decl: ast::fn_decl { output: ref ty, _ },
+                id: id,
+                ident: ident,
+                _
+            },
+            _,
+            _) => {
+            (ident, ty, id)
         }
-      }
-      _ => fcx.ccx.sess.bug("create_function: unexpected sort of node")
+        ast_map::node_expr(ref expr) => {
+            match expr.node {
+                ast::expr_fn_block(ref decl, _) => {
+                    let name = gensym_name("fn");
+                    (name, &decl.output, expr.id)
+                }
+                _ => fcx.ccx.sess.span_bug(expr.span,
+                        "create_function_metadata: expected an expr_fn_block here")
+            }
+        }
+        ast_map::node_trait_method(
+            @ast::provided(
+                @ast::method {
+                    decl: ast::fn_decl { output: ref ty, _ },
+                    id: id,
+                    ident: ident,
+                    _
+                }),
+            _,
+            _) => {
+            (ident, ty, id)
+        }
+        _ => fcx.ccx.sess.bug("create_function_metadata: unexpected sort of node")
     };
 
     match dbg_cx(cx).created_functions.find(&id) {
-        Some(fn_md) => return *fn_md,
+        Some(fn_metadata) => return *fn_metadata,
         None => ()
     }
 
-    debug!("create_function: %s, %s", cx.sess.str_of(ident), cx.sess.codemap.span_to_str(span));
+    debug!("create_function_metadata: %s, %s",
+           cx.sess.str_of(ident),
+           cx.sess.codemap.span_to_str(span));
 
     let loc = span_start(cx, span);
-    let file_md = create_file(cx, loc.file.name);
+    let file_metadata = file_metadata(cx, loc.file.name);
 
-    let ret_ty_md = if cx.sess.opts.extra_debuginfo {
+    let return_type_metadata = if cx.sess.opts.extra_debuginfo {
         match ret_ty.node {
           ast::ty_nil => ptr::null(),
-          _ => create_ty(cx, ty::node_id_to_type(cx.tcx, id), ret_ty.span)
+          _ => type_metadata(cx, ty::node_id_to_type(cx.tcx, id), ret_ty.span)
         }
     } else {
         ptr::null()
@@ -308,33 +349,35 @@ pub fn create_function(fcx: fn_ctxt) -> DISubprogram {
     let fn_ty = unsafe {
         llvm::LLVMDIBuilderCreateSubroutineType(
             DIB(cx),
-            file_md,
-            create_DIArray(DIB(cx), [ret_ty_md]))
+            file_metadata,
+            create_DIArray(DIB(cx), [return_type_metadata]))
     };
 
-    let fn_md =
+    let fn_metadata =
         do as_c_str(cx.sess.str_of(ident)) |name| {
-        do as_c_str(cx.sess.str_of(ident)) |linkage| { unsafe {
-            llvm::LLVMDIBuilderCreateFunction(
-                DIB(cx),
-                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())
-            }}};
+        do as_c_str(cx.sess.str_of(ident)) |linkage| {
+            unsafe {
+                llvm::LLVMDIBuilderCreateFunction(
+                    DIB(cx),
+                    file_metadata,
+                    name,
+                    linkage,
+                    file_metadata,
+                    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(cx).created_functions.insert(id, fn_md);
-    return fn_md;
+    dbg_cx(cx).created_functions.insert(id, fn_metadata);
+    return fn_metadata;
 }
 
 
@@ -350,11 +393,11 @@ fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
     };
 }
 
-fn create_compile_unit(cx: @mut CrateContext) {
+fn compile_unit_metadata(cx: @mut CrateContext) {
     let dcx = dbg_cx(cx);
     let crate_name: &str = dcx.crate_file;
 
-    debug!("create_compile_unit: %?", crate_name);
+    debug!("compile_unit_metadata: %?", crate_name);
 
     let work_dir = cx.sess.working_dir.to_str();
     let producer = fmt!("rustc version %s", env!("CFG_VERSION"));
@@ -363,21 +406,23 @@ fn create_compile_unit(cx: @mut CrateContext) {
     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::LLVMDIBuilderCreateCompileUnit(dcx.builder,
-            DW_LANG_RUST as c_uint, crate_name, work_dir, producer,
-            cx.sess.opts.optimize != session::No,
-            flags, 0, split_name);
-    }}}}}};
+    do as_c_str("") |split_name| {
+        unsafe {
+            llvm::LLVMDIBuilderCreateCompileUnit(dcx.builder,
+                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: &mut CrateContext, full_path: &str) -> DIFile {
+fn file_metadata(cx: &mut CrateContext, full_path: &str) -> DIFile {
     match dbg_cx(cx).created_files.find_equiv(&full_path) {
-        Some(file_md) => return *file_md,
+        Some(file_metadata) => return *file_metadata,
         None => ()
     }
 
-    debug!("create_file: %s", full_path);
+    debug!("file_metadata: %s", full_path);
 
     let work_dir = cx.sess.working_dir.to_str();
     let file_name =
@@ -387,68 +432,67 @@ fn create_file(cx: &mut CrateContext, full_path: &str) -> DIFile {
             full_path
         };
 
-    let file_md =
+    let file_metadata =
         do as_c_str(file_name) |file_name| {
-        do as_c_str(work_dir) |work_dir| { unsafe {
-            llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir)
-        }}};
+        do as_c_str(work_dir) |work_dir| {
+            unsafe {
+                llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir)
+            }
+        }};
 
-    dbg_cx(cx).created_files.insert(full_path.to_owned(), file_md);
-    return file_md;
+    dbg_cx(cx).created_files.insert(full_path.to_owned(), file_metadata);
+    return file_metadata;
 }
 
-
-
-fn create_block(bcx: block) -> DILexicalBlock {
-    let mut bcx = bcx;
+/// Get or create the lexical block metadata node for the given LLVM basic block.
+fn lexical_block_metadata(bcx: block) -> DILexicalBlock {
     let cx = bcx.ccx();
+    let mut bcx = bcx;
 
+    // Search up the tree of basic blocks until we find one that knows the containing lexical block.
     while bcx.node_info.is_none() {
         match bcx.parent {
-          Some(b) => bcx = b,
-          None => fail!()
+            Some(b) => bcx = b,
+            None => cx.sess.bug("debuginfo: Could not find lexical block for LLVM basic block.")
         }
     }
+
     let span = bcx.node_info.get().span;
     let id = bcx.node_info.get().id;
 
+    // Check whether we already have a cache entry for this node id
     match dbg_cx(cx).created_blocks.find(&id) {
         Some(block) => return *block,
         None => ()
     }
 
-    debug!("create_block: %s", bcx.sess().codemap.span_to_str(span));
+    debug!("lexical_block_metadata: %s", bcx.sess().codemap.span_to_str(span));
 
     let parent = match bcx.parent {
-        None => create_function(bcx.fcx),
-        Some(b) => create_block(b)
+        None => create_function_metadata(bcx.fcx),
+        Some(b) => lexical_block_metadata(b)
     };
-    let cx = bcx.ccx();
+
     let loc = span_start(cx, span);
-    let file_md = create_file(cx, loc.file.name);
+    let file_metadata = file_metadata(cx, loc.file.name);
 
-    let block_md = unsafe {
+    let lexical_block_metadata = unsafe {
         llvm::LLVMDIBuilderCreateLexicalBlock(
             DIB(cx),
-            parent, file_md,
-            loc.line as c_uint, loc.col.to_uint() as c_uint)
+            parent,
+            file_metadata,
+            loc.line as c_uint,
+            loc.col.to_uint() as c_uint)
     };
 
-    dbg_cx(cx).created_blocks.insert(id, block_md);
+    dbg_cx(cx).created_blocks.insert(id, lexical_block_metadata);
 
-    return block_md;
+    return lexical_block_metadata;
 }
 
+fn basic_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType {
 
-
-fn create_basic_type(cx: &mut CrateContext, t: ty::t, _span: span) -> DIType {
-    let ty_id = ty::type_id(t);
-    match dbg_cx(cx).created_types.find(&ty_id) {
-        Some(ty_md) => return *ty_md,
-        None => ()
-    }
-
-    debug!("create_basic_type: %?", ty::get(t));
+    debug!("basic_type_metadata: %?", ty::get(t));
 
     let (name, encoding) = match ty::get(t).sty {
         ty::ty_nil | ty::ty_bot => (~"uint", DW_ATE_unsigned),
@@ -473,424 +517,805 @@ fn create_basic_type(cx: &mut CrateContext, t: ty::t, _span: span) -> DIType {
             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::basic_type_metadata - t is invalid type")
     };
 
-    let (size, align) = size_and_align_of(cx, t);
-    let ty_md = do as_c_str(name) |name| { unsafe {
+    let llvm_type = type_of::type_of(cx, t);
+    let (size, align) = size_and_align_of(cx, llvm_type);
+    let ty_metadata = do as_c_str(name) |name| {
+        unsafe {
             llvm::LLVMDIBuilderCreateBasicType(
                 DIB(cx),
                 name,
                 bytes_to_bits(size),
                 bytes_to_bits(align),
                 encoding as c_uint)
-        }};
+        }
+    };
 
-    // One could think that this call is not necessary, as the create_ty() function will insert the
-    // type descriptor into the cache anyway. Mind, however, that create_basic_type() is also called
-    // directly from other functions (e.g. create_boxed_type()).
-    dbg_cx(cx).created_types.insert(ty_id, ty_md);
-    return ty_md;
+    return ty_metadata;
 }
 
-fn create_pointer_type(cx: &mut CrateContext, t: ty::t, _span: span, pointee: DIType) -> DIType {
-    let (size, align) = size_and_align_of(cx, t);
-    let name = ty_to_str(cx.tcx, t);
-    let ptr_md = do as_c_str(name) |name| { unsafe {
-        llvm::LLVMDIBuilderCreatePointerType(
-            DIB(cx),
-            pointee,
-            bytes_to_bits(size),
-            bytes_to_bits(align),
-            name)
-    }};
-    return ptr_md;
+fn pointer_type_metadata(cx: &mut CrateContext,
+                         pointer_type: ty::t,
+                         pointee_type_metadata: DIType)
+                      -> DIType {
+    let pointer_llvm_type = type_of::type_of(cx, pointer_type);
+    let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
+    let name = ty_to_str(cx.tcx, pointer_type);
+    let ptr_metadata = do as_c_str(name) |name| {
+        unsafe {
+            llvm::LLVMDIBuilderCreatePointerType(
+                DIB(cx),
+                pointee_type_metadata,
+                bytes_to_bits(pointer_size),
+                bytes_to_bits(pointer_align),
+                name)
+        }
+    };
+    return ptr_metadata;
 }
 
-struct StructContext {
-    builder: DIBuilderRef,
-    file: DIFile,
-    name: ~str,
-    line: uint,
-    members: ~[DIDerivedType],
-    total_size: uint,
-    align: uint
-}
-
-impl StructContext {
-    fn new(cx: &CrateContext, name: ~str, file: DIFile, line: uint) -> StructContext {
-        debug!("StructContext::create: %s", name);
-        return StructContext {
-            builder: DIB(cx),
-            file: file,
-            name: name,
-            line: line,
-            members: ~[],
-            total_size: 0,
-            align: 1
-        };
+fn struct_metadata(cx: &mut CrateContext,
+                   struct_type: ty::t,
+                   fields: ~[ty::field],
+                   span: span)
+                -> DICompositeType {
+    let struct_name = ty_to_str(cx.tcx, struct_type);
+    debug!("struct_metadata: %s", struct_name);
+
+    let struct_llvm_type = type_of::type_of(cx, struct_type);
+
+    let field_llvm_types = do fields.map |field| { type_of::type_of(cx, field.mt.ty) };
+    let field_names = do fields.map |field| { cx.sess.str_of(field.ident).to_owned() };
+    let field_types_metadata = do fields.map |field| {
+        type_metadata(cx, field.mt.ty, span)
+    };
+
+    return composite_type_metadata(
+        cx,
+        struct_llvm_type,
+        struct_name,
+        field_llvm_types,
+        field_names,
+        field_types_metadata,
+        span);
+}
+
+fn tuple_metadata(cx: &mut CrateContext,
+                  tuple_type: ty::t,
+                  component_types: &[ty::t],
+                  span: span)
+               -> DICompositeType {
+
+    let tuple_name = ty_to_str(cx.tcx, tuple_type);
+    let tuple_llvm_type = type_of::type_of(cx, tuple_type);
+
+    let component_names = do component_types.map |_| { ~"" };
+    let component_llvm_types = do component_types.map |it| { type_of::type_of(cx, *it) };
+    let component_types_metadata = do component_types.map |it| {
+        type_metadata(cx, *it, span)
+    };
+
+    return composite_type_metadata(
+        cx,
+        tuple_llvm_type,
+        tuple_name,
+        component_llvm_types,
+        component_names,
+        component_types_metadata,
+        span);
+}
+
+// The stage0 snapshot does not yet support the fixes from PR #7557, so there are two versions of
+// following function for now
+#[cfg(not(stage0))]
+fn enum_metadata(cx: &mut CrateContext,
+                 enum_type: ty::t,
+                 enum_def_id: ast::def_id,
+                 // _substs is only needed in the other version. Will go away with new snapshot.
+                 _substs: &ty::substs,
+                 span: span)
+              -> DIType {
+
+    let enum_name = ty_to_str(cx.tcx, enum_type);
+
+    // For empty enums there is an early exit. Just describe it as an empty struct with the
+    // appropriate type name
+    if ty::type_is_empty(cx.tcx, enum_type) {
+        return composite_type_metadata(cx, Type::nil(), enum_name, [], [], [], span);
     }
 
-    fn add_member(&mut self, name: &str, line: uint, size: uint, align: uint, ty: DIType) {
-        let offset = roundup(self.total_size, align);
+    // Prepare some data (llvm type, size, align, ...) about the discriminant. This data will be
+    // needed in all of the following cases.
+    let discriminant_llvm_type = Type::enum_discrim(cx);
+    let (discriminant_size, discriminant_align) = size_and_align_of(cx, discriminant_llvm_type);
 
-        debug!("StructContext(%s)::add_member: %s, size=%u, align=%u, offset=%u",
-                self.name, name, size, align, offset);
+    assert!(Type::enum_discrim(cx) == cx.int_type);
+    let discriminant_type_metadata = type_metadata(cx, ty::mk_int(), span);
 
-        let mem_t = do as_c_str(name) |name| { unsafe {
-            llvm::LLVMDIBuilderCreateMemberType(
-                self.builder,
-                self.file,
-                name,
-                self.file,
-                line as c_uint,
-                bytes_to_bits(size),
-                bytes_to_bits(align),
-                bytes_to_bits(offset),
-                0,
-                ty)
+    let variants: &[@ty::VariantInfo] = *ty::enum_variants(cx.tcx, enum_def_id);
+
+    let enumerators_metadata: ~[DIDescriptor] = variants
+        .iter()
+        .transform(|v| {
+            let name: &str = cx.sess.str_of(v.name);
+            let discriminant_value = v.disr_val as c_ulonglong;
+
+            do name.as_c_str |name| {
+                unsafe {
+                    llvm::LLVMDIBuilderCreateEnumerator(
+                        DIB(cx),
+                        name,
+                        discriminant_value)
+                }
+            }
+        })
+        .collect();
+
+    let loc = span_start(cx, span);
+    let file_metadata = file_metadata(cx, loc.file.name);
+
+    let discriminant_type_metadata = do enum_name.as_c_str |enum_name| {
+        unsafe {
+            llvm::LLVMDIBuilderCreateEnumerationType(
+                DIB(cx),
+                file_metadata,
+                enum_name,
+                file_metadata,
+                loc.line as c_uint,
+                bytes_to_bits(discriminant_size),
+                bytes_to_bits(discriminant_align),
+                create_DIArray(DIB(cx), enumerators_metadata),
+                discriminant_type_metadata)
+        }
+    };
+
+    let type_rep = adt::represent_type(cx, enum_type);
+
+    match *type_rep {
+        adt::CEnum(*) => {
+            return discriminant_type_metadata;
+        }
+        adt::Univariant(ref struct_def, _) => {
+            assert!(variants.len() == 1);
+            return adt_struct_metadata(cx, struct_def, variants[0], None, span);
+        }
+        adt::General(ref struct_defs) => {
+            let variants_member_metadata: ~[DIDescriptor] = do struct_defs
+                .iter()
+                .enumerate()
+                .transform |(i, struct_def)| {
+                    let variant_type_metadata = adt_struct_metadata(
+                        cx,
+                        struct_def,
+                        variants[i],
+                        Some(discriminant_type_metadata),
+                        span);
+
+                    do "".as_c_str |name| {
+                        unsafe {
+                            llvm::LLVMDIBuilderCreateMemberType(
+                                DIB(cx),
+                                file_metadata,
+                                name,
+                                file_metadata,
+                                loc.line as c_uint,
+                                bytes_to_bits(struct_def.size as uint),
+                                bytes_to_bits(struct_def.align as uint),
+                                bytes_to_bits(0),
+                                0,
+                                variant_type_metadata)
+                        }
+                    }
+            }.collect();
+
+            let enum_llvm_type = type_of::type_of(cx, enum_type);
+            let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
+
+            return do enum_name.as_c_str |enum_name| {
+                unsafe {
+                    llvm::LLVMDIBuilderCreateUnionType(
+                    DIB(cx),
+                    file_metadata,
+                    enum_name,
+                    file_metadata,
+                    loc.line as c_uint,
+                    bytes_to_bits(enum_type_size),
+                    bytes_to_bits(enum_type_align),
+                    0, // Flags
+                    create_DIArray(DIB(cx), variants_member_metadata),
+                    0) // RuntimeLang
             }};
-        self.members.push(mem_t);
-        self.total_size = offset + size;
-        // struct alignment is the max alignment of its' members
-        self.align = cmp::max(self.align, align);
+        }
+        adt::NullablePointer { nonnull: ref struct_def, nndiscr, _ } => {
+            return adt_struct_metadata(cx, struct_def, variants[nndiscr], None, span);
+        }
     }
 
-    fn get_total_size_with_alignment(&self) -> uint {
-        roundup(self.total_size, self.align)
-    }
+    fn adt_struct_metadata(cx: &mut CrateContext,
+                                  struct_def: &adt::Struct,
+                                  variant_info: &ty::VariantInfo,
+                                  discriminant_type_metadata: Option<DIType>,
+                                  span: span)
+                               -> DICompositeType
+    {
+        let arg_llvm_types: ~[Type] = do struct_def.fields.map |&ty| { type_of::type_of(cx, ty) };
+        let arg_metadata: ~[DIType] = do struct_def.fields.iter().enumerate()
+            .transform |(i, &ty)| {
+                match discriminant_type_metadata {
+                    Some(metadata) if i == 0 => metadata,
+                    _                        => type_metadata(cx, ty, span)
+                }
+        }.collect();
 
-    fn finalize(&self) -> DICompositeType {
-        debug!("StructContext(%s)::finalize: total_size=%u, align=%u",
-                self.name, self.total_size, self.align);
-        let members_md = create_DIArray(self.builder, self.members);
-
-        // The size of the struct/tuple must be rounded to the next multiple of its alignment.
-        // Otherwise gdb has trouble reading the struct correctly when it is embedded into another
-        // data structure. This is also the value `sizeof` in C would give.
-        let actual_total_size = self.get_total_size_with_alignment();
-
-        let struct_md =
-            do as_c_str(self.name) |name| { unsafe {
-                llvm::LLVMDIBuilderCreateStructType(
-                    self.builder,
-                    self.file,
-                    name,
-                    self.file,
-                    self.line as c_uint,
-                    bytes_to_bits(actual_total_size),
-                    bytes_to_bits(self.align),
-                    0,
-                    ptr::null(),
-                    members_md,
-                    0,
-                    ptr::null())
-            }};
-        return struct_md;
+        let mut arg_names = match variant_info.arg_names {
+            Some(ref names) => do names.map |ident| { cx.sess.str_of(*ident).to_owned() },
+            None => do variant_info.args.map |_| { ~"" }
+        };
+
+        if discriminant_type_metadata.is_some() {
+            arg_names.insert(0, ~"");
+        }
+
+        let variant_llvm_type = Type::struct_(arg_llvm_types, struct_def.packed);
+        let variant_name: &str = cx.sess.str_of(variant_info.name);
+
+        return composite_type_metadata(
+            cx,
+            variant_llvm_type,
+            variant_name,
+            arg_llvm_types,
+            arg_names,
+            arg_metadata,
+            span);
     }
 }
 
-fn create_struct(cx: &mut CrateContext, struct_type: ty::t, fields: ~[ty::field], span: span)
-                -> DICompositeType {
-    debug!("create_struct: %?", ty::get(struct_type));
+#[cfg(stage0)]
+fn enum_metadata(cx: &mut CrateContext,
+                 enum_type: ty::t,
+                 enum_def_id: ast::def_id,
+                 substs: &ty::substs,
+                 span: span)
+              -> DIType {
+
+    let enum_name = ty_to_str(cx.tcx, enum_type);
+
+    // For empty enums there is an early exit. Just describe it as an empty struct with the
+    // appropriate type name
+    if ty::type_is_empty(cx.tcx, enum_type) {
+        return composite_type_metadata(cx, Type::nil(), enum_name, &[], &[], &[], span);
+    }
+
+    // Prepare some data (llvm type, size, align, ...) about the discriminant. This data will be
+    // needed in all of the following cases.
+    let discriminant_llvm_type = Type::enum_discrim(cx);
+    let (discriminant_size, discriminant_align) = size_and_align_of(cx, discriminant_llvm_type);
+
+    assert!(Type::enum_discrim(cx) == cx.int_type);
+    let discriminant_type_metadata = type_metadata(cx, ty::mk_int(), span);
+
+    let variants: &[@ty::VariantInfo] = *ty::enum_variants(cx.tcx, enum_def_id);
+
+    let enumerators_metadata: ~[DIDescriptor] = variants
+        .iter()
+        .transform(|v| {
+            let name: &str = cx.sess.str_of(v.name);
+            let discriminant_value = v.disr_val as c_ulonglong;
+
+            do name.as_c_str |name| {
+                unsafe {
+                    llvm::LLVMDIBuilderCreateEnumerator(
+                        DIB(cx),
+                        name,
+                        discriminant_value)
+                }
+            }
+        })
+        .collect();
 
     let loc = span_start(cx, span);
-    let file_md = create_file(cx, loc.file.name);
-
-    let mut scx = StructContext::new(cx, ty_to_str(cx.tcx, struct_type), file_md, loc.line);
-    for fields.iter().advance |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);
-        scx.add_member(cx.sess.str_of(field.ident), loc.line, size, align, ty_md);
+    let file_metadata = file_metadata(cx, loc.file.name);
+
+    let discriminant_type_metadata = do enum_name.as_c_str |enum_name| {
+        unsafe {
+            llvm::LLVMDIBuilderCreateEnumerationType(
+                DIB(cx),
+                file_metadata,
+                enum_name,
+                file_metadata,
+                loc.line as c_uint,
+                bytes_to_bits(discriminant_size),
+                bytes_to_bits(discriminant_align),
+                create_DIArray(DIB(cx), enumerators_metadata),
+                discriminant_type_metadata)
+        }
+    };
+
+    if ty::type_is_c_like_enum(cx.tcx, enum_type) {
+        return discriminant_type_metadata;
     }
-    return scx.finalize();
-}
 
-// returns (void* type as a ValueRef, size in bytes, align in bytes)
-fn voidptr(cx: &mut CrateContext) -> (DIDerivedType, uint, uint) {
-    let size = sys::size_of::<ValueRef>();
-    let align = sys::min_align_of::<ValueRef>();
-    let vp = do as_c_str("*void") |name| { unsafe {
-            llvm::LLVMDIBuilderCreatePointerType(
+    let is_univariant = variants.len() == 1;
+
+    let variants_metadata = do variants.map |&vi| {
+
+        let raw_types: &[ty::t] = vi.args;
+        let arg_types = do raw_types.map |&raw_type| { ty::subst(cx.tcx, substs, raw_type) };
+
+        let mut arg_llvm_types = do arg_types.map |&ty| { type_of::type_of(cx, ty) };
+        let mut arg_names = match vi.arg_names {
+            Some(ref names) => do names.map |ident| { cx.sess.str_of(*ident).to_owned() },
+            None => do arg_types.map |_| { ~"" }
+        };
+
+        let mut arg_metadata = do arg_types.map |&ty| { type_metadata(cx, ty, span) };
+
+        if !is_univariant {
+            arg_llvm_types.insert(0, discriminant_llvm_type);
+            arg_names.insert(0, ~"");
+            arg_metadata.insert(0, discriminant_type_metadata);
+        }
+
+        let variant_llvm_type = Type::struct_(arg_llvm_types, false);
+        let (variant_type_size, variant_type_align) = size_and_align_of(cx, variant_llvm_type);
+
+        let variant_type_metadata = composite_type_metadata(
+            cx,
+            variant_llvm_type,
+            &"",
+            arg_llvm_types,
+            arg_names,
+            arg_metadata,
+            span);
+
+        do "".as_c_str |name| {
+            unsafe {
+                llvm::LLVMDIBuilderCreateMemberType(
+                    DIB(cx),
+                    file_metadata,
+                    name,
+                    file_metadata,
+                    loc.line as c_uint,
+                    bytes_to_bits(variant_type_size),
+                    bytes_to_bits(variant_type_align),
+                    bytes_to_bits(0),
+                    0,
+                    variant_type_metadata)
+            }
+        }
+    };
+
+    let enum_llvm_type = type_of::type_of(cx, enum_type);
+    let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
+
+    return do enum_name.as_c_str |enum_name| {
+        unsafe {
+            llvm::LLVMDIBuilderCreateUnionType(
                 DIB(cx),
-                ptr::null(),
-                bytes_to_bits(size),
-                bytes_to_bits(align),
-                name)
-        }};
-    return (vp, size, align);
+                file_metadata,
+                enum_name,
+                file_metadata,
+                loc.line as c_uint,
+                bytes_to_bits(enum_type_size),
+                bytes_to_bits(enum_type_align),
+                0, // Flags
+                create_DIArray(DIB(cx), variants_metadata),
+                0) // RuntimeLang
+        }
+    };
 }
 
-fn create_tuple(cx: &mut CrateContext, tuple_type: ty::t, elements: &[ty::t], span: span)
-                -> DICompositeType {
-    debug!("create_tuple: %?", ty::get(tuple_type));
+
+/// Creates debug information for a composite type, that is, anything that results in a LLVM struct.
+///
+/// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
+fn composite_type_metadata(cx: &mut CrateContext,
+                           composite_llvm_type: Type,
+                           composite_type_name: &str,
+                           member_llvm_types: &[Type],
+                           member_names: &[~str],
+                           member_type_metadata: &[DIType],
+                           span: span)
+                        -> DICompositeType {
 
     let loc = span_start(cx, span);
-    let file_md = create_file(cx, loc.file.name);
-
-    let name = fmt!("tuple_%u", token::gensym("tuple"));
-    let mut scx = StructContext::new(cx, name, file_md, loc.line);
-    for elements.iter().advance |element| {
-        let ty_md = create_ty(cx, *element, span);
-        let (size, align) = size_and_align_of(cx, *element);
-        scx.add_member("", loc.line, size, align, ty_md);
+    let file_metadata = file_metadata(cx, loc.file.name);
+
+    let (composite_size, composite_align) = size_and_align_of(cx, composite_llvm_type);
+
+    let member_metadata: ~[DIDescriptor] = member_llvm_types
+        .iter()
+        .enumerate()
+        .transform(|(i, &member_llvm_type)| {
+            let (member_size, member_align) = size_and_align_of(cx, member_llvm_type);
+            let member_offset = machine::llelement_offset(cx, composite_llvm_type, i);
+            let member_name: &str = member_names[i];
+
+            do member_name.as_c_str |member_name| {
+                unsafe {
+                    llvm::LLVMDIBuilderCreateMemberType(
+                        DIB(cx),
+                        file_metadata,
+                        member_name,
+                        file_metadata,
+                        loc.line as c_uint,
+                        bytes_to_bits(member_size),
+                        bytes_to_bits(member_align),
+                        bytes_to_bits(member_offset),
+                        0,
+                        member_type_metadata[i])
+                }
+            }
+        })
+        .collect();
+
+    return do composite_type_name.as_c_str |name| {
+        unsafe {
+            llvm::LLVMDIBuilderCreateStructType(
+                DIB(cx),
+                file_metadata,
+                name,
+                file_metadata,
+                loc.line as c_uint,
+                bytes_to_bits(composite_size),
+                bytes_to_bits(composite_align),
+                0,
+                ptr::null(),
+                create_DIArray(DIB(cx), member_metadata),
+                0,
+                ptr::null())
     }
-    return scx.finalize();
+    };
 }
 
-fn create_boxed_type(cx: &mut CrateContext, contents: ty::t,
-                     span: span, boxed: DIType) -> DICompositeType {
-    debug!("create_boxed_type: %?", ty::get(contents));
+fn boxed_type_metadata(cx: &mut CrateContext,
+                       content_type_name: Option<&str>,
+                       content_llvm_type: Type,
+                       content_type_metadata: DIType,
+                       span: span)
+                    -> DICompositeType {
 
-    let loc = span_start(cx, span);
-    let file_md = create_file(cx, loc.file.name);
-    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 mut scx = StructContext::new(cx, fmt!("box<%s>", name), file_md, 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(cx);
-    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);
-    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: uint, span: span) -> DIType {
-    debug!("create_fixed_vec: %?", ty::get(_vec_t));
-
-    let elem_ty_md = create_ty(cx, elem_t, span);
-    let (size, align) = size_and_align_of(cx, elem_t);
+    let box_type_name = match content_type_name {
+        Some(content_type_name) => fmt!("Boxed<%s>", content_type_name),
+        None                    => ~"BoxedType"
+    };
+
+    let box_llvm_type = Type::box(cx, &content_llvm_type);
+    let member_llvm_types = box_llvm_type.field_types();
+    let member_names = [~"refcnt", ~"tydesc", ~"prev", ~"next", ~"val"];
+
+    assert!(box_layout_is_correct(cx, member_llvm_types, content_llvm_type));
+
+    let int_type = ty::mk_int();
+    let nil_pointer_type = ty::mk_nil_ptr(cx.tcx);
+
+    let member_types_metadata = [
+        type_metadata(cx, int_type, span),
+        type_metadata(cx, nil_pointer_type, span),
+        type_metadata(cx, nil_pointer_type, span),
+        type_metadata(cx, nil_pointer_type, span),
+        content_type_metadata
+    ];
+
+    return composite_type_metadata(
+        cx,
+        box_llvm_type,
+        box_type_name,
+        member_llvm_types,
+        member_names,
+        member_types_metadata,
+        span);
+
+    // Unfortunately, we cannot assert anything but the correct types here---and not whether the
+    // 'next' and 'prev' pointers are in the correct order.
+    fn box_layout_is_correct(cx: &CrateContext,
+                             member_llvm_types: &[Type],
+                             content_llvm_type: Type)
+                          -> bool {
+        member_llvm_types.len() == 5 &&
+        member_llvm_types[0] == cx.int_type &&
+        member_llvm_types[1] == cx.tydesc_type.ptr_to() &&
+        member_llvm_types[2] == Type::i8().ptr_to() &&
+        member_llvm_types[3] == Type::i8().ptr_to() &&
+        member_llvm_types[4] == content_llvm_type
+    }
+}
+
+fn fixed_vec_metadata(cx: &mut CrateContext,
+                      element_type: ty::t,
+                      len: uint,
+                      span: span)
+                   -> DIType {
+    let element_type_metadata = type_metadata(cx, element_type, span);
+    let element_llvm_type = type_of::type_of(cx, element_type);
+    let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type);
 
     let subrange = unsafe {
-        llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0_i64, len as i64)
+        llvm::LLVMDIBuilderGetOrCreateSubrange(
+        DIB(cx),
+        0,
+        len as c_longlong)
     };
 
     let subscripts = create_DIArray(DIB(cx), [subrange]);
     return unsafe {
         llvm::LLVMDIBuilderCreateArrayType(
             DIB(cx),
-            bytes_to_bits(size * len),
-            bytes_to_bits(align),
-            elem_ty_md,
+            bytes_to_bits(element_type_size * len),
+            bytes_to_bits(element_type_align),
+            element_type_metadata,
             subscripts)
     };
 }
 
-fn create_boxed_vec(cx: &mut CrateContext, vec_t: ty::t, elem_t: ty::t,
-                    vec_ty_span: span) -> DICompositeType {
-    debug!("create_boxed_vec: %?", ty::get(vec_t));
-
-    let loc = span_start(cx, vec_ty_span);
-    let file_md = create_file(cx, loc.file.name);
-    let elem_ty_md = create_ty(cx, elem_t, vec_ty_span);
+fn vec_metadata(cx: &mut CrateContext,
+                element_type: ty::t,
+                span: span)
+             -> DICompositeType {
 
-    let mut vec_scx = StructContext::new(cx, ty_to_str(cx.tcx, vec_t), file_md, 0);
-    let size_t_type = create_basic_type(cx, ty::mk_uint(), vec_ty_span);
+    let element_type_metadata = type_metadata(cx, element_type, span);
+    let element_llvm_type = type_of::type_of(cx, element_type);
+    let (element_size, element_align) = size_and_align_of(cx, element_llvm_type);
 
-    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 vec_llvm_type = Type::vec(cx.sess.targ_cfg.arch, &element_llvm_type);
+    let vec_type_name: &str = fmt!("[%s]", ty_to_str(cx.tcx, element_type));
 
-    let subrange = unsafe {
-        llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(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 member_llvm_types = vec_llvm_type.field_types();
+    let member_names = &[~"fill", ~"alloc", ~"elements"];
 
-    let subscripts = create_DIArray(DIB(cx), [subrange]);
-    let data_ptr = unsafe {
+    let int_type_metadata = type_metadata(cx, ty::mk_int(), span);
+    let array_type_metadata = unsafe {
         llvm::LLVMDIBuilderCreateArrayType(
             DIB(cx),
-            bytes_to_bits(arr_size),
-            bytes_to_bits(arr_align),
-            elem_ty_md,
-            subscripts)
+            bytes_to_bits(element_size),
+            bytes_to_bits(element_align),
+            element_type_metadata,
+            create_DIArray(DIB(cx), [llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, 0)]))
     };
-    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();
+    //                           fill               alloc              elements
+    let member_type_metadata = &[int_type_metadata, int_type_metadata, array_type_metadata];
+
+    return composite_type_metadata(
+        cx,
+        vec_llvm_type,
+        vec_type_name,
+        member_llvm_types,
+        member_names,
+        member_type_metadata,
+        span);
+}
 
-    let mut box_scx = StructContext::new(cx, fmt!("box<%s>", name), file_md, 0);
-    let int_t = ty::mk_int();
-    let refcount_type = create_basic_type(cx, int_t, vec_ty_span);
+fn boxed_vec_metadata(cx: &mut CrateContext,
+                      element_type: ty::t,
+                      span: span)
+                   -> DICompositeType {
+
+    let element_llvm_type = type_of::type_of(cx, element_type);
+    let vec_llvm_type = Type::vec(cx.sess.targ_cfg.arch, &element_llvm_type);
+    let vec_type_name: &str = fmt!("[%s]", ty_to_str(cx.tcx, element_type));
+    let vec_metadata = vec_metadata(cx, element_type, span);
+
+    return boxed_type_metadata(
+        cx,
+        Some(vec_type_name),
+        vec_llvm_type,
+        vec_metadata,
+        span);
+}
 
-    box_scx.add_member(
-        "refcnt",
-        0,
-        sys::size_of::<uint>(),
-        sys::min_align_of::<uint>(),
-        refcount_type);
-
-    let (vp, vpsize, vpalign) = voidptr(cx);
-    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)
-                    -> DICompositeType {
-    debug!("create_vec_slice: %?", ty::get(vec_t));
+fn vec_slice_metadata(cx: &mut CrateContext,
+                      vec_type: ty::t,
+                      element_type: ty::t,
+                      span: span)
+                   -> DICompositeType {
 
-    let loc = span_start(cx, span);
-    let file_md = create_file(cx, loc.file.name);
-    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);
+    debug!("vec_slice_metadata: %?", ty::get(vec_type));
+
+    let slice_llvm_type = type_of::type_of(cx, vec_type);
+    let slice_type_name = ty_to_str(cx.tcx, vec_type);
+
+    let member_llvm_types = slice_llvm_type.field_types();
+    let member_names = &[~"data_ptr", ~"size_in_bytes"];
 
-    let mut scx = StructContext::new(cx, ty_to_str(cx.tcx, vec_t), file_md, 0);
-    let (_, ptr_size, ptr_align) = voidptr(cx);
-    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();
+    assert!(slice_layout_is_correct(cx, member_llvm_types, element_type));
+
+    let data_ptr_type = ty::mk_ptr(cx.tcx, ty::mt { ty: element_type, mutbl: ast::m_imm });
+
+    let member_type_metadata = &[type_metadata(cx, data_ptr_type, span),
+                                 type_metadata(cx, ty::mk_uint(), span)];
+
+    return composite_type_metadata(
+        cx,
+        slice_llvm_type,
+        slice_type_name,
+        member_llvm_types,
+        member_names,
+        member_type_metadata,
+        span);
+
+    fn slice_layout_is_correct(cx: &mut CrateContext,
+                               member_llvm_types: &[Type],
+                               element_type: ty::t)
+                            -> bool {
+        member_llvm_types.len() == 2 &&
+        member_llvm_types[0] == type_of::type_of(cx, element_type).ptr_to() &&
+        member_llvm_types[1] == cx.int_type
+    }
 }
 
-fn create_fn_ty(cx: &mut CrateContext, _fn_ty: ty::t, inputs: ~[ty::t], output: ty::t,
-                span: span) -> DICompositeType {
-    debug!("create_fn_ty: %?", ty::get(_fn_ty));
+fn bare_fn_metadata(cx: &mut CrateContext,
+                    _fn_ty: ty::t,
+                    inputs: ~[ty::t],
+                    output: ty::t,
+                    span: span)
+                 -> DICompositeType {
+
+    debug!("bare_fn_metadata: %?", ty::get(_fn_ty));
 
     let loc = span_start(cx, span);
-    let file_md = create_file(cx, loc.file.name);
-    let (vp, _, _) = voidptr(cx);
-    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) };
-    let members = ~[output_ptr_md, vp] + inputs_vals;
+    let file_metadata = file_metadata(cx, loc.file.name);
+
+    let nil_pointer_type_metadata = type_metadata(cx, ty::mk_nil_ptr(cx.tcx), span);
+    let output_metadata = type_metadata(cx, output, span);
+    let output_ptr_metadata = pointer_type_metadata(cx, output, output_metadata);
+
+    let inputs_vals = do inputs.map |arg| { type_metadata(cx, *arg, span) };
+    let members = ~[output_ptr_metadata, nil_pointer_type_metadata] + inputs_vals;
 
     return unsafe {
         llvm::LLVMDIBuilderCreateSubroutineType(
             DIB(cx),
-            file_md,
+            file_metadata,
             create_DIArray(DIB(cx), members))
     };
 }
 
-fn create_unimpl_ty(cx: &mut CrateContext, t: ty::t) -> DIType {
-    debug!("create_unimpl_ty: %?", ty::get(t));
+fn unimplemented_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType {
+    debug!("unimplemented_type_metadata: %?", ty::get(t));
 
     let name = ty_to_str(cx.tcx, t);
-    let md = do as_c_str(fmt!("NYI<%s>", name)) |name| { unsafe {
-        llvm::LLVMDIBuilderCreateBasicType(
-            DIB(cx),
-            name,
-            0_u64,
-            8_u64,
-            DW_ATE_unsigned as c_uint)
-        }};
-    return md;
+    let metadata = do as_c_str(fmt!("NYI<%s>", name)) |name| {
+        unsafe {
+            llvm::LLVMDIBuilderCreateBasicType(
+                DIB(cx),
+                name,
+                0_u64,
+                8_u64,
+                DW_ATE_unsigned as c_uint)
+            }
+        };
+
+    return metadata;
 }
 
-fn create_ty(cx: &mut CrateContext, t: ty::t, span: span) -> DIType {
-    let ty_id = ty::type_id(t);
-    match dbg_cx(cx).created_types.find(&ty_id) {
-        Some(ty_md) => return *ty_md,
+fn type_metadata(cx: &mut CrateContext,
+                 t: ty::t,
+                 span: span)
+              -> DIType {
+    let type_id = ty::type_id(t);
+    match dbg_cx(cx).created_types.find(&type_id) {
+        Some(type_metadata) => return *type_metadata,
         None => ()
     }
 
-    debug!("create_ty: %?", ty::get(t));
+    fn create_pointer_to_box_metadata(cx: &mut CrateContext,
+                                      pointer_type: ty::t,
+                                      type_in_box: ty::t)
+                                   -> DIType {
+
+        let content_type_name: &str = ty_to_str(cx.tcx, type_in_box);
+        let content_llvm_type = type_of::type_of(cx, type_in_box);
+        let content_type_metadata = type_metadata(
+            cx,
+            type_in_box,
+            codemap::dummy_sp());
+
+        let box_metadata = boxed_type_metadata(
+            cx,
+            Some(content_type_name),
+            content_llvm_type,
+            content_type_metadata,
+            codemap::dummy_sp());
+
+        pointer_type_metadata(cx, pointer_type, box_metadata)
+    }
+
+    debug!("type_metadata: %?", ty::get(t));
 
     let sty = &ty::get(t).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),
+    let type_metadata = match *sty {
+        ty::ty_nil      |
+        ty::ty_bot      |
+        ty::ty_bool     |
+        ty::ty_int(_)   |
+        ty::ty_uint(_)  |
+        ty::ty_float(_) => {
+            basic_type_metadata(cx, t)
+        },
         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 + 1, span)
+                    fixed_vec_metadata(cx, i8_t, len + 1, span)
                 },
-                ty::vstore_uniq | ty::vstore_box => {
-                    let box_md = create_boxed_vec(cx, t, i8_t, span);
-                    create_pointer_type(cx, t, span, box_md)
+                ty::vstore_uniq  => {
+                    let vec_metadata = vec_metadata(cx, i8_t, span);
+                    pointer_type_metadata(cx, t, vec_metadata)
+                }
+                ty::vstore_box => {
+                    let boxed_vec_metadata = boxed_vec_metadata(cx, i8_t, span);
+                    pointer_type_metadata(cx, t, boxed_vec_metadata)
                 }
                 ty::vstore_slice(_region) => {
-                    create_vec_slice(cx, t, i8_t, span)
+                    vec_slice_metadata(cx, t, i8_t, span)
                 }
             }
         },
-        ty::ty_enum(_did, ref _substs) => {
-            cx.sess.span_note(span, "debuginfo for enum NYI");
-            create_unimpl_ty(cx, t)
-        }
-        ty::ty_box(ref mt) | ty::ty_uniq(ref mt) => {
-            let boxed = create_ty(cx, mt.ty, span);
-            let box_md = create_boxed_type(cx, mt.ty, span, boxed);
-            create_pointer_type(cx, t, span, box_md)
+        ty::ty_enum(def_id, ref substs) => {
+            enum_metadata(cx, t, def_id, substs, span)
+        },
+        ty::ty_box(ref mt) => {
+            create_pointer_to_box_metadata(cx, t, mt.ty)
         },
         ty::ty_evec(ref mt, ref vstore) => {
             match *vstore {
                 ty::vstore_fixed(len) => {
-                    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);
-                    create_pointer_type(cx, t, span, box_md)
-                },
-                ty::vstore_slice(_region) => {
-                    create_vec_slice(cx, t, mt.ty, span)
+                    fixed_vec_metadata(cx, mt.ty, len, span)
+                }
+                ty::vstore_uniq if ty::type_contents(cx.tcx, mt.ty).contains_managed() => {
+                    let boxed_vec_metadata = boxed_vec_metadata(cx, mt.ty, span);
+                    pointer_type_metadata(cx, t, boxed_vec_metadata)
+                }
+                ty::vstore_uniq => {
+                    let vec_metadata = vec_metadata(cx, mt.ty, span);
+                    pointer_type_metadata(cx, t, vec_metadata)
+                }
+                ty::vstore_box => {
+                    let boxed_vec_metadata = boxed_vec_metadata(cx, mt.ty, span);
+                    pointer_type_metadata(cx, t, boxed_vec_metadata)
+                }
+                ty::vstore_slice(_) => {
+                    vec_slice_metadata(cx, t, mt.ty, span)
                 }
             }
         },
-        ty::ty_ptr(ref mt) => {
-            let pointee = create_ty(cx, mt.ty, span);
-            create_pointer_type(cx, t, span, pointee)
+        ty::ty_uniq(ref mt) if ty::type_contents(cx.tcx, mt.ty).contains_managed() => {
+            create_pointer_to_box_metadata(cx, t, mt.ty)
         },
+        ty::ty_uniq(ref mt)    |
+        ty::ty_ptr(ref mt)     |
         ty::ty_rptr(_, ref mt) => {
-            let pointee = create_ty(cx, mt.ty, span);
-            create_pointer_type(cx, t, span, pointee)
+            let pointee = type_metadata(cx, mt.ty, span);
+            pointer_type_metadata(cx, t, pointee)
         },
         ty::ty_bare_fn(ref barefnty) => {
             let inputs = barefnty.sig.inputs.map(|a| *a);
             let output = barefnty.sig.output;
-            create_fn_ty(cx, t, inputs, output, span)
+            bare_fn_metadata(cx, t, inputs, output, span)
         },
         ty::ty_closure(ref _closurety) => {
             cx.sess.span_note(span, "debuginfo for closure NYI");
-            create_unimpl_ty(cx, t)
+            unimplemented_type_metadata(cx, t)
         },
         ty::ty_trait(_did, ref _substs, ref _vstore, _, _bounds) => {
             cx.sess.span_note(span, "debuginfo for trait NYI");
-            create_unimpl_ty(cx, t)
+            unimplemented_type_metadata(cx, t)
         },
         ty::ty_struct(did, ref substs) => {
             let fields = ty::struct_fields(cx.tcx, did, substs);
-            create_struct(cx, t, fields, span)
+            struct_metadata(cx, t, fields, span)
         },
         ty::ty_tup(ref elements) => {
-            create_tuple(cx, t, *elements, span)
+            tuple_metadata(cx, t, *elements, span)
         },
-        _ => cx.sess.bug("debuginfo: unexpected type in create_ty")
+        _ => cx.sess.bug("debuginfo: unexpected type in type_metadata")
     };
 
-    dbg_cx(cx).created_types.insert(ty_id, ty_md);
-    return ty_md;
+    dbg_cx(cx).created_types.insert(type_id, type_metadata);
+    return type_metadata;
 }
 
 fn set_debug_location(cx: @mut CrateContext, scope: DIScope, line: uint, col: uint) {
@@ -926,9 +1351,8 @@ fn span_start(cx: &CrateContext, span: span) -> codemap::Loc {
     cx.sess.codemap.lookup_char_pos(span.lo)
 }
 
-fn size_and_align_of(cx: &mut CrateContext, t: ty::t) -> (uint, uint) {
-    let llty = type_of::type_of(cx, t);
-    (machine::llsize_of_real(cx, llty), machine::llalign_of_min(cx, llty))
+fn size_and_align_of(cx: &mut CrateContext, llvm_type: Type) -> (uint, uint) {
+    (machine::llsize_of_alloc(cx, llvm_type), machine::llalign_of_min(cx, llvm_type))
 }
 
 fn bytes_to_bits(bytes: uint) -> c_ulonglong {
diff --git a/src/librustc/middle/trans/machine.rs b/src/librustc/middle/trans/machine.rs
index 2cd313ff431..0bf0a522a65 100644
--- a/src/librustc/middle/trans/machine.rs
+++ b/src/librustc/middle/trans/machine.rs
@@ -113,3 +113,9 @@ pub fn llalign_of(cx: &CrateContext, ty: Type) -> ValueRef {
             llvm::LLVMAlignOf(ty.to_ref()), cx.int_type.to_ref(), False);
     }
 }
+
+pub fn llelement_offset(cx: &CrateContext, struct_ty: Type, element: uint) -> uint {
+    unsafe {
+        return llvm::LLVMOffsetOfElement(cx.td.lltd, struct_ty.to_ref(), element as u32) as uint;
+    }
+}
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index b63117d25bb..94d872aa132 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -49,6 +49,8 @@ use syntax::opt_vec;
 use syntax::abi::AbiSet;
 use syntax;
 
+pub static INITIAL_DISCRIMINANT_VALUE: int = 0;
+
 // Data types
 
 #[deriving(Eq, IterBytes)]
@@ -275,7 +277,7 @@ struct ctxt_ {
     needs_unwind_cleanup_cache: @mut HashMap<t, bool>,
     tc_cache: @mut HashMap<uint, TypeContents>,
     ast_ty_to_ty_cache: @mut HashMap<node_id, ast_ty_to_ty_cache_entry>,
-    enum_var_cache: @mut HashMap<def_id, @~[VariantInfo]>,
+    enum_var_cache: @mut HashMap<def_id, @~[@VariantInfo]>,
     ty_param_defs: @mut HashMap<ast::node_id, TypeParameterDef>,
     adjustments: @mut HashMap<ast::node_id, @AutoAdjustment>,
     normalized_cache: @mut HashMap<t, t>,
@@ -3681,8 +3683,9 @@ fn struct_ctor_id(cx: ctxt, struct_did: ast::def_id) -> Option<ast::def_id> {
 
 // Enum information
 #[deriving(Clone)]
-pub struct VariantInfo_ {
+pub struct VariantInfo {
     args: ~[t],
+    arg_names: Option<~[ast::ident]>,
     ctor_ty: t,
     name: ast::ident,
     id: ast::def_id,
@@ -3690,19 +3693,71 @@ pub struct VariantInfo_ {
     vis: visibility
 }
 
-pub type VariantInfo = @VariantInfo_;
+impl VariantInfo {
+
+    /// Creates a new VariantInfo from the corresponding ast representation.
+    ///
+    /// Does not do any caching of the value in the type context.
+    pub fn from_ast_variant(cx: ctxt,
+                            ast_variant: &ast::variant,
+                            discriminant: int) -> VariantInfo {
+
+        let ctor_ty = node_id_to_type(cx, ast_variant.node.id);
+
+        match ast_variant.node.kind {
+            ast::tuple_variant_kind(ref args) => {
+                let arg_tys = if args.len() > 0 { ty_fn_args(ctor_ty).map(|a| *a) } else { ~[] };
+
+                return VariantInfo {
+                    args: arg_tys,
+                    arg_names: None,
+                    ctor_ty: ctor_ty,
+                    name: ast_variant.node.name,
+                    id: ast_util::local_def(ast_variant.node.id),
+                    disr_val: discriminant,
+                    vis: ast_variant.node.vis
+                };
+            },
+            ast::struct_variant_kind(ref struct_def) => {
+
+                let fields: &[@struct_field] = struct_def.fields;
+
+                assert!(fields.len() > 0);
+
+                let arg_tys = ty_fn_args(ctor_ty).map(|a| *a);
+                let arg_names = do fields.map |field| {
+                    match field.node.kind {
+                        named_field(ident, _) => ident,
+                        unnamed_field => cx.sess.bug(
+                            "enum_variants: all fields in struct must have a name")
+                    }
+                };
+
+                return VariantInfo {
+                    args: arg_tys,
+                    arg_names: Some(arg_names),
+                    ctor_ty: ctor_ty,
+                    name: ast_variant.node.name,
+                    id: ast_util::local_def(ast_variant.node.id),
+                    disr_val: discriminant,
+                    vis: ast_variant.node.vis
+                };
+            }
+        }
+    }
+}
 
 pub fn substd_enum_variants(cx: ctxt,
                             id: ast::def_id,
                             substs: &substs)
-                         -> ~[VariantInfo] {
+                         -> ~[@VariantInfo] {
     do enum_variants(cx, id).iter().transform |variant_info| {
         let substd_args = variant_info.args.iter()
             .transform(|aty| subst(cx, substs, *aty)).collect();
 
         let substd_ctor_ty = subst(cx, substs, variant_info.ctor_ty);
 
-        @VariantInfo_ {
+        @VariantInfo {
             args: substd_args,
             ctor_ty: substd_ctor_ty,
             ..(**variant_info).clone()
@@ -3820,7 +3875,7 @@ pub fn type_is_empty(cx: ctxt, t: t) -> bool {
      }
 }
 
-pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] {
+pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[@VariantInfo] {
     match cx.enum_var_cache.find(&id) {
       Some(&variants) => return variants,
       _ => { /* fallthrough */ }
@@ -3839,61 +3894,31 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] {
                     node: ast::item_enum(ref enum_definition, _),
                     _
                 }, _) => {
-            let mut disr_val = -1;
+            let mut last_discriminant: Option<int> = None;
             @enum_definition.variants.iter().transform(|variant| {
 
-                let ctor_ty = node_id_to_type(cx, variant.node.id);
-
-                match variant.node.kind {
-                    ast::tuple_variant_kind(ref args) => {
-                        let arg_tys = if args.len() > 0u {
-                                ty_fn_args(ctor_ty).map(|a| *a) }
-                            else {
-                                ~[]
-                            };
-
-                        match variant.node.disr_expr {
-                          Some (ex) => {
-                            disr_val = match const_eval::eval_const_expr(cx,
-                                                                         ex) {
-                              const_eval::const_int(val) => val as int,
-                              _ => cx.sess.bug("enum_variants: bad disr expr")
-                            }
-                          }
-                          _ => disr_val += 1
+                let mut discriminant = match last_discriminant {
+                    Some(val) => val + 1,
+                    None => INITIAL_DISCRIMINANT_VALUE
+                };
+
+                match variant.node.disr_expr {
+                    Some(e) => match const_eval::eval_const_expr_partial(&cx, e) {
+                        Ok(const_eval::const_int(val)) => discriminant = val as int,
+                        Ok(_) => {
+                            cx.sess.span_err(e.span, "expected signed integer constant");
                         }
-                        @VariantInfo_{
-                            args: arg_tys,
-                            ctor_ty: ctor_ty,
-                            name: variant.node.name,
-                            id: ast_util::local_def(variant.node.id),
-                            disr_val: disr_val,
-                            vis: variant.node.vis
-                         }
-                    },
-                    ast::struct_variant_kind(struct_def) => {
-                        let arg_tys =
-                            // Is this check needed for structs too, or are they always guaranteed
-                            // to have a valid constructor function?
-                            if struct_def.fields.len() > 0 {
-                                ty_fn_args(ctor_ty).map(|a| *a)
-                            } else {
-                                ~[]
-                            };
-
-                        assert!(variant.node.disr_expr.is_none());
-                        disr_val += 1;
-
-                        @VariantInfo_{
-                            args: arg_tys,
-                            ctor_ty: ctor_ty,
-                            name: variant.node.name,
-                            id: ast_util::local_def(variant.node.id),
-                            disr_val: disr_val,
-                            vis: variant.node.vis
+                        Err(ref err) => {
+                            cx.sess.span_err(e.span, fmt!("expected constant: %s", (*err)));
                         }
-                    }
-                }
+                    },
+                    None => {}
+                };
+
+                let variant_info = @VariantInfo::from_ast_variant(cx, variant, discriminant);
+                last_discriminant = Some(discriminant);
+                variant_info
+
             }).collect()
           }
           _ => cx.sess.bug("enum_variants: id not bound to an enum")
@@ -3908,7 +3933,7 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] {
 pub fn enum_variant_with_id(cx: ctxt,
                             enum_id: ast::def_id,
                             variant_id: ast::def_id)
-                         -> VariantInfo {
+                         -> @VariantInfo {
     let variants = enum_variants(cx, enum_id);
     let mut i = 0;
     while i < variants.len() {
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index 4a9e0fddbe7..fa24c8c6d09 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -81,7 +81,7 @@ use middle::const_eval;
 use middle::pat_util::pat_id_map;
 use middle::pat_util;
 use middle::lint::unreachable_code;
-use middle::ty::{FnSig, VariantInfo_};
+use middle::ty::{FnSig, VariantInfo};
 use middle::ty::{ty_param_bounds_and_ty, ty_param_substs_and_ty};
 use middle::ty::{substs, param_ty, ExprTyProvider};
 use middle::ty;
@@ -3133,82 +3133,66 @@ pub fn check_enum_variants(ccx: @mut CrateCtxt,
                            vs: &[ast::variant],
                            id: ast::node_id) {
     fn do_check(ccx: @mut CrateCtxt,
-                _sp: span,
                 vs: &[ast::variant],
-                id: ast::node_id,
-                disr_vals: &mut ~[int],
-                disr_val: &mut int,
-                variants: &mut ~[ty::VariantInfo]) {
+                id: ast::node_id)
+                -> ~[@ty::VariantInfo] {
+
         let rty = ty::node_id_to_type(ccx.tcx, id);
-        for vs.iter().advance |v| {
-            for v.node.disr_expr.iter().advance |e_ref| {
-                let e = *e_ref;
-                debug!("disr expr, checking %s",
-                       pprust::expr_to_str(e, ccx.tcx.sess.intr()));
-                let declty = ty::mk_int();
-                let fcx = blank_fn_ctxt(ccx, rty, e.id);
-                check_const_with_ty(fcx, e.span, e, declty);
-                // check_expr (from check_const pass) doesn't guarantee
-                // that the expression is in an form that eval_const_expr can
-                // handle, so we may still get an internal compiler error
-
-                match const_eval::eval_const_expr_partial(&ccx.tcx, e) {
-                  Ok(const_eval::const_int(val)) => {
-                    *disr_val = val as int;
-                  }
-                  Ok(_) => {
-                    ccx.tcx.sess.span_err(e.span, "expected signed integer \
-                                                   constant");
-                  }
-                  Err(ref err) => {
-                    ccx.tcx.sess.span_err(e.span,
-                     fmt!("expected constant: %s", (*err)));
+        let mut variants: ~[@ty::VariantInfo] = ~[];
+        let mut disr_vals: ~[int] = ~[];
+        let mut prev_disr_val: Option<int> = None;
 
-                  }
-                }
-            }
-            if disr_vals.contains(&*disr_val) {
-                ccx.tcx.sess.span_err(v.span,
-                                      "discriminator value already exists");
-            }
-            disr_vals.push(*disr_val);
-            let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
+        for vs.iter().advance |v| {
 
-            let this_disr_val = *disr_val;
-            *disr_val += 1;
+            // If the discriminant value is specified explicitly in the enum check whether the
+            // initialization expression is valid, otherwise use the last value plus one.
+            let mut current_disr_val = match prev_disr_val {
+                Some(prev_disr_val) => prev_disr_val + 1,
+                None => ty::INITIAL_DISCRIMINANT_VALUE
+            };
 
-            let arg_tys = match v.node.kind {
-                ast::tuple_variant_kind(ref args) if args.len() > 0u => {
-                    Some(ty::ty_fn_args(ctor_ty).map(|a| *a))
-                }
-                ast::tuple_variant_kind(_) => {
-                    Some(~[])
-                }
-                ast::struct_variant_kind(_) => {
-                    Some(ty::lookup_struct_fields(
-                        ccx.tcx, local_def(v.node.id)).map(|cf|
-                            ty::node_id_to_type(ccx.tcx, cf.id.node)))
-                }
+            match v.node.disr_expr {
+                Some(e) => {
+                    debug!("disr expr, checking %s", pprust::expr_to_str(e, ccx.tcx.sess.intr()));
+
+                    let declty = ty::mk_int();
+                    let fcx = blank_fn_ctxt(ccx, rty, e.id);
+                    check_const_with_ty(fcx, e.span, e, declty);
+                    // check_expr (from check_const pass) doesn't guarantee
+                    // that the expression is in an form that eval_const_expr can
+                    // handle, so we may still get an internal compiler error
+
+                    match const_eval::eval_const_expr_partial(&ccx.tcx, e) {
+                        Ok(const_eval::const_int(val)) => current_disr_val = val as int,
+                        Ok(_) => {
+                            ccx.tcx.sess.span_err(e.span, "expected signed integer constant");
+                        }
+                        Err(ref err) => {
+                            ccx.tcx.sess.span_err(e.span, fmt!("expected constant: %s", (*err)));
+                        }
+                    }
+                },
+                None => ()
             };
 
-            match arg_tys {
-                None => {}
-                Some(arg_tys) => {
-                    variants.push(
-                        @VariantInfo_{args: arg_tys, ctor_ty: ctor_ty,
-                          name: v.node.name, id: local_def(v.node.id),
-                          disr_val: this_disr_val, vis: v.node.vis});
-                }
+            // Check for duplicate discriminator values
+            if disr_vals.contains(&current_disr_val) {
+                ccx.tcx.sess.span_err(v.span, "discriminator value already exists");
             }
+            disr_vals.push(current_disr_val);
+
+            let variant_info = @VariantInfo::from_ast_variant(ccx.tcx, v, current_disr_val);
+            prev_disr_val = Some(current_disr_val);
+
+            variants.push(variant_info);
         }
+
+        return variants;
     }
 
     let rty = ty::node_id_to_type(ccx.tcx, id);
-    let mut disr_vals: ~[int] = ~[];
-    let mut disr_val = 0;
-    let mut variants = ~[];
 
-    do_check(ccx, sp, vs, id, &mut disr_vals, &mut disr_val, &mut variants);
+    let variants = do_check(ccx, vs, id);
 
     // cache so that ty::enum_variants won't repeat this work
     ccx.tcx.enum_var_cache.insert(local_def(id), @variants);
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index 614c1723c5f..2a1f26bf441 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -565,8 +565,8 @@ extern "C" bool LLVMRustStartMultithreading() {
 typedef DIBuilder* DIBuilderRef;
 
 template<typename DIT>
-DIT unwrapDI(LLVMValueRef ref) { 
-    return DIT(ref ? unwrap<MDNode>(ref) : NULL); 
+DIT unwrapDI(LLVMValueRef ref) {
+    return DIT(ref ? unwrap<MDNode>(ref) : NULL);
 }
 
 extern "C" DIBuilderRef LLVMDIBuilderCreate(LLVMModuleRef M) {
@@ -604,21 +604,21 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateFile(
 
 extern "C" LLVMValueRef LLVMDIBuilderCreateSubroutineType(
     DIBuilderRef Builder,
-    LLVMValueRef File, 
+    LLVMValueRef File,
     LLVMValueRef ParameterTypes) {
     return wrap(Builder->createSubroutineType(
-        unwrapDI<DIFile>(File), 
+        unwrapDI<DIFile>(File),
         unwrapDI<DIArray>(ParameterTypes)));
 }
 
 extern "C" LLVMValueRef LLVMDIBuilderCreateFunction(
     DIBuilderRef Builder,
-    LLVMValueRef Scope, 
+    LLVMValueRef Scope,
     const char* Name,
     const char* LinkageName,
-    LLVMValueRef File,  
+    LLVMValueRef File,
     unsigned LineNo,
-    LLVMValueRef Ty, 
+    LLVMValueRef Ty,
     bool isLocalToUnit,
     bool isDefinition,
     unsigned ScopeLine,
@@ -628,11 +628,11 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateFunction(
     LLVMValueRef TParam,
     LLVMValueRef Decl) {
     return wrap(Builder->createFunction(
-        unwrapDI<DIScope>(Scope), Name, LinkageName, 
-        unwrapDI<DIFile>(File), LineNo, 
-        unwrapDI<DIType>(Ty), isLocalToUnit, isDefinition, ScopeLine, 
+        unwrapDI<DIScope>(Scope), Name, LinkageName,
+        unwrapDI<DIFile>(File), LineNo,
+        unwrapDI<DIType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
         Flags, isOptimized,
-        unwrap<Function>(Fn), 
+        unwrap<Function>(Fn),
         unwrapDI<MDNode*>(TParam),
         unwrapDI<MDNode*>(Decl)));
 }
@@ -644,10 +644,10 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateBasicType(
     uint64_t AlignInBits,
     unsigned Encoding) {
     return wrap(Builder->createBasicType(
-        Name, SizeInBits, 
+        Name, SizeInBits,
         AlignInBits, Encoding));
 }
-    
+
 extern "C" LLVMValueRef LLVMDIBuilderCreatePointerType(
     DIBuilderRef Builder,
     LLVMValueRef PointeeTy,
@@ -672,11 +672,11 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateStructType(
     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<DIDescriptor>(Scope), Name,
+        unwrapDI<DIFile>(File), LineNumber,
+        SizeInBits, AlignInBits, Flags,
+        unwrapDI<DIType>(DerivedFrom),
+        unwrapDI<DIArray>(Elements), RunTimeLang,
         unwrapDI<MDNode*>(VTableHolder)));
 }
 
@@ -692,12 +692,12 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateMemberType(
     unsigned Flags,
     LLVMValueRef Ty) {
     return wrap(Builder->createMemberType(
-        unwrapDI<DIDescriptor>(Scope), Name, 
+        unwrapDI<DIDescriptor>(Scope), Name,
         unwrapDI<DIFile>(File), LineNo,
-        SizeInBits, AlignInBits, OffsetInBits, Flags, 
+        SizeInBits, AlignInBits, OffsetInBits, Flags,
         unwrapDI<DIType>(Ty)));
 }
-    
+
 extern "C" LLVMValueRef LLVMDIBuilderCreateLexicalBlock(
     DIBuilderRef Builder,
     LLVMValueRef Scope,
@@ -705,10 +705,10 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateLexicalBlock(
     unsigned Line,
     unsigned Col) {
     return wrap(Builder->createLexicalBlock(
-        unwrapDI<DIDescriptor>(Scope), 
+        unwrapDI<DIDescriptor>(Scope),
         unwrapDI<DIFile>(File), Line, Col));
 }
-    
+
 extern "C" LLVMValueRef LLVMDIBuilderCreateLocalVariable(
     DIBuilderRef Builder,
     unsigned Tag,
@@ -720,45 +720,45 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateLocalVariable(
     bool AlwaysPreserve,
     unsigned Flags,
     unsigned ArgNo) {
-    return wrap(Builder->createLocalVariable(Tag, 
-        unwrapDI<DIDescriptor>(Scope), Name, 
-        unwrapDI<DIFile>(File), 
-        LineNo, 
+    return wrap(Builder->createLocalVariable(Tag,
+        unwrapDI<DIDescriptor>(Scope), Name,
+        unwrapDI<DIFile>(File),
+        LineNo,
         unwrapDI<DIType>(Ty), AlwaysPreserve, Flags, ArgNo));
 }
 
 extern "C" LLVMValueRef LLVMDIBuilderCreateArrayType(
     DIBuilderRef Builder,
-    uint64_t Size,  
-    uint64_t AlignInBits,  
-    LLVMValueRef Ty, 
+    uint64_t Size,
+    uint64_t AlignInBits,
+    LLVMValueRef Ty,
     LLVMValueRef Subscripts) {
     return wrap(Builder->createArrayType(Size, AlignInBits,
-        unwrapDI<DIType>(Ty), 
+        unwrapDI<DIType>(Ty),
         unwrapDI<DIArray>(Subscripts)));
 }
 
 extern "C" LLVMValueRef LLVMDIBuilderCreateVectorType(
     DIBuilderRef Builder,
-    uint64_t Size,  
-    uint64_t AlignInBits,  
-    LLVMValueRef Ty, 
+    uint64_t Size,
+    uint64_t AlignInBits,
+    LLVMValueRef Ty,
     LLVMValueRef Subscripts) {
     return wrap(Builder->createVectorType(Size, AlignInBits,
-        unwrapDI<DIType>(Ty), 
+        unwrapDI<DIType>(Ty),
         unwrapDI<DIArray>(Subscripts)));
 }
 
 extern "C" LLVMValueRef LLVMDIBuilderGetOrCreateSubrange(
-    DIBuilderRef Builder, 
-    int64_t Lo, 
+    DIBuilderRef Builder,
+    int64_t Lo,
     int64_t Count) {
     return wrap(Builder->getOrCreateSubrange(Lo, Count));
 }
 
 extern "C" LLVMValueRef LLVMDIBuilderGetOrCreateArray(
     DIBuilderRef Builder,
-    LLVMValueRef* Ptr, 
+    LLVMValueRef* Ptr,
     unsigned Count) {
     return wrap(Builder->getOrCreateArray(
         ArrayRef<Value*>(reinterpret_cast<Value**>(Ptr), Count)));
@@ -770,8 +770,8 @@ extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(
     LLVMValueRef VarInfo,
     LLVMBasicBlockRef InsertAtEnd) {
     return wrap(Builder->insertDeclare(
-        unwrap(Val), 
-        unwrapDI<DIVariable>(VarInfo), 
+        unwrap(Val),
+        unwrapDI<DIVariable>(VarInfo),
         unwrap(InsertAtEnd)));
 }
 
@@ -781,7 +781,61 @@ extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareBefore(
     LLVMValueRef VarInfo,
     LLVMValueRef InsertBefore) {
     return wrap(Builder->insertDeclare(
-        unwrap(Val), 
-        unwrapDI<DIVariable>(VarInfo), 
+        unwrap(Val),
+        unwrapDI<DIVariable>(VarInfo),
         unwrap<Instruction>(InsertBefore)));
 }
+
+extern "C" LLVMValueRef LLVMDIBuilderCreateEnumerator(
+    DIBuilderRef Builder,
+    const char* Name,
+    uint64_t Val)
+{
+    return wrap(Builder->createEnumerator(Name, Val));
+}
+
+extern "C" LLVMValueRef LLVMDIBuilderCreateEnumerationType(
+    DIBuilderRef Builder,
+    LLVMValueRef Scope,
+    const char* Name,
+    LLVMValueRef File,
+    unsigned LineNumber,
+    uint64_t SizeInBits,
+    uint64_t AlignInBits,
+    LLVMValueRef Elements,
+    LLVMValueRef ClassType)
+{
+    return wrap(Builder->createEnumerationType(
+        unwrapDI<DIDescriptor>(Scope),
+        Name,
+        unwrapDI<DIFile>(File),
+        LineNumber,
+        SizeInBits,
+        AlignInBits,
+        unwrapDI<DIArray>(Elements),
+        unwrapDI<DIType>(ClassType)));
+}
+
+extern "C" LLVMValueRef LLVMDIBuilderCreateUnionType(
+    DIBuilderRef Builder,
+    LLVMValueRef Scope,
+    const char* Name,
+    LLVMValueRef File,
+    unsigned LineNumber,
+    uint64_t SizeInBits,
+    uint64_t AlignInBits,
+    unsigned Flags,
+    LLVMValueRef Elements,
+    unsigned RunTimeLang)
+{
+    return wrap(Builder->createUnionType(
+        unwrapDI<DIDescriptor>(Scope),
+        Name,
+        unwrapDI<DIFile>(File),
+        LineNumber,
+        SizeInBits,
+        AlignInBits,
+        Flags,
+        unwrapDI<DIArray>(Elements),
+        RunTimeLang));
+}
\ No newline at end of file
diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in
index d5f03ac604b..5b6c3ed2f52 100644
--- a/src/rustllvm/rustllvm.def.in
+++ b/src/rustllvm/rustllvm.def.in
@@ -608,3 +608,6 @@ LLVMDIBuilderCreateSubroutineType
 LLVMDIBuilderGetOrCreateArray
 LLVMDIBuilderInsertDeclareAtEnd
 LLVMDIBuilderInsertDeclareBefore
+LLVMDIBuilderCreateEnumerator
+LLVMDIBuilderCreateEnumerationType
+LLVMDIBuilderCreateUnionType
diff --git a/src/test/debug-info/reference-to-basic.rs b/src/test/debug-info/borrowed-basic.rs
index dfd0fbf8655..7610301f6f0 100644
--- a/src/test/debug-info/reference-to-basic.rs
+++ b/src/test/debug-info/borrowed-basic.rs
@@ -10,10 +10,7 @@
 
 // xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
 
-// Caveats - gdb prints any 8-bit value (meaning rust i8 and u8 values)
-// as its numerical value along with its associated ASCII char, there
-// doesn't seem to be any way around this. Also, gdb doesn't know
-// about UTF-32 character encoding and will print a rust char as only
+// Gdb doesn't know about UTF-32 character encoding and will print a rust char as only
 // its numerical value.
 
 // compile-flags:-Z extra-debug-info
@@ -67,49 +64,49 @@
 
 fn main() {
     let bool_val: bool = true;
-    let bool_ref : &bool = &bool_val;
+    let bool_ref: &bool = &bool_val;
 
     let int_val: int = -1;
-    let int_ref : &int = &int_val;
+    let int_ref: &int = &int_val;
 
     let char_val: char = 'a';
-    let char_ref : &char = &char_val;
+    let char_ref: &char = &char_val;
 
     let i8_val: i8 = 68;
-    let i8_ref : &i8 = &i8_val;
+    let i8_ref: &i8 = &i8_val;
 
     let i16_val: i16 = -16;
-    let i16_ref : &i16 = &i16_val;
+    let i16_ref: &i16 = &i16_val;
 
     let i32_val: i32 = -32;
-    let i32_ref : &i32 = &i32_val;
+    let i32_ref: &i32 = &i32_val;
 
     let uint_val: i64 = -64;
-    let i64_ref : &i64 = &uint_val;
+    let i64_ref: &i64 = &uint_val;
 
     let uint_val: uint = 1;
-    let uint_ref : &uint = &uint_val;
+    let uint_ref: &uint = &uint_val;
 
     let u8_val: u8 = 100;
-    let u8_ref : &u8 = &u8_val;
+    let u8_ref: &u8 = &u8_val;
 
     let u16_val: u16 = 16;
-    let u16_ref : &u16 = &u16_val;
+    let u16_ref: &u16 = &u16_val;
 
     let u32_val: u32 = 32;
-    let u32_ref : &u32 = &u32_val;
+    let u32_ref: &u32 = &u32_val;
 
     let u64_val: u64 = 64;
-    let u64_ref : &u64 = &u64_val;
+    let u64_ref: &u64 = &u64_val;
 
     let float_val: float = 1.5;
-    let float_ref : &float = &float_val;
+    let float_ref: &float = &float_val;
 
     let f32_val: f32 = 2.5;
-    let f32_ref : &f32 = &f32_val;
+    let f32_ref: &f32 = &f32_val;
 
     let f64_val: f64 = 3.5;
-    let f64_ref : &f64 = &f64_val;
+    let f64_ref: &f64 = &f64_val;
     zzz();
 }
 
diff --git a/src/test/debug-info/borrowed-c-style-enum.rs b/src/test/debug-info/borrowed-c-style-enum.rs
new file mode 100644
index 00000000000..70c85258c79
--- /dev/null
+++ b/src/test/debug-info/borrowed-c-style-enum.rs
@@ -0,0 +1,42 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print *the_a_ref
+// check:$1 = TheA
+
+// debugger:print *the_b_ref
+// check:$2 = TheB
+
+// debugger:print *the_c_ref
+// check:$3 = TheC
+
+enum ABC { TheA, TheB, TheC }
+
+fn main() {
+    let the_a = TheA;
+    let the_a_ref: &ABC = &the_a;
+
+    let the_b = TheB;
+    let the_b_ref: &ABC = &the_b;
+
+    let the_c = TheC;
+    let the_c_ref: &ABC = &the_c;
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/borrowed-enum.rs b/src/test/debug-info/borrowed-enum.rs
new file mode 100644
index 00000000000..38aa9c38810
--- /dev/null
+++ b/src/test/debug-info/borrowed-enum.rs
@@ -0,0 +1,62 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print *the_a_ref
+// check:$1 = {{TheA, x = 0, y = 8970181431921507452}, {TheA, 0, 2088533116, 2088533116}}
+
+// debugger:print *the_b_ref
+// check:$2 = {{TheB, x = 0, y = 1229782938247303441}, {TheB, 0, 286331153, 286331153}}
+
+// debugger:print *univariant_ref
+// check:$3 = {4820353753753434}
+
+// The first element is to ensure proper alignment, irrespective of the machines word size. Since
+// the size of the discriminant value is machine dependent, this has be taken into account when
+// datatype layout should be predictable as in this case.
+enum ABC {
+	TheA { x: i64, y: i64 },
+	TheB (i64, i32, i32),
+}
+
+// This is a special case since it does not have the implicit discriminant field.
+enum Univariant {
+    TheOnlyCase(i64)
+}
+
+fn main() {
+
+	// 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
+	// 0b01111100011111000111110001111100 = 2088533116
+	// 0b0111110001111100 = 31868
+	// 0b01111100 = 124
+    let the_a = TheA { x: 0, y: 8970181431921507452 };
+    let the_a_ref: &ABC = &the_a;
+
+    // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
+    // 0b00010001000100010001000100010001 = 286331153
+    // 0b0001000100010001 = 4369
+    // 0b00010001 = 17
+    let the_b = TheB (0, 286331153, 286331153);
+    let the_b_ref: &ABC = &the_b;
+
+    let univariant = TheOnlyCase(4820353753753434);
+    let univariant_ref: &Univariant = &univariant;
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/reference-to-managed-basic.rs b/src/test/debug-info/borrowed-managed-basic.rs
index e3951c94b6f..9087bb36fa5 100644
--- a/src/test/debug-info/reference-to-managed-basic.rs
+++ b/src/test/debug-info/borrowed-managed-basic.rs
@@ -65,49 +65,49 @@
 
 fn main() {
     let bool_box: @bool = @true;
-    let bool_ref : &bool = bool_box;
+    let bool_ref: &bool = bool_box;
 
     let int_box: @int = @-1;
-    let int_ref : &int = int_box;
+    let int_ref: &int = int_box;
 
     let char_box: @char = @'a';
-    let char_ref : &char = char_box;
+    let char_ref: &char = char_box;
 
     let i8_box: @i8 = @68;
-    let i8_ref : &i8 = i8_box;
+    let i8_ref: &i8 = i8_box;
 
     let i16_box: @i16 = @-16;
-    let i16_ref : &i16 = i16_box;
+    let i16_ref: &i16 = i16_box;
 
     let i32_box: @i32 = @-32;
-    let i32_ref : &i32 = i32_box;
+    let i32_ref: &i32 = i32_box;
 
     let i64_box: @i64 = @-64;
-    let i64_ref : &i64 = i64_box;
+    let i64_ref: &i64 = i64_box;
 
     let uint_box: @uint = @1;
-    let uint_ref : &uint = uint_box;
+    let uint_ref: &uint = uint_box;
 
     let u8_box: @u8 = @100;
-    let u8_ref : &u8 = u8_box;
+    let u8_ref: &u8 = u8_box;
 
     let u16_box: @u16 = @16;
-    let u16_ref : &u16 = u16_box;
+    let u16_ref: &u16 = u16_box;
 
     let u32_box: @u32 = @32;
-    let u32_ref : &u32 = u32_box;
+    let u32_ref: &u32 = u32_box;
 
     let u64_box: @u64 = @64;
-    let u64_ref : &u64 = u64_box;
+    let u64_ref: &u64 = u64_box;
 
     let float_box: @float = @1.5;
-    let float_ref : &float = float_box;
+    let float_ref: &float = float_box;
 
     let f32_box: @f32 = @2.5;
-    let f32_ref : &f32 = f32_box;
+    let f32_ref: &f32 = f32_box;
 
     let f64_box: @f64 = @3.5;
-    let f64_ref : &f64 = f64_box;
+    let f64_ref: &f64 = f64_box;
     zzz();
 }
 
diff --git a/src/test/debug-info/reference-to-struct.rs b/src/test/debug-info/borrowed-struct.rs
index f00872c00b0..8b6eca3e37f 100644
--- a/src/test/debug-info/reference-to-struct.rs
+++ b/src/test/debug-info/borrowed-struct.rs
@@ -10,9 +10,6 @@
 
 // xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
 
-// GDB doesn't know about UTF-32 character encoding and will print a rust char as only its numerical
-// value.
-
 // compile-flags:-Z extra-debug-info
 // debugger:break zzz
 // debugger:run
@@ -57,20 +54,20 @@ struct SomeStruct {
 
 fn main() {
     let stack_val: SomeStruct = SomeStruct { x: 10, y: 23.5 };
-    let stack_val_ref : &SomeStruct = &stack_val;
-    let stack_val_interior_ref_1 : &int = &stack_val.x;
-    let stack_val_interior_ref_2 : &f64 = &stack_val.y;
-    let ref_to_unnamed : &SomeStruct = &SomeStruct { x: 11, y: 24.5 };
+    let stack_val_ref: &SomeStruct = &stack_val;
+    let stack_val_interior_ref_1: &int = &stack_val.x;
+    let stack_val_interior_ref_2: &f64 = &stack_val.y;
+    let ref_to_unnamed: &SomeStruct = &SomeStruct { x: 11, y: 24.5 };
 
     let managed_val = @SomeStruct { x: 12, y: 25.5 };
-    let managed_val_ref : &SomeStruct = managed_val;
-    let managed_val_interior_ref_1 : &int = &managed_val.x;
-    let managed_val_interior_ref_2 : &f64 = &managed_val.y;
+    let managed_val_ref: &SomeStruct = managed_val;
+    let managed_val_interior_ref_1: &int = &managed_val.x;
+    let managed_val_interior_ref_2: &f64 = &managed_val.y;
 
     let unique_val = ~SomeStruct { x: 13, y: 26.5 };
-    let unique_val_ref : &SomeStruct = unique_val;
-    let unique_val_interior_ref_1 : &int = &unique_val.x;
-    let unique_val_interior_ref_2 : &f64 = &unique_val.y;
+    let unique_val_ref: &SomeStruct = unique_val;
+    let unique_val_interior_ref_1: &int = &unique_val.x;
+    let unique_val_interior_ref_2: &f64 = &unique_val.y;
 
     zzz();
 }
diff --git a/src/test/debug-info/reference-to-tuple.rs b/src/test/debug-info/borrowed-tuple.rs
index 86d02185bda..da199941c84 100644
--- a/src/test/debug-info/reference-to-tuple.rs
+++ b/src/test/debug-info/borrowed-tuple.rs
@@ -10,9 +10,6 @@
 
 // xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
 
-// GDB doesn't know about UTF-32 character encoding and will print a rust char as only its numerical
-// value.
-
 // compile-flags:-Z extra-debug-info
 // debugger:break zzz
 // debugger:run
@@ -32,14 +29,14 @@
 
 fn main() {
     let stack_val: (i16, f32) = (-14, -19f32);
-    let stack_val_ref : &(i16, f32) = &stack_val;
-    let ref_to_unnamed : &(i16, f32) = &(-15, -20f32);
+    let stack_val_ref: &(i16, f32) = &stack_val;
+    let ref_to_unnamed: &(i16, f32) = &(-15, -20f32);
 
-    let managed_val : @(i16, f32) = @(-16, -21f32);
-    let managed_val_ref : &(i16, f32) = managed_val;
+    let managed_val: @(i16, f32) = @(-16, -21f32);
+    let managed_val_ref: &(i16, f32) = managed_val;
 
     let unique_val: ~(i16, f32) = ~(-17, -22f32);
-    let unique_val_ref : &(i16, f32) = unique_val;
+    let unique_val_ref: &(i16, f32) = unique_val;
 
     zzz();
 }
diff --git a/src/test/debug-info/reference-to-unique-basic.rs b/src/test/debug-info/borrowed-unique-basic.rs
index ce5b50459f6..52f5a2cba1e 100644
--- a/src/test/debug-info/reference-to-unique-basic.rs
+++ b/src/test/debug-info/borrowed-unique-basic.rs
@@ -10,8 +10,7 @@
 
 // xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
 
-// Gdb doesn't know
-// about UTF-32 character encoding and will print a rust char as only
+// Gdb doesn't know about UTF-32 character encoding and will print a rust char as only
 // its numerical value.
 
 // compile-flags:-Z extra-debug-info
@@ -66,49 +65,49 @@
 
 fn main() {
     let bool_box: ~bool = ~true;
-    let bool_ref : &bool = bool_box;
+    let bool_ref: &bool = bool_box;
 
     let int_box: ~int = ~-1;
-    let int_ref : &int = int_box;
+    let int_ref: &int = int_box;
 
     let char_box: ~char = ~'a';
-    let char_ref : &char = char_box;
+    let char_ref: &char = char_box;
 
     let i8_box: ~i8 = ~68;
-    let i8_ref : &i8 = i8_box;
+    let i8_ref: &i8 = i8_box;
 
     let i16_box: ~i16 = ~-16;
-    let i16_ref : &i16 = i16_box;
+    let i16_ref: &i16 = i16_box;
 
     let i32_box: ~i32 = ~-32;
-    let i32_ref : &i32 = i32_box;
+    let i32_ref: &i32 = i32_box;
 
     let i64_box: ~i64 = ~-64;
-    let i64_ref : &i64 = i64_box;
+    let i64_ref: &i64 = i64_box;
 
     let uint_box: ~uint = ~1;
-    let uint_ref : &uint = uint_box;
+    let uint_ref: &uint = uint_box;
 
     let u8_box: ~u8 = ~100;
-    let u8_ref : &u8 = u8_box;
+    let u8_ref: &u8 = u8_box;
 
     let u16_box: ~u16 = ~16;
-    let u16_ref : &u16 = u16_box;
+    let u16_ref: &u16 = u16_box;
 
     let u32_box: ~u32 = ~32;
-    let u32_ref : &u32 = u32_box;
+    let u32_ref: &u32 = u32_box;
 
     let u64_box: ~u64 = ~64;
-    let u64_ref : &u64 = u64_box;
+    let u64_ref: &u64 = u64_box;
 
     let float_box: ~float = ~1.5;
-    let float_ref : &float = float_box;
+    let float_ref: &float = float_box;
 
     let f32_box: ~f32 = ~2.5;
-    let f32_ref : &f32 = f32_box;
+    let f32_ref: &f32 = f32_box;
 
     let f64_box: ~f64 = ~3.5;
-    let f64_ref : &f64 = f64_box;
+    let f64_ref: &f64 = f64_box;
     zzz();
 }
 
diff --git a/src/test/debug-info/box.rs b/src/test/debug-info/box.rs
index 4a3a65a9055..c63cffd7b74 100644
--- a/src/test/debug-info/box.rs
+++ b/src/test/debug-info/box.rs
@@ -8,20 +8,20 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// xfail-test
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
 
 // compile-flags:-Z extra-debug-info
 // debugger:set print pretty off
 // debugger:break _zzz
 // debugger:run
 // debugger:finish
-// debugger:print a->boxed
+// debugger:print *a
 // check:$1 = 1
-// debugger:print b->boxed
+// debugger:print *b
 // check:$2 = {2, 3.5}
-// debugger:print c->boxed
+// debugger:print c->val
 // check:$3 = 4
-// debugger:print d->boxed
+// debugger:print d->val
 // check:$4 = false
 
 fn main() {
diff --git a/src/test/debug-info/boxed-struct.rs b/src/test/debug-info/boxed-struct.rs
new file mode 100644
index 00000000000..86162f0fa04
--- /dev/null
+++ b/src/test/debug-info/boxed-struct.rs
@@ -0,0 +1,59 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print *unique
+// check:$1 = {x = 99, y = 999, z = 9999, w = 99999}
+
+// debugger:print managed->val
+// check:$2 = {x = 88, y = 888, z = 8888, w = 88888}
+
+// debugger:print *unique_dtor
+// check:$3 = {x = 77, y = 777, z = 7777, w = 77777}
+
+// debugger:print managed_dtor->val
+// check:$4 = {x = 33, y = 333, z = 3333, w = 33333}
+
+struct StructWithSomePadding {
+    x: i16,
+    y: i32,
+    z: i32,
+    w: i64
+}
+
+struct StructWithDestructor {
+    x: i16,
+    y: i32,
+    z: i32,
+    w: i64
+}
+
+impl Drop for StructWithDestructor {
+    fn drop(&self) {}
+}
+
+fn main() {
+
+    let unique = ~StructWithSomePadding { x: 99, y: 999, z: 9999, w: 99999 };
+    let managed = @StructWithSomePadding { x: 88, y: 888, z: 8888, w: 88888 };
+
+    let unique_dtor = ~StructWithDestructor { x: 77, y: 777, z: 7777, w: 77777 };
+    let managed_dtor = @StructWithDestructor { x: 33, y: 333, z: 3333, w: 33333 };
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/boxed-vec.rs b/src/test/debug-info/boxed-vec.rs
new file mode 100644
index 00000000000..8abead65196
--- /dev/null
+++ b/src/test/debug-info/boxed-vec.rs
@@ -0,0 +1,36 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print managed->val.fill
+// check:$1 = 24
+// debugger:print *((uint64_t[3]*)(managed->val.elements))
+// check:$2 = {7, 8, 9}
+
+// debugger:print unique->fill
+// check:$3 = 32
+// debugger:print *((uint64_t[4]*)(unique->elements))
+// check:$4 = {10, 11, 12, 13}
+
+fn main() {
+
+    let managed: @[i64] = @[7, 8, 9];
+    let unique: ~[i64] = ~[10, 11, 12, 13];
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/c-style-enum-in-composite.rs b/src/test/debug-info/c-style-enum-in-composite.rs
new file mode 100644
index 00000000000..47e433ea814
--- /dev/null
+++ b/src/test/debug-info/c-style-enum-in-composite.rs
@@ -0,0 +1,119 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print tuple_interior_padding
+// check:$1 = {0, OneHundred}
+
+// debugger:print tuple_padding_at_end
+// check:$2 = {{1, OneThousand}, 2}
+
+// debugger:print tuple_different_enums
+// check:$3 = {OneThousand, MountainView, OneMillion, Vienna}
+
+// debugger:print padded_struct
+// check:$4 = {a = 3, b = OneMillion, c = 4, d = Toronto, e = 5}
+
+// debugger:print packed_struct
+// check:$5 = {a = 6, b = OneHundred, c = 7, d = Vienna, e = 8}
+
+// debugger:print non_padded_struct
+// check:$6 = {a = OneMillion, b = MountainView, c = OneThousand, d = Toronto}
+
+// debugger:print struct_with_drop
+// check:$7 = {{a = OneHundred, b = Vienna}, 9}
+
+enum AnEnum {
+    OneHundred = 100,
+    OneThousand = 1000,
+    OneMillion = 1000000
+}
+
+enum AnotherEnum {
+    MountainView,
+    Toronto,
+    Vienna
+}
+
+struct PaddedStruct {
+    a: i16,
+    b: AnEnum,
+    c: i16,
+    d: AnotherEnum,
+    e: i16
+}
+
+#[packed]
+struct PackedStruct {
+    a: i16,
+    b: AnEnum,
+    c: i16,
+    d: AnotherEnum,
+    e: i16
+}
+
+struct NonPaddedStruct {
+    a: AnEnum,
+    b: AnotherEnum,
+    c: AnEnum,
+    d: AnotherEnum
+}
+
+struct StructWithDrop {
+    a: AnEnum,
+    b: AnotherEnum
+}
+
+impl Drop for StructWithDrop {
+    fn drop(&self) {()}
+}
+
+fn main() {
+
+    let tuple_interior_padding = (0_i16, OneHundred);
+    // It will depend on the machine architecture if any padding is actually involved here
+    let tuple_padding_at_end = ((1_u64, OneThousand), 2_u64);
+    let tuple_different_enums = (OneThousand, MountainView, OneMillion, Vienna);
+
+    let padded_struct = PaddedStruct {
+        a: 3,
+        b: OneMillion,
+        c: 4,
+        d: Toronto,
+        e: 5
+    };
+
+    let packed_struct = PackedStruct {
+        a: 6,
+        b: OneHundred,
+        c: 7,
+        d: Vienna,
+        e: 8
+    };
+
+    let non_padded_struct = NonPaddedStruct {
+        a: OneMillion,
+        b: MountainView,
+        c: OneThousand,
+        d: Toronto
+    };
+
+    let struct_with_drop = (StructWithDrop { a: OneHundred, b: Vienna }, 9_i64);
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/c-style-enum.rs b/src/test/debug-info/c-style-enum.rs
new file mode 100644
index 00000000000..d7cce4e6f3f
--- /dev/null
+++ b/src/test/debug-info/c-style-enum.rs
@@ -0,0 +1,70 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print auto_one
+// check:$1 = One
+
+// debugger:print auto_two
+// check:$2 = Two
+
+// debugger:print auto_three
+// check:$3 = Three
+
+// debugger:print manual_one_hundred
+// check:$4 = OneHundred
+
+// debugger:print manual_one_thousand
+// check:$5 = OneThousand
+
+// debugger:print manual_one_million
+// check:$6 = OneMillion
+
+// debugger:print single_variant
+// check:$7 = TheOnlyVariant
+
+enum AutoDiscriminant {
+    One,
+    Two,
+    Three
+}
+
+enum ManualDiscriminant {
+    OneHundred = 100,
+    OneThousand = 1000,
+    OneMillion = 1000000
+}
+
+enum SingleVariant {
+    TheOnlyVariant
+}
+
+fn main() {
+
+    let auto_one = One;
+    let auto_two = Two;
+    let auto_three = Three;
+
+    let manual_one_hundred = OneHundred;
+    let manual_one_thousand = OneThousand;
+    let manual_one_million = OneMillion;
+
+    let single_variant = TheOnlyVariant;
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/destructured-local.rs b/src/test/debug-info/destructured-local.rs
index bf53d95b588..207899fe3b5 100644
--- a/src/test/debug-info/destructured-local.rs
+++ b/src/test/debug-info/destructured-local.rs
@@ -10,9 +10,6 @@
 
 // xfail-test
 
-// GDB doesn't know about UTF-32 character encoding and will print a rust char as only its numerical
-// value.
-
 // compile-flags:-Z extra-debug-info
 // debugger:break zzz
 // debugger:run
@@ -25,7 +22,7 @@
 // check:$2 = false
 
 fn main() {
-    let (a, b) : (int, bool) = (9898, false);
+    let (a, b): (int, bool) = (9898, false);
 
     zzz();
 }
diff --git a/src/test/debug-info/evec-in-struct.rs b/src/test/debug-info/evec-in-struct.rs
new file mode 100644
index 00000000000..7e42690548e
--- /dev/null
+++ b/src/test/debug-info/evec-in-struct.rs
@@ -0,0 +1,88 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:set print pretty off
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print no_padding1
+// check:$1 = {x = {0, 1, 2}, y = -3, z = {4.5, 5.5}}
+// debugger:print no_padding2
+// check:$2 = {x = {6, 7, 8}, y = {{9, 10}, {11, 12}}}
+
+// debugger:print struct_internal_padding
+// check:$3 = {x = {13, 14}, y = {15, 16}}
+
+// debugger:print single_vec
+// check:$4 = {x = {17, 18, 19, 20, 21}}
+
+// debugger:print struct_padded_at_end
+// check:$5 = {x = {22, 23}, y = {24, 25}}
+
+struct NoPadding1 {
+    x: [u32, ..3],
+    y: i32,
+    z: [f32, ..2]
+}
+
+struct NoPadding2 {
+    x: [u32, ..3],
+    y: [[u32, ..2], ..2]
+}
+
+struct StructInternalPadding {
+    x: [i16, ..2],
+    y: [i64, ..2]
+}
+
+struct SingleVec {
+    x: [i16, ..5]
+}
+
+struct StructPaddedAtEnd {
+    x: [i64, ..2],
+    y: [i16, ..2]
+}
+
+fn main() {
+
+    let no_padding1 = NoPadding1 {
+        x: [0, 1, 2],
+        y: -3,
+        z: [4.5, 5.5]
+    };
+
+    let no_padding2 = NoPadding2 {
+        x: [6, 7, 8],
+        y: [[9, 10], [11, 12]]
+    };
+
+    let struct_internal_padding = StructInternalPadding {
+        x: [13, 14],
+        y: [15, 16]
+    };
+
+    let single_vec = SingleVec {
+        x: [17, 18, 19, 20, 21]
+    };
+
+    let struct_padded_at_end = StructPaddedAtEnd {
+        x: [22, 23],
+        y: [24, 25]
+    };
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/function-arguments.rs b/src/test/debug-info/function-arguments.rs
index f5563cda259..225dfedfec7 100644
--- a/src/test/debug-info/function-arguments.rs
+++ b/src/test/debug-info/function-arguments.rs
@@ -10,9 +10,6 @@
 
 // xfail-test
 
-// GDB doesn't know about UTF-32 character encoding and will print a rust char as only its numerical
-// value.
-
 // compile-flags:-Z extra-debug-info
 // debugger:break zzz
 // debugger:run
diff --git a/src/test/debug-info/managed-enum.rs b/src/test/debug-info/managed-enum.rs
new file mode 100644
index 00000000000..1a3600a7d8c
--- /dev/null
+++ b/src/test/debug-info/managed-enum.rs
@@ -0,0 +1,63 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print the_a->val
+// check:$1 = {{TheA, x = 0, y = 8970181431921507452}, {TheA, 0, 2088533116, 2088533116}}
+
+// debugger:print the_b->val
+// check:$2 = {{TheB, x = 0, y = 1229782938247303441}, {TheB, 0, 286331153, 286331153}}
+
+// debugger:print univariant->val
+// check:$3 = {-9747455}
+
+// The first element is to ensure proper alignment, irrespective of the machines word size. Since
+// the size of the discriminant value is machine dependent, this has be taken into account when
+// datatype layout should be predictable as in this case.
+enum ABC {
+	TheA { x: i64, y: i64 },
+	TheB (i64, i32, i32),
+}
+
+// This is a special case since it does not have the implicit discriminant field.
+enum Univariant {
+    TheOnlyCase(i64)
+}
+
+fn main() {
+
+    // In order to avoid endianess trouble all of the following test values consist of a single
+    // repeated byte. This way each interpretation of the union should look the same, no matter if
+    // this is a big or little endian machine.
+
+	// 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
+	// 0b01111100011111000111110001111100 = 2088533116
+	// 0b0111110001111100 = 31868
+	// 0b01111100 = 124
+    let the_a = @TheA { x: 0, y: 8970181431921507452 };
+
+    // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
+    // 0b00010001000100010001000100010001 = 286331153
+    // 0b0001000100010001 = 4369
+    // 0b00010001 = 17
+    let the_b = @TheB (0, 286331153, 286331153);
+
+    let univariant = @TheOnlyCase(-9747455);
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/managed-pointer-within-unique-vec.rs b/src/test/debug-info/managed-pointer-within-unique-vec.rs
new file mode 100644
index 00000000000..e42631599a9
--- /dev/null
+++ b/src/test/debug-info/managed-pointer-within-unique-vec.rs
@@ -0,0 +1,37 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print unique->val.elements[0]->val
+// check:$1 = 10
+
+// debugger:print unique->val.elements[1]->val
+// check:$2 = 11
+
+// debugger:print unique->val.elements[2]->val
+// check:$3 = 12
+
+// debugger:print unique->val.elements[3]->val
+// check:$4 = 13
+
+fn main() {
+
+    let unique: ~[@i64] = ~[@10, @11, @12, @13];
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/managed-pointer-within-unique.rs b/src/test/debug-info/managed-pointer-within-unique.rs
new file mode 100644
index 00000000000..3eb1c2ef01e
--- /dev/null
+++ b/src/test/debug-info/managed-pointer-within-unique.rs
@@ -0,0 +1,47 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:set print pretty off
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print *ordinary_unique
+// check:$1 = {-1, -2}
+
+// debugger:print managed_within_unique.val->x
+// check:$2 = -3
+
+// debugger:print managed_within_unique.val->y->val
+// check:$3 = -4
+
+struct ContainsManaged
+{
+	x: int,
+	y: @int
+}
+
+fn main() {
+
+	let ordinary_unique = ~(-1, -2);
+
+
+	// This is a special case: Normally values allocated in the exchange heap are not boxed, unless,
+	// however, if they contain managed pointers.
+	// This test case verifies that both cases are handled correctly.
+    let managed_within_unique = ~ContainsManaged { x: -3, y: @-4 };
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/nil-enum.rs b/src/test/debug-info/nil-enum.rs
new file mode 100644
index 00000000000..d3afd4b11f9
--- /dev/null
+++ b/src/test/debug-info/nil-enum.rs
@@ -0,0 +1,40 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print first
+// check:$1 = {<No data fields>}
+
+// debugger:print second
+// check:$2 = {<No data fields>}
+
+enum ANilEnum {}
+enum AnotherNilEnum {}
+
+// I (mw) am not sure this test case makes much sense...
+// Also, it relies on some implementation details:
+// 1. That empty enums as well as '()' are represented as empty structs
+// 2. That gdb prints the string "{<No data fields>}" for empty structs (which may change some time)
+fn main() {
+    unsafe {
+        let first: ANilEnum = std::cast::transmute(());
+        let second: AnotherNilEnum = std::cast::transmute(());
+
+        zzz();
+    }
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/option-like-enum.rs b/src/test/debug-info/option-like-enum.rs
new file mode 100644
index 00000000000..6d3b157d63e
--- /dev/null
+++ b/src/test/debug-info/option-like-enum.rs
@@ -0,0 +1,71 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print some
+// check:$1 = {0x12345678}
+
+// debugger:print none
+// check:$2 = {0x0}
+
+// debugger:print full
+// check:$3 = {454545, 0x87654321, 9988}
+
+// debugger:print empty
+// check:$4 = {0, 0x0, 0}
+
+// debugger:print droid
+// check:$5 = {id = 675675, range = 10000001, internals = 0x43218765}
+
+// debugger:print void_droid
+// check:$6 = {id = 0, range = 0, internals = 0x0}
+
+
+// If a struct has exactly two variants, one of them is empty, and the other one
+// contains a non-nullable pointer, then this value is used as the discriminator.
+// The test cases in this file make sure that something readable is generated for
+// this kind of types.
+
+enum MoreFields<'self> {
+    Full(u32, &'self int, i16),
+    Empty
+}
+
+enum NamedFields<'self> {
+    Droid { id: i32, range: i64, internals: &'self int },
+    Void
+}
+
+fn main() {
+
+    let some: Option<&u32> = Some(unsafe { std::cast::transmute(0x12345678) });
+    let none: Option<&u32> = None;
+
+    let full = Full(454545, unsafe { std::cast::transmute(0x87654321) }, 9988);
+
+    let int_val = 0;
+    let mut empty = Full(0, &int_val, 0);
+    empty = Empty;
+
+    let droid = Droid { id: 675675, range: 10000001, internals: unsafe { std::cast::transmute(0x43218765) } };
+
+    let mut void_droid = Droid { id: 0, range: 0, internals: &int_val };
+    void_droid = Void;
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/packed-struct-with-destructor.rs b/src/test/debug-info/packed-struct-with-destructor.rs
new file mode 100644
index 00000000000..9ff91aa00d1
--- /dev/null
+++ b/src/test/debug-info/packed-struct-with-destructor.rs
@@ -0,0 +1,219 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:set print pretty off
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print packed
+// check:$1 = {x = 123, y = 234, z = 345}
+
+// debugger:print packedInPacked
+// check:$2 = {a = 1111, b = {x = 2222, y = 3333, z = 4444}, c = 5555, d = {x = 6666, y = 7777, z = 8888}}
+
+// debugger:print packedInUnpacked
+// check:$3 = {a = -1111, b = {x = -2222, y = -3333, z = -4444}, c = -5555, d = {x = -6666, y = -7777, z = -8888}}
+
+// debugger:print unpackedInPacked
+// check:$4 = {a = 987, b = {x = 876, y = 765, z = 654}, c = {x = 543, y = 432, z = 321}, d = 210}
+
+
+// debugger:print packedInPackedWithDrop
+// check:$5 = {a = 11, b = {x = 22, y = 33, z = 44}, c = 55, d = {x = 66, y = 77, z = 88}}
+
+// debugger:print packedInUnpackedWithDrop
+// check:$6 = {a = -11, b = {x = -22, y = -33, z = -44}, c = -55, d = {x = -66, y = -77, z = -88}}
+
+// debugger:print unpackedInPackedWithDrop
+// check:$7 = {a = 98, b = {x = 87, y = 76, z = 65}, c = {x = 54, y = 43, z = 32}, d = 21}
+
+// debugger:print deeplyNested
+// check:$8 = {a = {a = 1, b = {x = 2, y = 3, z = 4}, c = 5, d = {x = 6, y = 7, z = 8}}, b = {a = 9, b = {x = 10, y = 11, z = 12}, c = {x = 13, y = 14, z = 15}, d = 16}, c = {a = 17, b = {x = 18, y = 19, z = 20}, c = 21, d = {x = 22, y = 23, z = 24}}, d = {a = 25, b = {x = 26, y = 27, z = 28}, c = 29, d = {x = 30, y = 31, z = 32}}, e = {a = 33, b = {x = 34, y = 35, z = 36}, c = {x = 37, y = 38, z = 39}, d = 40}, f = {a = 41, b = {x = 42, y = 43, z = 44}, c = 45, d = {x = 46, y = 47, z = 48}}}
+
+#[packed]
+struct Packed {
+    x: i16,
+    y: i32,
+    z: i64
+}
+
+impl Drop for Packed {
+    fn drop(&self) {}
+}
+
+#[packed]
+struct PackedInPacked {
+    a: i32,
+    b: Packed,
+    c: i64,
+    d: Packed
+}
+
+struct PackedInUnpacked {
+    a: i32,
+    b: Packed,
+    c: i64,
+    d: Packed
+}
+
+struct Unpacked {
+    x: i64,
+    y: i32,
+    z: i16
+}
+
+impl Drop for Unpacked {
+    fn drop(&self) {}
+}
+
+#[packed]
+struct UnpackedInPacked {
+    a: i16,
+    b: Unpacked,
+    c: Unpacked,
+    d: i64
+}
+
+#[packed]
+struct PackedInPackedWithDrop {
+    a: i32,
+    b: Packed,
+    c: i64,
+    d: Packed
+}
+
+impl Drop for PackedInPackedWithDrop {
+    fn drop(&self) {}
+}
+
+struct PackedInUnpackedWithDrop {
+    a: i32,
+    b: Packed,
+    c: i64,
+    d: Packed
+}
+
+impl Drop for PackedInUnpackedWithDrop {
+    fn drop(&self) {}
+}
+
+#[packed]
+struct UnpackedInPackedWithDrop {
+    a: i16,
+    b: Unpacked,
+    c: Unpacked,
+    d: i64
+}
+
+impl Drop for UnpackedInPackedWithDrop {
+    fn drop(&self) {}
+}
+
+struct DeeplyNested {
+    a: PackedInPacked,
+    b: UnpackedInPackedWithDrop,
+    c: PackedInUnpacked,
+    d: PackedInUnpackedWithDrop,
+    e: UnpackedInPacked,
+    f: PackedInPackedWithDrop
+}
+
+fn main() {
+    let packed = Packed { x: 123, y: 234, z: 345 };
+
+    let packedInPacked = PackedInPacked {
+        a: 1111,
+        b: Packed { x: 2222, y: 3333, z: 4444 },
+        c: 5555,
+        d: Packed { x: 6666, y: 7777, z: 8888 }
+    };
+
+    let packedInUnpacked = PackedInUnpacked {
+        a: -1111,
+        b: Packed { x: -2222, y: -3333, z: -4444 },
+        c: -5555,
+        d: Packed { x: -6666, y: -7777, z: -8888 }
+    };
+
+    let unpackedInPacked = UnpackedInPacked {
+        a: 987,
+        b: Unpacked { x: 876, y: 765, z: 654 },
+        c: Unpacked { x: 543, y: 432, z: 321 },
+        d: 210
+    };
+
+    let packedInPackedWithDrop = PackedInPackedWithDrop {
+        a: 11,
+        b: Packed { x: 22, y: 33, z: 44 },
+        c: 55,
+        d: Packed { x: 66, y: 77, z: 88 }
+    };
+
+    let packedInUnpackedWithDrop = PackedInUnpackedWithDrop {
+        a: -11,
+        b: Packed { x: -22, y: -33, z: -44 },
+        c: -55,
+        d: Packed { x: -66, y: -77, z: -88 }
+    };
+
+    let unpackedInPackedWithDrop = UnpackedInPackedWithDrop {
+        a: 98,
+        b: Unpacked { x: 87, y: 76, z: 65 },
+        c: Unpacked { x: 54, y: 43, z: 32 },
+        d: 21
+    };
+
+    let deeplyNested = DeeplyNested {
+        a: PackedInPacked {
+            a: 1,
+            b: Packed { x: 2, y: 3, z: 4 },
+            c: 5,
+            d: Packed { x: 6, y: 7, z: 8 }
+        },
+        b: UnpackedInPackedWithDrop {
+            a: 9,
+            b: Unpacked { x: 10, y: 11, z: 12 },
+            c: Unpacked { x: 13, y: 14, z: 15 },
+            d: 16
+        },
+        c: PackedInUnpacked {
+            a: 17,
+            b: Packed { x: 18, y: 19, z: 20 },
+            c: 21,
+            d: Packed { x: 22, y: 23, z: 24 }
+        },
+        d: PackedInUnpackedWithDrop {
+            a: 25,
+            b: Packed { x: 26, y: 27, z: 28 },
+            c: 29,
+            d: Packed { x: 30, y: 31, z: 32 }
+        },
+        e: UnpackedInPacked {
+            a: 33,
+            b: Unpacked { x: 34, y: 35, z: 36 },
+            c: Unpacked { x: 37, y: 38, z: 39 },
+            d: 40
+        },
+        f: PackedInPackedWithDrop {
+            a: 41,
+            b: Packed { x: 42, y: 43, z: 44 },
+            c: 45,
+            d: Packed { x: 46, y: 47, z: 48 }
+        }
+    };
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/packed-struct.rs b/src/test/debug-info/packed-struct.rs
new file mode 100644
index 00000000000..859166cb023
--- /dev/null
+++ b/src/test/debug-info/packed-struct.rs
@@ -0,0 +1,104 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:set print pretty off
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print packed
+// check:$1 = {x = 123, y = 234, z = 345}
+
+// debugger:print packedInPacked
+// check:$2 = {a = 1111, b = {x = 2222, y = 3333, z = 4444}, c = 5555, d = {x = 6666, y = 7777, z = 8888}}
+
+// debugger:print packedInUnpacked
+// check:$3 = {a = -1111, b = {x = -2222, y = -3333, z = -4444}, c = -5555, d = {x = -6666, y = -7777, z = -8888}}
+
+// debugger:print unpackedInPacked
+// check:$4 = {a = 987, b = {x = 876, y = 765, z = 654, w = 543}, c = {x = 432, y = 321, z = 210, w = 109}, d = -98}
+
+// debugger:print sizeof(packed)
+// check:$5 = 14
+
+// debugger:print sizeof(packedInPacked)
+// check:$6 = 40
+
+#[packed]
+struct Packed {
+    x: i16,
+    y: i32,
+    z: i64
+}
+
+#[packed]
+struct PackedInPacked {
+    a: i32,
+    b: Packed,
+    c: i64,
+    d: Packed
+}
+
+// layout (64 bit): aaaa bbbb bbbb bbbb bb.. .... cccc cccc dddd dddd dddd dd..
+struct PackedInUnpacked {
+    a: i32,
+    b: Packed,
+    c: i64,
+    d: Packed
+}
+
+// layout (64 bit): xx.. yyyy zz.. .... wwww wwww
+struct Unpacked {
+    x: i16,
+    y: i32,
+    z: i16,
+    w: i64
+}
+
+// layout (64 bit): aabb bbbb bbbb bbbb bbbb bbbb bbcc cccc cccc cccc cccc cccc ccdd dddd dd
+#[packed]
+struct UnpackedInPacked {
+    a: i16,
+    b: Unpacked,
+    c: Unpacked,
+    d: i64
+}
+
+fn main() {
+    let packed = Packed { x: 123, y: 234, z: 345 };
+
+    let packedInPacked = PackedInPacked {
+        a: 1111,
+        b: Packed { x: 2222, y: 3333, z: 4444 },
+        c: 5555,
+        d: Packed { x: 6666, y: 7777, z: 8888 }
+    };
+
+    let packedInUnpacked = PackedInUnpacked {
+        a: -1111,
+        b: Packed { x: -2222, y: -3333, z: -4444 },
+        c: -5555,
+        d: Packed { x: -6666, y: -7777, z: -8888 }
+    };
+
+    let unpackedInPacked = UnpackedInPacked {
+        a: 987,
+        b: Unpacked { x: 876, y: 765, z: 654, w: 543 },
+        c: Unpacked { x: 432, y: 321, z: 210, w: 109 },
+        d: -98
+    };
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/simple-tuple.rs b/src/test/debug-info/simple-tuple.rs
index 84c736fab6b..f45294221af 100644
--- a/src/test/debug-info/simple-tuple.rs
+++ b/src/test/debug-info/simple-tuple.rs
@@ -35,15 +35,15 @@
 
 
 fn main() {
-    let noPadding8 : (i8, u8) = (-100, 100);
-    let noPadding16 : (i16, i16, u16) = (0, 1, 2);
-    let noPadding32 : (i32, f32, u32) = (3, 4.5, 5);
-    let noPadding64 : (i64, f64, u64) = (6, 7.5, 8);
+    let noPadding8: (i8, u8) = (-100, 100);
+    let noPadding16: (i16, i16, u16) = (0, 1, 2);
+    let noPadding32: (i32, f32, u32) = (3, 4.5, 5);
+    let noPadding64: (i64, f64, u64) = (6, 7.5, 8);
 
-    let internalPadding1 : (i16, i32) = (9, 10);
-    let internalPadding2 : (i16, i32, u32, u64) = (11, 12, 13, 14);
+    let internalPadding1: (i16, i32) = (9, 10);
+    let internalPadding2: (i16, i32, u32, u64) = (11, 12, 13, 14);
 
-    let paddingAtEnd : (i32, i16) = (15, 16);
+    let paddingAtEnd: (i32, i16) = (15, 16);
 
     zzz();
 }
diff --git a/src/test/debug-info/struct-in-enum.rs b/src/test/debug-info/struct-in-enum.rs
new file mode 100644
index 00000000000..1002266a1a9
--- /dev/null
+++ b/src/test/debug-info/struct-in-enum.rs
@@ -0,0 +1,69 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:set print union on
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print case1
+// check:$1 = {{Case1, 0, {x = 2088533116, y = 2088533116, z = 31868}}, {Case1, 0, 8970181431921507452, 31868}}
+
+// debugger:print case2
+// check:$2 = {{Case2, 0, {x = 286331153, y = 286331153, z = 4369}}, {Case2, 0, 1229782938247303441, 4369}}
+
+// debugger:print univariant
+// check:$3 = {{x = 123, y = 456, z = 789}}
+
+struct Struct {
+	x: u32,
+	y: i32,
+	z: i16
+}
+
+// The first element is to ensure proper alignment, irrespective of the machines word size. Since
+// the size of the discriminant value is machine dependent, this has be taken into account when
+// datatype layout should be predictable as in this case.
+enum Regular {
+    Case1(u64, Struct),
+    Case2(u64, u64, i16)
+}
+
+enum Univariant {
+	TheOnlyCase(Struct)
+}
+
+fn main() {
+
+    // In order to avoid endianess trouble all of the following test values consist of a single
+    // repeated byte. This way each interpretation of the union should look the same, no matter if
+    // this is a big or little endian machine.
+
+    // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
+    // 0b01111100011111000111110001111100 = 2088533116
+    // 0b0111110001111100 = 31868
+    // 0b01111100 = 124
+    let case1 = Case1(0, Struct { x: 2088533116, y: 2088533116, z: 31868 });
+
+    // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
+    // 0b00010001000100010001000100010001 = 286331153
+    // 0b0001000100010001 = 4369
+    // 0b00010001 = 17
+    let case2 = Case2(0, 1229782938247303441, 4369);
+
+    let univariant = TheOnlyCase(Struct { x: 123, y: 456, z: 789 });
+
+    zzz();
+}
+
+fn zzz() {()}
diff --git a/src/test/debug-info/struct-style-enum.rs b/src/test/debug-info/struct-style-enum.rs
new file mode 100644
index 00000000000..61bbd2e215f
--- /dev/null
+++ b/src/test/debug-info/struct-style-enum.rs
@@ -0,0 +1,73 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:set print union on
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print case1
+// check:$1 = {{Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {Case1, a = 0, b = 2088533116, c = 2088533116}, {Case1, a = 0, b = 8970181431921507452}}
+
+// debugger:print case2
+// check:$2 = {{Case2, a = 0, b = 4369, c = 4369, d = 4369, e = 4369}, {Case2, a = 0, b = 286331153, c = 286331153}, {Case2, a = 0, b = 1229782938247303441}}
+
+// debugger:print case3
+// check:$3 = {{Case3, a = 0, b = 22873, c = 22873, d = 22873, e = 22873}, {Case3, a = 0, b = 1499027801, c = 1499027801}, {Case3, a = 0, b = 6438275382588823897}}
+
+// debugger:print univariant
+// check:$4 = {a = -1}
+
+// The first element is to ensure proper alignment, irrespective of the machines word size. Since
+// the size of the discriminant value is machine dependent, this has be taken into account when
+// datatype layout should be predictable as in this case.
+enum Regular {
+    Case1 { a: u64, b: u16, c: u16, d: u16, e: u16},
+    Case2 { a: u64, b: u32, c: u32},
+    Case3 { a: u64, b: u64 }
+}
+
+enum Univariant {
+    TheOnlyCase { a: i64 }
+}
+
+fn main() {
+
+    // In order to avoid endianess trouble all of the following test values consist of a single
+    // repeated byte. This way each interpretation of the union should look the same, no matter if
+    // this is a big or little endian machine.
+
+    // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
+    // 0b01111100011111000111110001111100 = 2088533116
+    // 0b0111110001111100 = 31868
+    // 0b01111100 = 124
+    let case1 = Case1 { a: 0, b: 31868, c: 31868, d: 31868, e: 31868 };
+
+    // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
+    // 0b00010001000100010001000100010001 = 286331153
+    // 0b0001000100010001 = 4369
+    // 0b00010001 = 17
+    let case2 = Case2 { a: 0, b: 286331153, c: 286331153 };
+
+    // 0b0101100101011001010110010101100101011001010110010101100101011001 = 6438275382588823897
+    // 0b01011001010110010101100101011001 = 1499027801
+    // 0b0101100101011001 = 22873
+    // 0b01011001 = 89
+    let case3 = Case3 { a: 0, b: 6438275382588823897 };
+
+    let univariant = TheOnlyCase { a: -1 };
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/struct-with-destructor.rs b/src/test/debug-info/struct-with-destructor.rs
index f8281bba49e..0719f64b256 100644
--- a/src/test/debug-info/struct-with-destructor.rs
+++ b/src/test/debug-info/struct-with-destructor.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// xfail-test
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
 
 // compile-flags:-Z extra-debug-info
 // debugger:break zzz
@@ -23,18 +23,21 @@
 // debugger:print withDestructor
 // check:$3 = {a = {x = 10, y = 20}, guard = -1}
 
+// debugger:print nested
+// check:$4 = {a = {a = {x = 7890, y = 9870}}}
+
 struct NoDestructor {
-    x : i32,
-    y : i64
+    x: i32,
+    y: i64
 }
 
 struct WithDestructor {
-    x : i32,
-    y : i64
+    x: i32,
+    y: i64
 }
 
 impl Drop for WithDestructor {
-    fn finalize(&self) {}
+    fn drop(&self) {}
 }
 
 struct NoDestructorGuarded {
@@ -47,6 +50,18 @@ struct WithDestructorGuarded {
     guard: i64
 }
 
+struct NestedInner {
+    a: WithDestructor
+}
+
+impl Drop for NestedInner {
+    fn drop(&self) {}
+}
+
+struct NestedOuter {
+    a: NestedInner
+}
+
 
 // The compiler adds a 'destructed' boolean field to structs implementing Drop. This field is used
 // at runtime to prevent drop() to be executed more than once (see middle::trans::adt).
@@ -65,6 +80,8 @@ fn main() {
     // then the debugger will have an invalid offset for the field 'guard' and thus should not be
     // able to read its value correctly (dots are padding bytes, D is the boolean destructor flag):
     //
+    // 64 bit
+    //
     // NoDestructorGuarded = 0000....00000000FFFFFFFF
     //                       <--------------><------>
     //                         NoDestructor   guard
@@ -77,11 +94,31 @@ fn main() {
     //                         <----------------------><------>  // How it actually is
     //                              WithDestructor      guard
     //
+    // 32 bit
+    //
+    // NoDestructorGuarded = 000000000000FFFFFFFF
+    //                       <----------><------>
+    //                       NoDestructor guard
+    //
+    //
+    // withDestructorGuarded = 000000000000D...FFFFFFFF
+    //                         <----------><------>      // How debug info says it is
+    //                      WithDestructor  guard
+    //
+    //                         <--------------><------>  // How it actually is
+    //                          WithDestructor  guard
+    //
     let withDestructor = WithDestructorGuarded {
         a: WithDestructor { x: 10, y: 20 },
         guard: -1
     };
 
+    // expected layout (64 bit) = xxxx....yyyyyyyyD.......D...
+    //                            <--WithDestructor------>
+    //                            <-------NestedInner-------->
+    //                            <-------NestedOuter-------->
+    let nested = NestedOuter { a: NestedInner { a: WithDestructor { x: 7890, y: 9870 } } };
+
     zzz();
 }
 
diff --git a/src/test/debug-info/tuple-in-tuple.rs b/src/test/debug-info/tuple-in-tuple.rs
index 13f8719694e..9c6805dae67 100644
--- a/src/test/debug-info/tuple-in-tuple.rs
+++ b/src/test/debug-info/tuple-in-tuple.rs
@@ -34,15 +34,15 @@
 // check:$7 = {{21, 22}, 23}
 
 fn main() {
-    let no_padding1 : ((u32, u32), u32, u32) = ((0, 1), 2, 3);
-    let no_padding2 : (u32, (u32, u32), u32) = (4, (5, 6), 7);
-    let no_padding3 : (u32, u32, (u32, u32)) = (8, 9, (10, 11));
+    let no_padding1: ((u32, u32), u32, u32) = ((0, 1), 2, 3);
+    let no_padding2: (u32, (u32, u32), u32) = (4, (5, 6), 7);
+    let no_padding3: (u32, u32, (u32, u32)) = (8, 9, (10, 11));
 
-    let internal_padding1 : (i16, (i32, i32)) = (12, (13, 14));
-    let internal_padding2 : (i16, (i16, i32)) = (15, (16, 17));
+    let internal_padding1: (i16, (i32, i32)) = (12, (13, 14));
+    let internal_padding2: (i16, (i16, i32)) = (15, (16, 17));
 
-    let padding_at_end1 : (i32, (i32, i16)) = (18, (19, 20));
-    let padding_at_end2 : ((i32, i16), i32) = ((21, 22), 23);
+    let padding_at_end1: (i32, (i32, i16)) = (18, (19, 20));
+    let padding_at_end2: ((i32, i16), i32) = ((21, 22), 23);
 
     zzz();
 }
diff --git a/src/test/debug-info/tuple-style-enum.rs b/src/test/debug-info/tuple-style-enum.rs
new file mode 100644
index 00000000000..ba1d02bb62a
--- /dev/null
+++ b/src/test/debug-info/tuple-style-enum.rs
@@ -0,0 +1,73 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:set print union on
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print case1
+// check:$1 = {{Case1, 0, 31868, 31868, 31868, 31868}, {Case1, 0, 2088533116, 2088533116}, {Case1, 0, 8970181431921507452}}
+
+// debugger:print case2
+// check:$2 = {{Case2, 0, 4369, 4369, 4369, 4369}, {Case2, 0, 286331153, 286331153}, {Case2, 0, 1229782938247303441}}
+
+// debugger:print case3
+// check:$3 = {{Case3, 0, 22873, 22873, 22873, 22873}, {Case3, 0, 1499027801, 1499027801}, {Case3, 0, 6438275382588823897}}
+
+// debugger:print univariant
+// check:$4 = {-1}
+
+// The first element is to ensure proper alignment, irrespective of the machines word size. Since
+// the size of the discriminant value is machine dependent, this has be taken into account when
+// datatype layout should be predictable as in this case.
+enum Regular {
+    Case1(u64, u16, u16, u16, u16),
+    Case2(u64, u32, u32),
+    Case3(u64, u64)
+}
+
+enum Univariant {
+	TheOnlyCase(i64)
+}
+
+fn main() {
+
+    // In order to avoid endianess trouble all of the following test values consist of a single
+    // repeated byte. This way each interpretation of the union should look the same, no matter if
+    // this is a big or little endian machine.
+
+    // 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
+    // 0b01111100011111000111110001111100 = 2088533116
+    // 0b0111110001111100 = 31868
+    // 0b01111100 = 124
+    let case1 = Case1(0, 31868, 31868, 31868, 31868);
+
+    // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
+    // 0b00010001000100010001000100010001 = 286331153
+    // 0b0001000100010001 = 4369
+    // 0b00010001 = 17
+    let case2 = Case2(0, 286331153, 286331153);
+
+    // 0b0101100101011001010110010101100101011001010110010101100101011001 = 6438275382588823897
+    // 0b01011001010110010101100101011001 = 1499027801
+    // 0b0101100101011001 = 22873
+    // 0b01011001 = 89
+    let case3 = Case3(0, 6438275382588823897);
+
+    let univariant = TheOnlyCase(-1);
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/unique-enum.rs b/src/test/debug-info/unique-enum.rs
new file mode 100644
index 00000000000..443f641a858
--- /dev/null
+++ b/src/test/debug-info/unique-enum.rs
@@ -0,0 +1,63 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+
+// debugger:print *the_a
+// check:$1 = {{TheA, x = 0, y = 8970181431921507452}, {TheA, 0, 2088533116, 2088533116}}
+
+// debugger:print *the_b
+// check:$2 = {{TheB, x = 0, y = 1229782938247303441}, {TheB, 0, 286331153, 286331153}}
+
+// debugger:print *univariant
+// check:$3 = {123234}
+
+// The first element is to ensure proper alignment, irrespective of the machines word size. Since
+// the size of the discriminant value is machine dependent, this has be taken into account when
+// datatype layout should be predictable as in this case.
+enum ABC {
+	TheA { x: i64, y: i64 },
+	TheB (i64, i32, i32),
+}
+
+// This is a special case since it does not have the implicit discriminant field.
+enum Univariant {
+    TheOnlyCase(i64)
+}
+
+fn main() {
+
+    // In order to avoid endianess trouble all of the following test values consist of a single
+    // repeated byte. This way each interpretation of the union should look the same, no matter if
+    // this is a big or little endian machine.
+
+	// 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
+	// 0b01111100011111000111110001111100 = 2088533116
+	// 0b0111110001111100 = 31868
+	// 0b01111100 = 124
+    let the_a = ~TheA { x: 0, y: 8970181431921507452 };
+
+    // 0b0001000100010001000100010001000100010001000100010001000100010001 = 1229782938247303441
+    // 0b00010001000100010001000100010001 = 286331153
+    // 0b0001000100010001 = 4369
+    // 0b00010001 = 17
+    let the_b = ~TheB (0, 286331153, 286331153);
+
+    let univariant = ~TheOnlyCase(123234);
+
+    zzz();
+}
+
+fn zzz() {()}
\ No newline at end of file
diff --git a/src/test/debug-info/vec-slices.rs b/src/test/debug-info/vec-slices.rs
new file mode 100644
index 00000000000..4691de04917
--- /dev/null
+++ b/src/test/debug-info/vec-slices.rs
@@ -0,0 +1,72 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
+
+// compile-flags:-Z extra-debug-info
+// debugger:set print pretty off
+// debugger:break zzz
+// debugger:run
+// debugger:finish
+// debugger:print empty.size_in_bytes
+// check:$1 = 0
+
+// debugger:print singleton.size_in_bytes
+// check:$2 = 8
+// debugger:print *((int64_t[1]*)(singleton.data_ptr))
+// check:$3 = {1}
+
+// debugger:print multiple.size_in_bytes
+// check:$4 = 32
+// debugger:print *((int64_t[4]*)(multiple.data_ptr))
+// check:$5 = {2, 3, 4, 5}
+
+// debugger:print slice_of_slice.size_in_bytes
+// check:$6 = 16
+// debugger:print *((int64_t[2]*)(slice_of_slice.data_ptr))
+// check:$7 = {3, 4}
+
+// debugger:print padded_tuple.size_in_bytes
+// check:$8 = 16
+// debugger:print padded_tuple.data_ptr[0]
+// check:$9 = {6, 7}
+// debugger:print padded_tuple.data_ptr[1]
+// check:$10 = {8, 9}
+
+// debugger:print padded_struct.size_in_bytes
+// check:$11 = 24
+// debugger:print padded_struct.data_ptr[0]
+// check:$12 = {x = 10, y = 11, z = 12}
+// debugger:print padded_struct.data_ptr[1]
+// check:$13 = {x = 13, y = 14, z = 15}
+
+struct AStruct {
+    x: i16,
+    y: i32,
+    z: i16
+}
+
+fn main() {
+    let empty: &[i64] = &[];
+    let singleton: &[i64] = &[1];
+    let multiple: &[i64] = &[2, 3, 4, 5];
+    let slice_of_slice = multiple.slice(1,3);
+
+    let padded_tuple: &[(i32, i16)] = &[(6, 7), (8, 9)];
+
+    let padded_struct: &[AStruct] = &[
+        AStruct { x: 10, y: 11, z: 12 },
+        AStruct { x: 13, y: 14, z: 15 }
+    ];
+
+    zzz();
+}
+
+fn zzz() {()}
diff --git a/src/test/debug-info/vec.rs b/src/test/debug-info/vec.rs
index f198a53729e..57130b45eae 100644
--- a/src/test/debug-info/vec.rs
+++ b/src/test/debug-info/vec.rs
@@ -8,28 +8,20 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// xfail-test
+// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
 
 // compile-flags:-Z extra-debug-info
 // debugger:set print pretty off
-// debugger:break _zzz
+// debugger:break zzz
 // debugger:run
 // debugger:finish
 // debugger:print a
 // check:$1 = {1, 2, 3}
-// debugger:print b.vec[0]
-// check:$2 = 4
-// debugger:print c->boxed.data[1]
-// check:$3 = 8
-// debugger:print d->boxed.data[2]
-// check:$4 = 12
 
 fn main() {
     let a = [1, 2, 3];
-    let b = &[4, 5, 6];
-    let c = @[7, 8, 9];
-    let d = ~[10, 11, 12];
-    _zzz();
+
+    zzz();
 }
 
-fn _zzz() {()}
+fn zzz() {()}
diff --git a/src/test/run-pass/issue-7712.rs b/src/test/run-pass/issue-7712.rs
new file mode 100644
index 00000000000..d4faae415d2
--- /dev/null
+++ b/src/test/run-pass/issue-7712.rs
@@ -0,0 +1,27 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags:-Z debug-info
+
+#[allow(default_methods)];
+
+pub trait TraitWithDefaultMethod {
+    pub fn method(self) {
+        ()
+    }
+}
+
+struct MyStruct;
+
+impl TraitWithDefaultMethod for MyStruct { }
+
+fn main() {
+    MyStruct.method();
+}
\ No newline at end of file