about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-09-11 06:26:05 -0700
committerbors <bors@rust-lang.org>2013-09-11 06:26:05 -0700
commit67ed30cd5eab9af1976a994c50d146a3dbeccad4 (patch)
treee626482c9b04d7ed291a4f52e82fcfa87adaad6b
parentd14bd0879d7357598f4f7f49dae6661559e10745 (diff)
parenteb32ec13f1d870e5b85b03b353b659b59a7481bb (diff)
downloadrust-67ed30cd5eab9af1976a994c50d146a3dbeccad4.tar.gz
rust-67ed30cd5eab9af1976a994c50d146a3dbeccad4.zip
auto merge of #9097 : michaelwoerister/rust/namespaces, r=jdm
Who would have thought that namespaces are such a can of worms `:P` This is mostly because of some GDB idiosyncrasies (does not use namespace information but linkage-name attributes for displaying items contained in namespaces, also cannot handle functions lexically nested within functions), monomorphization, and information about external items only available from metadata.

This pull request tries to tackle the problem anyway:
* The `DW_AT_linkage_name` for functions is generated just to make GDB display a proper namespace-enabled function name. To this end, a pseudo-mangled name is generated, not corresponding to the real linkage name. This approach shows some success and could be extended to make GDB also show proper parameter types.
* As GDB won't accept subprogram DIEs nested within other subprogram DIEs, the `debuginfo` module now generates a *companion namespace* for each functions (iff needed). A function `fn abc()` will get a companion namespace with name `abc()`, which contains all items (modules, types, functions) declared within the functions scope. The real, proper solution, in my opinion, would be to faithfully reflect the program's lexical structure within DWARF (which allows arbitrary nesting of DIEs, afaik), but I am not sure LLVM's source level debugging implementation would like that and I am pretty sure GDB won't support this in the foreseeable future.
* Monomorphization leads to functions and companion namespaces like `somelib::some_func<int, float>()::some_other_function<bool, bool, bool>()`, which I think is the desired behaviour. There is some design space here, however. Maybe you people prefer `somelib::some_func()::some_other_function<bool, bool, bool>()` or `somelib::some_func()::some_other_function::<int, float, bool, bool, bool>()`.

The solution will work for now but there are a few things on my 'far future wish list':
* A real specification somewhere, what language constructs are mapped to what DWARF structures.
* Proper tests that directly compare the generated DWARF information to the expected results (possibly using something like [pyelftools](https://github.com/eliben/pyelftools) or llvm-dwarfdump)
* A unified implementation for crate-local and crate-external items (which would possibly involve beefing up `ast_map::path` and metadata a bit)

Any comments are welcome!

Closes #1541
Closes #1542 (there might be other issues with function name prettiness, but this specific issue should be fixed)
Closes #7715 (source locations for structs and enums are now read correctly from the AST)
-rw-r--r--src/librustc/lib/llvm.rs8
-rw-r--r--src/librustc/middle/trans/base.rs4
-rw-r--r--src/librustc/middle/trans/debuginfo.rs709
-rw-r--r--src/rustllvm/RustWrapper.cpp20
-rw-r--r--src/rustllvm/rustllvm.def.in1
-rw-r--r--src/test/debug-info/basic-types.rs2
-rw-r--r--src/test/debug-info/borrowed-basic.rs2
-rw-r--r--src/test/debug-info/borrowed-c-style-enum.rs2
-rw-r--r--src/test/debug-info/borrowed-enum.rs2
-rw-r--r--src/test/debug-info/borrowed-managed-basic.rs2
-rw-r--r--src/test/debug-info/borrowed-struct.rs2
-rw-r--r--src/test/debug-info/borrowed-tuple.rs2
-rw-r--r--src/test/debug-info/borrowed-unique-basic.rs2
-rw-r--r--src/test/debug-info/box.rs2
-rw-r--r--src/test/debug-info/boxed-struct.rs2
-rw-r--r--src/test/debug-info/boxed-vec.rs2
-rw-r--r--src/test/debug-info/by-value-non-immediate-argument.rs2
-rw-r--r--src/test/debug-info/by-value-self-argument-in-trait-impl.rs2
-rw-r--r--src/test/debug-info/c-style-enum-in-composite.rs2
-rw-r--r--src/test/debug-info/c-style-enum.rs2
-rw-r--r--src/test/debug-info/closure-in-generic-function.rs2
-rw-r--r--src/test/debug-info/destructured-fn-argument.rs2
-rw-r--r--src/test/debug-info/destructured-local.rs2
-rw-r--r--src/test/debug-info/evec-in-struct.rs2
-rw-r--r--src/test/debug-info/function-arguments.rs4
-rw-r--r--src/test/debug-info/generic-function.rs2
-rw-r--r--src/test/debug-info/generic-functions-nested.rs2
-rw-r--r--src/test/debug-info/generic-method-on-generic-struct.rs2
-rw-r--r--src/test/debug-info/generic-static-method-on-struct-and-enum.rs2
-rw-r--r--src/test/debug-info/generic-struct-style-enum.rs2
-rw-r--r--src/test/debug-info/generic-struct.rs2
-rw-r--r--src/test/debug-info/generic-trait-generic-static-default-method.rs2
-rw-r--r--src/test/debug-info/generic-tuple-style-enum.rs2
-rw-r--r--src/test/debug-info/lexical-scope-in-for-loop.rs2
-rw-r--r--src/test/debug-info/lexical-scope-in-if.rs2
-rw-r--r--src/test/debug-info/lexical-scope-in-managed-closure.rs2
-rw-r--r--src/test/debug-info/lexical-scope-in-match.rs2
-rw-r--r--src/test/debug-info/lexical-scope-in-stack-closure.rs2
-rw-r--r--src/test/debug-info/lexical-scope-in-unconditional-loop.rs2
-rw-r--r--src/test/debug-info/lexical-scope-in-unique-closure.rs2
-rw-r--r--src/test/debug-info/lexical-scope-in-while.rs2
-rw-r--r--src/test/debug-info/lexical-scope-with-macro.rs2
-rw-r--r--src/test/debug-info/lexical-scopes-in-block-expression.rs2
-rw-r--r--src/test/debug-info/managed-enum.rs2
-rw-r--r--src/test/debug-info/managed-pointer-within-unique-vec.rs2
-rw-r--r--src/test/debug-info/managed-pointer-within-unique.rs2
-rw-r--r--src/test/debug-info/method-on-enum.rs2
-rw-r--r--src/test/debug-info/method-on-generic-struct.rs2
-rw-r--r--src/test/debug-info/method-on-struct.rs2
-rw-r--r--src/test/debug-info/method-on-trait.rs2
-rw-r--r--src/test/debug-info/method-on-tuple-struct.rs2
-rw-r--r--src/test/debug-info/multiple-functions-equal-var-names.rs2
-rw-r--r--src/test/debug-info/multiple-functions.rs2
-rw-r--r--src/test/debug-info/name-shadowing-and-scope-nesting.rs2
-rw-r--r--src/test/debug-info/nil-enum.rs2
-rw-r--r--src/test/debug-info/option-like-enum.rs2
-rw-r--r--src/test/debug-info/packed-struct-with-destructor.rs2
-rw-r--r--src/test/debug-info/packed-struct.rs2
-rw-r--r--src/test/debug-info/self-in-default-method.rs2
-rw-r--r--src/test/debug-info/self-in-generic-default-method.rs2
-rw-r--r--src/test/debug-info/shadowed-argument.rs2
-rw-r--r--src/test/debug-info/shadowed-variable.rs2
-rw-r--r--src/test/debug-info/simple-lexical-scope.rs2
-rw-r--r--src/test/debug-info/simple-struct.rs2
-rw-r--r--src/test/debug-info/simple-tuple.rs2
-rw-r--r--src/test/debug-info/static-method-on-struct-and-enum.rs2
-rw-r--r--src/test/debug-info/struct-in-enum.rs2
-rw-r--r--src/test/debug-info/struct-in-struct.rs2
-rw-r--r--src/test/debug-info/struct-style-enum.rs2
-rw-r--r--src/test/debug-info/struct-with-destructor.rs2
-rw-r--r--src/test/debug-info/trait-generic-static-default-method.rs2
-rw-r--r--src/test/debug-info/tuple-in-struct.rs2
-rw-r--r--src/test/debug-info/tuple-in-tuple.rs2
-rw-r--r--src/test/debug-info/tuple-struct.rs2
-rw-r--r--src/test/debug-info/tuple-style-enum.rs2
-rw-r--r--src/test/debug-info/unique-enum.rs2
-rw-r--r--src/test/debug-info/var-captured-in-managed-closure.rs2
-rw-r--r--src/test/debug-info/var-captured-in-nested-closure.rs2
-rw-r--r--src/test/debug-info/var-captured-in-sendable-closure.rs2
-rw-r--r--src/test/debug-info/var-captured-in-stack-closure.rs2
-rw-r--r--src/test/debug-info/vec-slices.rs2
-rw-r--r--src/test/debug-info/vec.rs2
82 files changed, 670 insertions, 228 deletions
diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs
index 34c0dbb1788..75dabc8478f 100644
--- a/src/librustc/lib/llvm.rs
+++ b/src/librustc/lib/llvm.rs
@@ -2110,6 +2110,14 @@ pub mod llvm {
             -> ValueRef;
 
         #[fast_ffi]
+        pub fn LLVMDIBuilderCreateNameSpace(Builder: DIBuilderRef,
+                                            Scope: ValueRef,
+                                            Name: *c_char,
+                                            File: ValueRef,
+                                            LineNo: c_uint)
+                                            -> ValueRef;
+
+        #[fast_ffi]
         pub fn LLVMIsAArgument(value_ref: ValueRef) -> ValueRef;
 
         #[fast_ffi]
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index cb05b8bb7eb..94771d6f519 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -3021,6 +3021,10 @@ pub fn trans_crate(sess: session::Session,
                                      link_meta,
                                      analysis.reachable);
 
+    if ccx.sess.opts.debuginfo {
+        debuginfo::initialize(ccx, crate);
+    }
+
     {
         let _icx = push_ctxt("text");
         trans_mod(ccx, &crate.module);
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index 70630e3ee49..9164ee4943b 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -68,7 +68,7 @@ use std::libc::{c_uint, c_ulonglong, c_longlong};
 use std::ptr;
 use std::vec;
 use syntax::codemap::Span;
-use syntax::{ast, codemap, ast_util, ast_map, opt_vec};
+use syntax::{ast, codemap, ast_util, ast_map, opt_vec, visit};
 use syntax::parse::token;
 use syntax::parse::token::special_idents;
 
@@ -96,9 +96,11 @@ pub struct CrateDebugContext {
     priv crate_file: ~str,
     priv llcontext: ContextRef,
     priv builder: DIBuilderRef,
-    priv curr_loc: DebugLocation,
+    priv current_debug_location: DebugLocation,
     priv created_files: HashMap<~str, DIFile>,
     priv created_types: HashMap<uint, DIType>,
+    priv local_namespace_map: HashMap<ast::NodeId, @NamespaceTreeNode>,
+    priv extern_namespaces: HashMap<~[ast::Ident], @NamespaceTreeNode>,
 }
 
 impl CrateDebugContext {
@@ -111,9 +113,11 @@ impl CrateDebugContext {
             crate_file: crate,
             llcontext: llcontext,
             builder: builder,
-            curr_loc: UnknownLocation,
+            current_debug_location: UnknownLocation,
             created_files: HashMap::new(),
             created_types: HashMap::new(),
+            local_namespace_map: HashMap::new(),
+            extern_namespaces: HashMap::new(),
         };
     }
 }
@@ -129,12 +133,10 @@ impl FunctionDebugContext {
         match *self {
             FunctionDebugContext(~ref data) => data,
             DebugInfoDisabled => {
-                cx.sess.span_bug(span, "debuginfo: Error trying to access FunctionDebugContext \
-                                        although debug info is disabled!");
+                cx.sess.span_bug(span, FunctionDebugContext::debuginfo_disabled_message());
             }
             FunctionWithoutDebugInfo => {
-                cx.sess.span_bug(span, "debuginfo: Error trying to access FunctionDebugContext \
-                                        for function that should be ignored by debug info!");
+                cx.sess.span_bug(span, FunctionDebugContext::should_be_ignored_message());
             }
         }
     }
@@ -146,15 +148,22 @@ impl FunctionDebugContext {
         match *self {
             FunctionDebugContext(~ref mut data) => data,
             DebugInfoDisabled => {
-                cx.sess.span_bug(span, "debuginfo: Error trying to access FunctionDebugContext \
-                                        although debug info is disabled!");
+                cx.sess.span_bug(span, FunctionDebugContext::debuginfo_disabled_message());
             }
             FunctionWithoutDebugInfo => {
-                cx.sess.span_bug(span, "debuginfo: Error trying to access FunctionDebugContext \
-                                        for function that should be ignored by debug info!");
+                cx.sess.span_bug(span, FunctionDebugContext::should_be_ignored_message());
             }
         }
     }
+
+    fn debuginfo_disabled_message() -> &'static str {
+        "debuginfo: Error trying to access FunctionDebugContext although debug info is disabled!"
+    }
+
+    fn should_be_ignored_message() -> &'static str {
+        "debuginfo: Error trying to access FunctionDebugContext for function that should be \
+         ignored by debug info!"
+    }
 }
 
 struct FunctionDebugContextData {
@@ -178,8 +187,22 @@ enum VariableKind {
     CapturedVariable,
 }
 
+pub fn initialize(cx: &mut CrateContext, crate: &ast::Crate) {
+    if cx.dbg_cx.is_none() {
+        return;
+    }
+
+    let crate_namespace_ident = token::str_to_ident(cx.link_meta.name);
+    let mut visitor = NamespaceVisitor::new_crate_visitor(cx, crate_namespace_ident);
+    visit::walk_crate(&mut visitor, crate, ());
+}
+
 /// Create any deferred debug metadata nodes
 pub fn finalize(cx: @mut CrateContext) {
+    if cx.dbg_cx.is_none() {
+        return;
+    }
+
     debug!("finalize");
     compile_unit_metadata(cx);
     unsafe {
@@ -573,22 +596,38 @@ pub fn create_function_debug_context(cx: &mut CrateContext,
     };
 
     // get_template_parameters() will append a `<...>` clause to the function name if necessary.
-    let mut function_name = cx.sess.str_of(ident).to_owned();
+    let mut function_name = token::ident_to_str(&ident).to_owned();
     let template_parameters = if cx.sess.opts.extra_debuginfo {
         get_template_parameters(cx, generics, param_substs, file_metadata, &mut function_name)
     } else {
         ptr::null()
     };
 
+    let namespace_node = debug_context(cx).local_namespace_map.find_copy(&fn_ast_id);
+    let (linkage_name, containing_scope) = match namespace_node {
+        Some(namespace_node) => {
+            (namespace_node.mangled_name_of_contained_item(function_name), namespace_node.scope)
+        }
+        None => {
+            // This branch is only hit when there is a bug in the NamespaceVisitor.
+            cx.sess.span_warn(span, "debuginfo: Could not find namespace node for function. \
+                                     This is a bug! Try running with RUST_LOG=rustc=1 \
+                                     to get further details and report the results \
+                                     to github.com/mozilla/rust/issues");
+            (function_name.clone(), file_metadata)
+        }
+    };
+
     let scope_line = get_scope_line(cx, top_level_block, loc.line);
 
-    let fn_metadata = do function_name.to_c_str().with_ref |function_name| {
+    let fn_metadata = do function_name.with_c_str |function_name| {
+                      do linkage_name.with_c_str |linkage_name| {
         unsafe {
             llvm::LLVMDIBuilderCreateFunction(
                 DIB(cx),
-                file_metadata,
-                function_name,
+                containing_scope,
                 function_name,
+                linkage_name,
                 file_metadata,
                 loc.line as c_uint,
                 function_type_metadata,
@@ -601,9 +640,9 @@ pub fn create_function_debug_context(cx: &mut CrateContext,
                 template_parameters,
                 ptr::null())
         }
-    };
+    }};
 
-    // Initialize fn debug context (including scope map)
+    // Initialize fn debug context (including scope map and namespace map)
     let mut fn_debug_context = ~FunctionDebugContextData {
         scope_map: HashMap::new(),
         fn_metadata: fn_metadata,
@@ -614,6 +653,18 @@ pub fn create_function_debug_context(cx: &mut CrateContext,
     let arg_pats = do fn_decl.inputs.map |arg_ref| { arg_ref.pat };
     populate_scope_map(cx, arg_pats, top_level_block, fn_metadata, &mut fn_debug_context.scope_map);
 
+    match top_level_block {
+        Some(top_level_block) => {
+            let mut namespace_visitor = NamespaceVisitor::new_function_visitor(cx,
+                                                                               function_name,
+                                                                               namespace_node,
+                                                                               file_metadata,
+                                                                               span);
+            visit::walk_block(&mut namespace_visitor, top_level_block, ());
+        }
+        _ => { /*nothing to do*/ }
+    }
+
     return FunctionDebugContext(fn_debug_context);
 
     fn get_function_signature(cx: &mut CrateContext,
@@ -644,7 +695,7 @@ pub fn create_function_debug_context(cx: &mut CrateContext,
             }
         }
 
-        // arguments types
+        // Arguments types
         for arg in fn_decl.inputs.iter() {
             let arg_type = ty::node_id_to_type(cx.tcx, arg.pat.id);
             let arg_type = match param_substs {
@@ -699,7 +750,7 @@ pub fn create_function_debug_context(cx: &mut CrateContext,
 
             let ident = special_idents::type_self;
 
-            let param_metadata = do cx.sess.str_of(ident).to_c_str().with_ref |name| {
+            let param_metadata = do token::ident_to_str(&ident).to_c_str().with_ref |name| {
                 unsafe {
                     llvm::LLVMDIBuilderCreateTemplateTypeParameter(
                         DIB(cx),
@@ -735,7 +786,7 @@ pub fn create_function_debug_context(cx: &mut CrateContext,
                 name_to_append_suffix_to.push_str(",");
             }
 
-            let param_metadata = do cx.sess.str_of(ident).to_c_str().with_ref |name| {
+            let param_metadata = do token::ident_to_str(&ident).to_c_str().with_ref |name| {
                 unsafe {
                     llvm::LLVMDIBuilderCreateTemplateTypeParameter(
                         DIB(cx),
@@ -783,7 +834,7 @@ fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
 }
 
 fn compile_unit_metadata(cx: @mut CrateContext) {
-    let dcx = dbg_cx(cx);
+    let dcx = debug_context(cx);
     let crate_name: &str = dcx.crate_file;
 
     debug!("compile_unit_metadata: %?", crate_name);
@@ -823,7 +874,7 @@ fn declare_local(bcx: @mut Block,
     let filename = span_start(cx, span).file.name;
     let file_metadata = file_metadata(cx, filename);
 
-    let name: &str = cx.sess.str_of(variable_ident);
+    let name: &str = token::ident_to_str(&variable_ident);
     let loc = span_start(cx, span);
     let type_metadata = type_metadata(cx, variable_type, span);
 
@@ -886,12 +937,12 @@ fn declare_local(bcx: @mut Block,
             assert!(!bcx.fcx.debug_context.get_ref(cx, span).source_locations_enabled);
             set_debug_location(cx, UnknownLocation);
         }
-        _ => { /* fallthrough */ }
+        _ => { /* nothing to do */ }
     }
 }
 
 fn file_metadata(cx: &mut CrateContext, full_path: &str) -> DIFile {
-    match dbg_cx(cx).created_files.find_equiv(&full_path) {
+    match debug_context(cx).created_files.find_equiv(&full_path) {
         Some(file_metadata) => return *file_metadata,
         None => ()
     }
@@ -914,7 +965,7 @@ fn file_metadata(cx: &mut CrateContext, full_path: &str) -> DIFile {
             }
         }};
 
-    dbg_cx(cx).created_files.insert(full_path.to_owned(), file_metadata);
+    debug_context(cx).created_files.insert(full_path.to_owned(), file_metadata);
     return file_metadata;
 }
 
@@ -1004,34 +1055,42 @@ fn pointer_type_metadata(cx: &mut CrateContext,
 
 fn struct_metadata(cx: &mut CrateContext,
                    struct_type: ty::t,
-                   fields: ~[ty::field],
+                   def_id: ast::DefId,
+                   substs: &ty::substs,
                    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| {
-        if field.ident.name == special_idents::unnamed_field.name {
-            ~""
+    let fields = ty::struct_fields(cx.tcx, def_id, substs);
+    let field_descriptions = do fields.map |field| {
+        let name = if field.ident.name == special_idents::unnamed_field.name {
+            @""
         } else {
-            cx.sess.str_of(field.ident).to_owned()
+            token::ident_to_str(&field.ident)
+        };
+
+        MemberDescription {
+            name: name,
+            llvm_type: type_of::type_of(cx, field.mt.ty),
+            type_metadata: type_metadata(cx, field.mt.ty, span),
         }
     };
-    let field_types_metadata = do fields.map |field| {
-        type_metadata(cx, field.mt.ty, span)
-    };
+
+    let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id, span);
+
+    let file_name = span_start(cx, definition_span).file.name;
+    let file_metadata = file_metadata(cx, file_name);
 
     return composite_type_metadata(
         cx,
         struct_llvm_type,
         struct_name,
-        field_llvm_types,
-        field_names,
-        field_types_metadata,
-        span);
+        field_descriptions,
+        containing_scope,
+        file_metadata,
+        definition_span);
 }
 
 fn tuple_metadata(cx: &mut CrateContext,
@@ -1039,23 +1098,27 @@ fn tuple_metadata(cx: &mut CrateContext,
                   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)
+    let component_descriptions = do component_types.map |&component_type| {
+        MemberDescription {
+            name: @"",
+            llvm_type: type_of::type_of(cx, component_type),
+            type_metadata: type_metadata(cx, component_type, span),
+        }
     };
 
+    let loc = span_start(cx, span);
+    let file_metadata = file_metadata(cx, loc.file.name);
+
     return composite_type_metadata(
         cx,
         tuple_llvm_type,
         tuple_name,
-        component_llvm_types,
-        component_names,
-        component_types_metadata,
+        component_descriptions,
+        file_metadata,
+        file_metadata,
         span);
 }
 
@@ -1064,13 +1127,24 @@ fn enum_metadata(cx: &mut CrateContext,
                  enum_def_id: ast::DefId,
                  span: Span)
               -> DIType {
-
     let enum_name = ty_to_str(cx.tcx, enum_type);
 
+    let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx,
+                                                                              enum_def_id,
+                                                                              span);
+    let loc = span_start(cx, definition_span);
+    let file_metadata = file_metadata(cx, loc.file.name);
+
     // 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);
+        return composite_type_metadata(cx,
+                                       Type::nil(),
+                                       enum_name,
+                                       [],
+                                       file_metadata,
+                                       file_metadata,
+                                       definition_span);
     }
 
     // Prepare some data (llvm type, size, align, ...) about the discriminant. This data will be
@@ -1079,14 +1153,14 @@ fn enum_metadata(cx: &mut CrateContext,
     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 discriminant_base_type_metadata = type_metadata(cx, ty::mk_int(), codemap::dummy_sp());
 
     let variants: &[@ty::VariantInfo] = *ty::enum_variants(cx.tcx, enum_def_id);
 
     let enumerators_metadata: ~[DIDescriptor] = variants
         .iter()
         .map(|v| {
-            let name: &str = cx.sess.str_of(v.name);
+            let name: &str = token::ident_to_str(&v.name);
             let discriminant_value = v.disr_val as c_ulonglong;
 
             do name.with_c_str |name| {
@@ -1100,21 +1174,18 @@ fn enum_metadata(cx: &mut CrateContext,
         })
         .collect();
 
-    let loc = span_start(cx, span);
-    let file_metadata = file_metadata(cx, loc.file.name);
-
     let discriminant_type_metadata = do enum_name.with_c_str |enum_name| {
         unsafe {
             llvm::LLVMDIBuilderCreateEnumerationType(
                 DIB(cx),
-                file_metadata,
+                containing_scope,
                 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)
+                discriminant_base_type_metadata)
         }
     };
 
@@ -1126,7 +1197,13 @@ fn enum_metadata(cx: &mut CrateContext,
         }
         adt::Univariant(ref struct_def, _) => {
             assert!(variants.len() == 1);
-            return adt_struct_metadata(cx, struct_def, variants[0], None, span);
+            return adt_struct_metadata(cx,
+                                       struct_def,
+                                       variants[0],
+                                       None,
+                                       containing_scope,
+                                       file_metadata,
+                                       span);
         }
         adt::General(ref struct_defs) => {
             let variants_member_metadata: ~[DIDescriptor] = do struct_defs
@@ -1138,13 +1215,15 @@ fn enum_metadata(cx: &mut CrateContext,
                         struct_def,
                         variants[i],
                         Some(discriminant_type_metadata),
+                        containing_scope,
+                        file_metadata,
                         span);
 
                     do "".with_c_str |name| {
                         unsafe {
                             llvm::LLVMDIBuilderCreateMemberType(
                                 DIB(cx),
-                                file_metadata,
+                                containing_scope,
                                 name,
                                 file_metadata,
                                 loc.line as c_uint,
@@ -1164,7 +1243,7 @@ fn enum_metadata(cx: &mut CrateContext,
                 unsafe {
                     llvm::LLVMDIBuilderCreateUnionType(
                     DIB(cx),
-                    file_metadata,
+                    containing_scope,
                     enum_name,
                     file_metadata,
                     loc.line as c_uint,
@@ -1176,7 +1255,13 @@ fn enum_metadata(cx: &mut CrateContext,
             }};
         }
         adt::NullablePointer { nonnull: ref struct_def, nndiscr, _ } => {
-            return adt_struct_metadata(cx, struct_def, variants[nndiscr], None, span);
+            return adt_struct_metadata(cx,
+                                       struct_def,
+                                       variants[nndiscr],
+                                       None,
+                                       containing_scope,
+                                       file_metadata,
+                                       span);
         }
     }
 
@@ -1184,67 +1269,93 @@ fn enum_metadata(cx: &mut CrateContext,
                                   struct_def: &adt::Struct,
                                   variant_info: &ty::VariantInfo,
                                   discriminant_type_metadata: Option<DIType>,
+                                  containing_scope: DIScope,
+                                  file_metadata: DIFile,
                                   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()
-            .map |(i, &ty)| {
-                match discriminant_type_metadata {
-                    Some(metadata) if i == 0 => metadata,
-                    _                        => type_metadata(cx, ty, span)
-                }
-        }.collect();
-
+                               -> DICompositeType {
+        // Get the argument names from the enum variant info
         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 |_| { ~"" }
+            Some(ref names) => do names.map |ident| { token::ident_to_str(ident) },
+            None => do variant_info.args.map |_| { @"" }
         };
 
+        // If this is not a univariant enum, there is also the (unnamed) discriminant field
         if discriminant_type_metadata.is_some() {
-            arg_names.insert(0, ~"");
+            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);
+        let arg_descriptions : ~[MemberDescription] =
+            do struct_def.fields.iter().enumerate().map |(i, &ty)| {
+                MemberDescription {
+                    name: arg_names[i].clone(),
+                    llvm_type: type_of::type_of(cx, ty),
+                    type_metadata: match discriminant_type_metadata {
+                        Some(metadata) if i == 0 => metadata,
+                        _                        => type_metadata(cx, ty, span)
+                    }
+                }
+            }.collect();
+
+        let variant_name = token::ident_to_str(&variant_info.name);
+        let variant_llvm_type = Type::struct_(arg_descriptions.map(|d| d.llvm_type),
+                                              struct_def.packed);
+
+        // Find the source code location of the variant's definition
+        let variant_definition_span = if variant_info.id.crate == ast::LOCAL_CRATE {
+            match cx.tcx.items.find(&variant_info.id.node) {
+                Some(&ast_map::node_variant(ref variant, _, _)) => variant.span,
+                ref node => {
+                    cx.sess.span_warn(span,
+                        fmt!("debuginfo::enum_metadata()::adt_struct_metadata() - Unexpected node \
+                              type: %?. This is a bug.", node));
+                    codemap::dummy_sp()
+                }
+            }
+        } else {
+            // For definitions from other crates we have no location information available.
+            codemap::dummy_sp()
+        };
 
         return composite_type_metadata(
             cx,
             variant_llvm_type,
             variant_name,
-            arg_llvm_types,
-            arg_names,
-            arg_metadata,
-            span);
+            arg_descriptions,
+            containing_scope,
+            file_metadata,
+            variant_definition_span);
     }
 }
 
+struct MemberDescription {
+    name: @str,
+    llvm_type: Type,
+    type_metadata: DIType,
+}
+
 /// 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)
+                           member_descriptions: &[MemberDescription],
+                           containing_scope: DIScope,
+                           file_metadata: DIFile,
+                           definition_span: Span)
                         -> DICompositeType {
-
-    let loc = span_start(cx, span);
-    let file_metadata = file_metadata(cx, loc.file.name);
+    let loc = span_start(cx, definition_span);
 
     let (composite_size, composite_align) = size_and_align_of(cx, composite_llvm_type);
 
-    let member_metadata: ~[DIDescriptor] = member_llvm_types
+    let member_metadata: ~[DIDescriptor] = member_descriptions
         .iter()
         .enumerate()
-        .map(|(i, &member_llvm_type)| {
-            let (member_size, member_align) = size_and_align_of(cx, member_llvm_type);
+        .map(|(i, member_description)| {
+            let (member_size, member_align) = size_and_align_of(cx, member_description.llvm_type);
             let member_offset = machine::llelement_offset(cx, composite_llvm_type, i);
-            let member_name: &str = member_names[i];
 
-            do member_name.with_c_str |member_name| {
+            do member_description.name.with_c_str |member_name| {
                 unsafe {
                     llvm::LLVMDIBuilderCreateMemberType(
                         DIB(cx),
@@ -1256,7 +1367,7 @@ fn composite_type_metadata(cx: &mut CrateContext,
                         bytes_to_bits(member_align),
                         bytes_to_bits(member_offset),
                         0,
-                        member_type_metadata[i])
+                        member_description.type_metadata)
                 }
             }
         })
@@ -1266,7 +1377,7 @@ fn composite_type_metadata(cx: &mut CrateContext,
         unsafe {
             llvm::LLVMDIBuilderCreateStructType(
                 DIB(cx),
-                file_metadata,
+                containing_scope,
                 name,
                 file_metadata,
                 loc.line as c_uint,
@@ -1277,8 +1388,7 @@ fn composite_type_metadata(cx: &mut CrateContext,
                 create_DIArray(DIB(cx), member_metadata),
                 0,
                 ptr::null())
-    }
-    };
+    }};
 }
 
 fn boxed_type_metadata(cx: &mut CrateContext,
@@ -1287,7 +1397,6 @@ fn boxed_type_metadata(cx: &mut CrateContext,
                        content_type_metadata: DIType,
                        span: Span)
                     -> DICompositeType {
-
     let box_type_name = match content_type_name {
         Some(content_type_name) => fmt!("Boxed<%s>", content_type_name),
         None                    => ~"BoxedType"
@@ -1295,28 +1404,50 @@ fn boxed_type_metadata(cx: &mut CrateContext,
 
     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 nil_pointer_type_metadata = type_metadata(cx, nil_pointer_type, codemap::dummy_sp());
 
-    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
+    let member_descriptions = [
+        MemberDescription {
+            name: @"refcnt",
+            llvm_type: member_llvm_types[0],
+            type_metadata: type_metadata(cx, int_type, codemap::dummy_sp()),
+        },
+        MemberDescription {
+            name: @"tydesc",
+            llvm_type: member_llvm_types[1],
+            type_metadata: nil_pointer_type_metadata,
+        },
+        MemberDescription {
+            name: @"prev",
+            llvm_type: member_llvm_types[2],
+            type_metadata: nil_pointer_type_metadata,
+        },
+        MemberDescription {
+            name: @"next",
+            llvm_type: member_llvm_types[3],
+            type_metadata: nil_pointer_type_metadata,
+        },
+        MemberDescription {
+            name: @"val",
+            llvm_type: member_llvm_types[4],
+            type_metadata: content_type_metadata
+        }
     ];
 
+    let loc = span_start(cx, span);
+    let file_metadata = file_metadata(cx, loc.file.name);
+
     return composite_type_metadata(
         cx,
         box_llvm_type,
         box_type_name,
-        member_llvm_types,
-        member_names,
-        member_types_metadata,
+        member_descriptions,
+        file_metadata,
+        file_metadata,
         span);
 
     // Unfortunately, we cannot assert anything but the correct types here---and not whether the
@@ -1374,7 +1505,6 @@ fn vec_metadata(cx: &mut CrateContext,
     let vec_type_name: &str = fmt!("[%s]", ty_to_str(cx.tcx, element_type));
 
     let member_llvm_types = vec_llvm_type.field_types();
-    let member_names = &[~"fill", ~"alloc", ~"elements"];
 
     let int_type_metadata = type_metadata(cx, ty::mk_int(), span);
     let array_type_metadata = unsafe {
@@ -1386,16 +1516,36 @@ fn vec_metadata(cx: &mut CrateContext,
             create_DIArray(DIB(cx), [llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, 0)]))
     };
 
-    //                           fill               alloc              elements
-    let member_type_metadata = &[int_type_metadata, int_type_metadata, array_type_metadata];
+    let member_descriptions = [
+        MemberDescription {
+            name: @"fill",
+            llvm_type: member_llvm_types[0],
+            type_metadata: int_type_metadata,
+        },
+        MemberDescription {
+            name: @"alloc",
+            llvm_type: member_llvm_types[1],
+            type_metadata: int_type_metadata,
+        },
+        MemberDescription {
+            name: @"elements",
+            llvm_type: member_llvm_types[2],
+            type_metadata: array_type_metadata,
+        }
+    ];
+
+    assert!(member_descriptions.len() == member_llvm_types.len());
+
+    let loc = span_start(cx, span);
+    let file_metadata = file_metadata(cx, loc.file.name);
 
     return composite_type_metadata(
         cx,
         vec_llvm_type,
         vec_type_name,
-        member_llvm_types,
-        member_names,
-        member_type_metadata,
+        member_descriptions,
+        file_metadata,
+        file_metadata,
         span);
 }
 
@@ -1429,22 +1579,35 @@ fn vec_slice_metadata(cx: &mut CrateContext,
     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"];
-
     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::MutImmutable });
 
-    let member_type_metadata = &[type_metadata(cx, data_ptr_type, span),
-                                 type_metadata(cx, ty::mk_uint(), span)];
+    let member_descriptions = [
+        MemberDescription {
+            name: @"data_ptr",
+            llvm_type: member_llvm_types[0],
+            type_metadata: type_metadata(cx, data_ptr_type, span),
+        },
+        MemberDescription {
+            name: @"size_in_bytes",
+            llvm_type: member_llvm_types[1],
+            type_metadata: type_metadata(cx, ty::mk_uint(), span),
+        },
+    ];
+
+    assert!(member_descriptions.len() == member_llvm_types.len());
+
+    let loc = span_start(cx, span);
+    let file_metadata = file_metadata(cx, loc.file.name);
 
     return composite_type_metadata(
         cx,
         slice_llvm_type,
         slice_type_name,
-        member_llvm_types,
-        member_names,
-        member_type_metadata,
+        member_descriptions,
+        file_metadata,
+        file_metadata,
         span);
 
     fn slice_layout_is_correct(cx: &mut CrateContext,
@@ -1505,10 +1668,10 @@ fn unimplemented_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType {
 
 fn type_metadata(cx: &mut CrateContext,
                  t: ty::t,
-                 span: Span)
+                 usage_site_span: Span)
               -> DIType {
     let type_id = ty::type_id(t);
-    match dbg_cx(cx).created_types.find(&type_id) {
+    match debug_context(cx).created_types.find(&type_id) {
         Some(type_metadata) => return *type_metadata,
         None => ()
     }
@@ -1552,23 +1715,23 @@ fn type_metadata(cx: &mut CrateContext,
             let i8_t = ty::mk_i8();
             match *vstore {
                 ty::vstore_fixed(len) => {
-                    fixed_vec_metadata(cx, i8_t, len + 1, span)
+                    fixed_vec_metadata(cx, i8_t, len + 1, usage_site_span)
                 },
                 ty::vstore_uniq  => {
-                    let vec_metadata = vec_metadata(cx, i8_t, span);
+                    let vec_metadata = vec_metadata(cx, i8_t, usage_site_span);
                     pointer_type_metadata(cx, t, vec_metadata)
                 }
                 ty::vstore_box => {
-                    let boxed_vec_metadata = boxed_vec_metadata(cx, i8_t, span);
+                    let boxed_vec_metadata = boxed_vec_metadata(cx, i8_t, usage_site_span);
                     pointer_type_metadata(cx, t, boxed_vec_metadata)
                 }
                 ty::vstore_slice(_region) => {
-                    vec_slice_metadata(cx, t, i8_t, span)
+                    vec_slice_metadata(cx, t, i8_t, usage_site_span)
                 }
             }
         },
         ty::ty_enum(def_id, _) => {
-            enum_metadata(cx, t, def_id, span)
+            enum_metadata(cx, t, def_id, usage_site_span)
         },
         ty::ty_box(ref mt) => {
             create_pointer_to_box_metadata(cx, t, mt.ty)
@@ -1576,22 +1739,22 @@ fn type_metadata(cx: &mut CrateContext,
         ty::ty_evec(ref mt, ref vstore) => {
             match *vstore {
                 ty::vstore_fixed(len) => {
-                    fixed_vec_metadata(cx, mt.ty, len, span)
+                    fixed_vec_metadata(cx, mt.ty, len, usage_site_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);
+                    let boxed_vec_metadata = boxed_vec_metadata(cx, mt.ty, usage_site_span);
                     pointer_type_metadata(cx, t, boxed_vec_metadata)
                 }
                 ty::vstore_uniq => {
-                    let vec_metadata = vec_metadata(cx, mt.ty, span);
+                    let vec_metadata = vec_metadata(cx, mt.ty, usage_site_span);
                     pointer_type_metadata(cx, t, vec_metadata)
                 }
                 ty::vstore_box => {
-                    let boxed_vec_metadata = boxed_vec_metadata(cx, mt.ty, span);
+                    let boxed_vec_metadata = boxed_vec_metadata(cx, mt.ty, usage_site_span);
                     pointer_type_metadata(cx, t, boxed_vec_metadata)
                 }
                 ty::vstore_slice(_) => {
-                    vec_slice_metadata(cx, t, mt.ty, span)
+                    vec_slice_metadata(cx, t, mt.ty, usage_site_span)
                 }
             }
         },
@@ -1601,34 +1764,33 @@ fn type_metadata(cx: &mut CrateContext,
         ty::ty_uniq(ref mt)    |
         ty::ty_ptr(ref mt)     |
         ty::ty_rptr(_, ref mt) => {
-            let pointee = type_metadata(cx, mt.ty, span);
+            let pointee = type_metadata(cx, mt.ty, usage_site_span);
             pointer_type_metadata(cx, t, pointee)
         },
         ty::ty_bare_fn(ref barefnty) => {
-            subroutine_type_metadata(cx, &barefnty.sig, span)
+            subroutine_type_metadata(cx, &barefnty.sig, usage_site_span)
         },
         ty::ty_closure(ref closurety) => {
-            subroutine_type_metadata(cx, &closurety.sig, span)
+            subroutine_type_metadata(cx, &closurety.sig, usage_site_span)
         },
         ty::ty_trait(_did, ref _substs, ref _vstore, _, _bounds) => {
-            cx.sess.span_note(span, "debuginfo for trait NYI");
+            cx.sess.span_note(usage_site_span, "debuginfo for trait NYI");
             unimplemented_type_metadata(cx, t)
         },
-        ty::ty_struct(did, ref substs) => {
-            let fields = ty::struct_fields(cx.tcx, did, substs);
-            struct_metadata(cx, t, fields, span)
+        ty::ty_struct(def_id, ref substs) => {
+            struct_metadata(cx, t, def_id, substs, usage_site_span)
         },
         ty::ty_tup(ref elements) => {
-            tuple_metadata(cx, t, *elements, span)
+            tuple_metadata(cx, t, *elements, usage_site_span)
         },
         ty::ty_opaque_box => {
-            cx.sess.span_note(span, "debuginfo for ty_opaque_box NYI");
+            cx.sess.span_note(usage_site_span, "debuginfo for ty_opaque_box NYI");
             unimplemented_type_metadata(cx, t)
         }
         _ => cx.sess.bug(fmt!("debuginfo: unexpected type in type_metadata: %?", sty))
     };
 
-    dbg_cx(cx).created_types.insert(type_id, type_metadata);
+    debug_context(cx).created_types.insert(type_id, type_metadata);
     return type_metadata;
 }
 
@@ -1649,7 +1811,7 @@ impl DebugLocation {
 }
 
 fn set_debug_location(cx: &mut CrateContext, debug_location: DebugLocation) {
-    if debug_location == dbg_cx(cx).curr_loc {
+    if debug_location == debug_context(cx).current_debug_location {
         return;
     }
 
@@ -1660,7 +1822,7 @@ fn set_debug_location(cx: &mut CrateContext, debug_location: DebugLocation) {
             debug!("setting debug location to %u %u", line, col);
             let elements = [C_i32(line as i32), C_i32(col as i32), scope, ptr::null()];
             unsafe {
-                metadata_node = llvm::LLVMMDNodeInContext(dbg_cx(cx).llcontext,
+                metadata_node = llvm::LLVMMDNodeInContext(debug_context(cx).llcontext,
                                                           vec::raw::to_ptr(elements),
                                                           elements.len() as c_uint);
             }
@@ -1675,7 +1837,7 @@ fn set_debug_location(cx: &mut CrateContext, debug_location: DebugLocation) {
         llvm::LLVMSetCurrentDebugLocation(cx.builder.B, metadata_node);
     }
 
-    dbg_cx(cx).curr_loc = debug_location;
+    debug_context(cx).current_debug_location = debug_location;
 }
 
 //=-------------------------------------------------------------------------------------------------
@@ -1701,7 +1863,7 @@ fn bytes_to_bits(bytes: uint) -> c_ulonglong {
 }
 
 #[inline]
-fn dbg_cx<'a>(cx: &'a mut CrateContext) -> &'a mut CrateDebugContext {
+fn debug_context<'a>(cx: &'a mut CrateContext) -> &'a mut CrateDebugContext {
     cx.dbg_cx.get_mut_ref()
 }
 
@@ -1725,6 +1887,28 @@ fn fn_should_be_ignored(fcx: &FunctionContext) -> bool {
     }
 }
 
+fn get_namespace_and_span_for_item(cx: &mut CrateContext,
+                                   def_id: ast::DefId,
+                                   warning_span: Span)
+                                -> (DIScope, Span) {
+    if def_id.crate == ast::LOCAL_CRATE {
+        let containing_scope = debug_context(cx).local_namespace_map.get_copy(&def_id.node).scope;
+        let definition_span = match cx.tcx.items.find(&def_id.node) {
+            Some(&ast_map::node_item(@ast::item { span, _ }, _)) => span,
+            ref node => {
+                cx.sess.span_warn(warning_span, fmt!("debuginfo::get_namespace_and_span_for_item() \
+                                                      - Unexpected node type: %?", *node));
+                codemap::dummy_sp()
+            }
+        };
+        (containing_scope, definition_span)
+    } else {
+        let item_path = ty::item_path(cx.tcx, def_id);
+        // For external items there is no span information
+        (namespace_for_external_item(cx, &item_path).scope, codemap::dummy_sp())
+    }
+}
+
 // This procedure builds the *scope map* for a given function, which maps any given ast::NodeId in
 // the function's AST to the correct DIScope metadata instance.
 //
@@ -2179,3 +2363,234 @@ fn populate_scope_map(cx: &mut CrateContext,
         }
     }
 }
+
+
+//=-------------------------------------------------------------------------------------------------
+// Namespace Handling
+//=-------------------------------------------------------------------------------------------------
+
+struct NamespaceTreeNode {
+    ident: ast::Ident,
+    scope: DIScope,
+    parent: Option<@NamespaceTreeNode>,
+}
+
+impl NamespaceTreeNode {
+    fn mangled_name_of_contained_item(&self, item_name: &str) -> ~str {
+        let mut name = ~"_ZN";
+        fill_nested(self, &mut name);
+
+        name.push_str(fmt!("%u%s", item_name.len(), item_name));
+        name.push_char('E');
+
+        return name;
+
+        fn fill_nested(node: &NamespaceTreeNode, output: &mut ~str) {
+            match node.parent {
+                Some(parent) => {
+                    fill_nested(parent, output);
+                }
+                None => {}
+            }
+            let name = token::ident_to_str(&node.ident);
+            output.push_str(fmt!("%u%s", name.len(), name));
+        }
+    }
+}
+
+fn namespace_for_external_item(cx: &mut CrateContext,
+                               item_path: &ast_map::path)
+                            -> @NamespaceTreeNode {
+    if item_path.len() < 2 {
+        cx.sess.bug(fmt!("debuginfo::namespace_for_external_item() - Invalid item_path: %s",
+            ast_map::path_to_str(*item_path, token::get_ident_interner())));
+    }
+
+    let path_excluding_item = item_path.slice_to(item_path.len() - 1);
+    let mut current_key = vec::with_capacity(path_excluding_item.len());
+    let mut parent_node: Option<@NamespaceTreeNode> = None;
+    let last_index = path_excluding_item.len() - 1;
+
+    for (i, &path_element) in path_excluding_item.iter().enumerate() {
+        let ident = match path_element {
+            ast_map::path_mod(ident)            |
+            ast_map::path_name(ident)           |
+            ast_map::path_pretty_name(ident, _) => ident
+        };
+
+        current_key.push(ident);
+
+        let existing_node = debug_context(cx).extern_namespaces.find_copy(&current_key);
+        let current_node = match existing_node {
+            Some(existing_node) => existing_node,
+            None => {
+                // create and insert
+                let parent_scope = match parent_node {
+                    Some(node) => node.scope,
+                    None => ptr::null()
+                };
+                let namespace_name = token::ident_to_str(&ident);
+
+                let namespace_metadata = unsafe {
+                    do namespace_name.with_c_str |namespace_name| {
+                        llvm::LLVMDIBuilderCreateNameSpace(
+                            DIB(cx),
+                            parent_scope,
+                            namespace_name,
+                            ptr::null(), // cannot reconstruct file ...
+                            0)           // ... or line information
+                    }
+                };
+
+                let node = @NamespaceTreeNode {
+                    ident: ident,
+                    scope: namespace_metadata,
+                    parent: parent_node,
+                };
+
+                debug_context(cx).extern_namespaces.insert(current_key.clone(), node);
+
+                node
+            }
+        };
+
+        if i == last_index {
+            return current_node;
+        } else {
+            parent_node = Some(current_node);
+        }
+    }
+
+    cx.sess.bug("debuginfo::namespace_for_external_item() - Code path should be unreachable");
+}
+
+struct NamespaceVisitor<'self> {
+    module_ident: ast::Ident,
+    scope_stack: ~[@NamespaceTreeNode],
+    crate_context: &'self mut CrateContext,
+}
+
+impl<'self> NamespaceVisitor<'self> {
+
+    fn new_crate_visitor<'a>(cx: &'a mut CrateContext,
+                             crate_ident: ast::Ident)
+                          -> NamespaceVisitor<'a> {
+        NamespaceVisitor {
+            module_ident: crate_ident,
+            scope_stack: ~[],
+            crate_context: cx,
+        }
+    }
+
+    fn new_function_visitor<'a>(cx: &'a mut CrateContext,
+                                function_name: &str,
+                                parent_node: Option<@NamespaceTreeNode>,
+                                file_metadata: DIFile,
+                                span: Span)
+                             -> NamespaceVisitor<'a> {
+        let companion_name = function_name + "()";
+        let companion_ident = token::str_to_ident(companion_name);
+        let parent_scope = match parent_node {
+            Some(parent_node) => parent_node.scope,
+            None => ptr::null()
+        };
+        let line = span_start(cx, span).line as c_uint;
+
+        let namespace_metadata = unsafe {
+            do companion_name.with_c_str |companion_name| {
+                llvm::LLVMDIBuilderCreateNameSpace(
+                    DIB(cx),
+                    parent_scope,
+                    companion_name,
+                    file_metadata,
+                    line)
+            }
+        };
+
+        let function_node = @NamespaceTreeNode {
+            scope: namespace_metadata,
+            ident: companion_ident,
+            parent: parent_node,
+        };
+
+        return NamespaceVisitor {
+            module_ident: special_idents::invalid,
+            scope_stack: ~[function_node],
+            crate_context: cx,
+        };
+    }
+}
+
+// Possible optimization: Only recurse if needed.
+impl<'self> visit::Visitor<()> for NamespaceVisitor<'self> {
+
+    fn visit_mod(&mut self,
+                 module: &ast::_mod,
+                 span: Span,
+                 _: ast::NodeId,
+                 _: ()) {
+        let module_name = token::ident_to_str(&self.module_ident);
+
+        let (parent_node, parent_scope) = if self.scope_stack.len() > 0 {
+            let parent_node = *self.scope_stack.last();
+            (Some(parent_node), parent_node.scope)
+        } else {
+            (None, ptr::null())
+        };
+
+        let loc = span_start(self.crate_context, span);
+        let file_metadata = file_metadata(self.crate_context, loc.file.name);
+
+        let namespace_metadata = unsafe {
+            do module_name.with_c_str |module_name| {
+                llvm::LLVMDIBuilderCreateNameSpace(
+                    DIB(self.crate_context),
+                    parent_scope,
+                    module_name,
+                    file_metadata,
+                    loc.line as c_uint)
+            }
+        };
+
+        let this_node = @NamespaceTreeNode {
+            scope: namespace_metadata,
+            ident: self.module_ident,
+            parent: parent_node,
+        };
+
+        self.scope_stack.push(this_node);
+
+        visit::walk_mod(self, module, ());
+
+        self.scope_stack.pop();
+    }
+
+    fn visit_item(&mut self, item: @ast::item, _: ()) {
+        match item.node {
+            ast::item_mod(*) => {
+                // always store the last module ident so visit_mod() has it available
+                self.module_ident = item.ident;
+            }
+            ast::item_fn(*) => { /* handled by visit_fn */ }
+            _ => {
+                debug_context(self.crate_context)
+                    .local_namespace_map
+                    .insert(item.id, *self.scope_stack.last());
+            }
+        }
+
+        visit::walk_item(self, item, ());
+    }
+
+    fn visit_fn(&mut self,
+                _: &visit::fn_kind,
+                _: &ast::fn_decl,
+                _: &ast::Block,
+                _: Span,
+                node_id: ast::NodeId,
+                _: ()) {
+        debug_context(self.crate_context)
+            .local_namespace_map
+            .insert(node_id, *self.scope_stack.last());
+    }
+}
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index 226a7c34304..22288a27624 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -727,9 +727,9 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateTemplateTypeParameter(
     LLVMValueRef Scope,
     const char* Name,
     LLVMValueRef Ty,
-    LLVMValueRef File = 0,
-    unsigned LineNo = 0,
-    unsigned ColumnNo = 0)
+    LLVMValueRef File,
+    unsigned LineNo,
+    unsigned ColumnNo)
 {
     return wrap(Builder->createTemplateTypeParameter(
       unwrapDI<DIDescriptor>(Scope),
@@ -775,3 +775,17 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateComplexVariable(
         ArgNo
     ));
 }
+
+extern "C" LLVMValueRef LLVMDIBuilderCreateNameSpace(
+    DIBuilderRef Builder,
+    LLVMValueRef Scope,
+    const char* Name,
+    LLVMValueRef File,
+    unsigned LineNo)
+{
+    return wrap(Builder->createNameSpace(
+        unwrapDI<DIDescriptor>(Scope),
+        Name,
+        unwrapDI<DIFile>(File),
+        LineNo));
+}
diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in
index d905370f587..2c7c445d308 100644
--- a/src/rustllvm/rustllvm.def.in
+++ b/src/rustllvm/rustllvm.def.in
@@ -611,6 +611,7 @@ LLVMDIBuilderCreateTemplateTypeParameter
 LLVMDIBuilderCreateOpDeref
 LLVMDIBuilderCreateOpPlus
 LLVMDIBuilderCreateComplexVariable
+LLVMDIBuilderCreateNameSpace
 LLVMSetUnnamedAddr
 LLVMRustAddPass
 LLVMRustAddAnalysisPasses
diff --git a/src/test/debug-info/basic-types.rs b/src/test/debug-info/basic-types.rs
index 5f769fceded..84d9c2c66cc 100644
--- a/src/test/debug-info/basic-types.rs
+++ b/src/test/debug-info/basic-types.rs
@@ -15,7 +15,7 @@
 // its numerical value.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break _zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 // debugger:print b
diff --git a/src/test/debug-info/borrowed-basic.rs b/src/test/debug-info/borrowed-basic.rs
index 8c19225311a..b02b4be2fd9 100644
--- a/src/test/debug-info/borrowed-basic.rs
+++ b/src/test/debug-info/borrowed-basic.rs
@@ -12,7 +12,7 @@
 // its numerical value.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 // debugger:print *bool_ref
diff --git a/src/test/debug-info/borrowed-c-style-enum.rs b/src/test/debug-info/borrowed-c-style-enum.rs
index b947cd80984..2461eb4887e 100644
--- a/src/test/debug-info/borrowed-c-style-enum.rs
+++ b/src/test/debug-info/borrowed-c-style-enum.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/borrowed-enum.rs b/src/test/debug-info/borrowed-enum.rs
index 6ac02390225..9a9e71c7068 100644
--- a/src/test/debug-info/borrowed-enum.rs
+++ b/src/test/debug-info/borrowed-enum.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/borrowed-managed-basic.rs b/src/test/debug-info/borrowed-managed-basic.rs
index c91f64973ad..35a222ffd04 100644
--- a/src/test/debug-info/borrowed-managed-basic.rs
+++ b/src/test/debug-info/borrowed-managed-basic.rs
@@ -12,7 +12,7 @@
 // its numerical value.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 // debugger:print *bool_ref
diff --git a/src/test/debug-info/borrowed-struct.rs b/src/test/debug-info/borrowed-struct.rs
index 75a47a0d8fe..42f7ffd8777 100644
--- a/src/test/debug-info/borrowed-struct.rs
+++ b/src/test/debug-info/borrowed-struct.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/borrowed-tuple.rs b/src/test/debug-info/borrowed-tuple.rs
index 493cd2ab3e1..bcf73bae5ec 100644
--- a/src/test/debug-info/borrowed-tuple.rs
+++ b/src/test/debug-info/borrowed-tuple.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/borrowed-unique-basic.rs b/src/test/debug-info/borrowed-unique-basic.rs
index 50ac34cbcf6..ac295783c9f 100644
--- a/src/test/debug-info/borrowed-unique-basic.rs
+++ b/src/test/debug-info/borrowed-unique-basic.rs
@@ -12,7 +12,7 @@
 // its numerical value.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 // debugger:print *bool_ref
diff --git a/src/test/debug-info/box.rs b/src/test/debug-info/box.rs
index 1a87392e6af..60ff5f789a8 100644
--- a/src/test/debug-info/box.rs
+++ b/src/test/debug-info/box.rs
@@ -10,7 +10,7 @@
 
 // compile-flags:-Z extra-debug-info
 // debugger:set print pretty off
-// debugger:break _zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 // debugger:print *a
diff --git a/src/test/debug-info/boxed-struct.rs b/src/test/debug-info/boxed-struct.rs
index 03be8f7f220..e996b249d36 100644
--- a/src/test/debug-info/boxed-struct.rs
+++ b/src/test/debug-info/boxed-struct.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/boxed-vec.rs b/src/test/debug-info/boxed-vec.rs
index b08f549e129..aa2a88afc46 100644
--- a/src/test/debug-info/boxed-vec.rs
+++ b/src/test/debug-info/boxed-vec.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/by-value-non-immediate-argument.rs b/src/test/debug-info/by-value-non-immediate-argument.rs
index da9c79a00ed..45f8c134f2c 100644
--- a/src/test/debug-info/by-value-non-immediate-argument.rs
+++ b/src/test/debug-info/by-value-non-immediate-argument.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // debugger:finish
diff --git a/src/test/debug-info/by-value-self-argument-in-trait-impl.rs b/src/test/debug-info/by-value-self-argument-in-trait-impl.rs
index 6e381c74a33..75e65178546 100644
--- a/src/test/debug-info/by-value-self-argument-in-trait-impl.rs
+++ b/src/test/debug-info/by-value-self-argument-in-trait-impl.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // debugger:finish
diff --git a/src/test/debug-info/c-style-enum-in-composite.rs b/src/test/debug-info/c-style-enum-in-composite.rs
index 8baca2baa42..d3e27c85b74 100644
--- a/src/test/debug-info/c-style-enum-in-composite.rs
+++ b/src/test/debug-info/c-style-enum-in-composite.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/c-style-enum.rs b/src/test/debug-info/c-style-enum.rs
index a60c28cedb4..f1bb42ac5f0 100644
--- a/src/test/debug-info/c-style-enum.rs
+++ b/src/test/debug-info/c-style-enum.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/closure-in-generic-function.rs b/src/test/debug-info/closure-in-generic-function.rs
index 37ad6f173d1..83a2c456ae6 100644
--- a/src/test/debug-info/closure-in-generic-function.rs
+++ b/src/test/debug-info/closure-in-generic-function.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // debugger:finish
diff --git a/src/test/debug-info/destructured-fn-argument.rs b/src/test/debug-info/destructured-fn-argument.rs
index 63b46875a49..49bbb7ed263 100644
--- a/src/test/debug-info/destructured-fn-argument.rs
+++ b/src/test/debug-info/destructured-fn-argument.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // debugger:finish
diff --git a/src/test/debug-info/destructured-local.rs b/src/test/debug-info/destructured-local.rs
index 424e195e681..8115d298570 100644
--- a/src/test/debug-info/destructured-local.rs
+++ b/src/test/debug-info/destructured-local.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/evec-in-struct.rs b/src/test/debug-info/evec-in-struct.rs
index de556bb1772..a00e1318967 100644
--- a/src/test/debug-info/evec-in-struct.rs
+++ b/src/test/debug-info/evec-in-struct.rs
@@ -10,7 +10,7 @@
 
 // compile-flags:-Z extra-debug-info
 // debugger:set print pretty off
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/function-arguments.rs b/src/test/debug-info/function-arguments.rs
index 5a410ef6462..6ae7b027075 100644
--- a/src/test/debug-info/function-arguments.rs
+++ b/src/test/debug-info/function-arguments.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
@@ -43,4 +43,4 @@ fn fun(x: int, y: bool) -> (int, bool) {
     (x, y)
 }
 
-fn zzz() {()}
\ No newline at end of file
+fn zzz() {()}
diff --git a/src/test/debug-info/generic-function.rs b/src/test/debug-info/generic-function.rs
index 1bde5acd9f6..22f565ceee5 100644
--- a/src/test/debug-info/generic-function.rs
+++ b/src/test/debug-info/generic-function.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // debugger:finish
diff --git a/src/test/debug-info/generic-functions-nested.rs b/src/test/debug-info/generic-functions-nested.rs
index 3151562f3f2..051b2054219 100644
--- a/src/test/debug-info/generic-functions-nested.rs
+++ b/src/test/debug-info/generic-functions-nested.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // debugger:finish
diff --git a/src/test/debug-info/generic-method-on-generic-struct.rs b/src/test/debug-info/generic-method-on-generic-struct.rs
index 131f89c5a6d..f97a3cea566 100644
--- a/src/test/debug-info/generic-method-on-generic-struct.rs
+++ b/src/test/debug-info/generic-method-on-generic-struct.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // STACK BY REF
diff --git a/src/test/debug-info/generic-static-method-on-struct-and-enum.rs b/src/test/debug-info/generic-static-method-on-struct-and-enum.rs
index f7ecad0b095..8e82f0f27b9 100644
--- a/src/test/debug-info/generic-static-method-on-struct-and-enum.rs
+++ b/src/test/debug-info/generic-static-method-on-struct-and-enum.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // STRUCT
diff --git a/src/test/debug-info/generic-struct-style-enum.rs b/src/test/debug-info/generic-struct-style-enum.rs
index 6a8f81aa843..81b12fe60ae 100644
--- a/src/test/debug-info/generic-struct-style-enum.rs
+++ b/src/test/debug-info/generic-struct-style-enum.rs
@@ -10,7 +10,7 @@
 
 // compile-flags:-Z extra-debug-info
 // debugger:set print union on
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/generic-struct.rs b/src/test/debug-info/generic-struct.rs
index efc250018c1..cf6286e9541 100644
--- a/src/test/debug-info/generic-struct.rs
+++ b/src/test/debug-info/generic-struct.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // debugger:finish
diff --git a/src/test/debug-info/generic-trait-generic-static-default-method.rs b/src/test/debug-info/generic-trait-generic-static-default-method.rs
index 9dd6d1ef173..8523a947aac 100644
--- a/src/test/debug-info/generic-trait-generic-static-default-method.rs
+++ b/src/test/debug-info/generic-trait-generic-static-default-method.rs
@@ -11,7 +11,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // debugger:finish
diff --git a/src/test/debug-info/generic-tuple-style-enum.rs b/src/test/debug-info/generic-tuple-style-enum.rs
index b97fa7b636b..0b9f9350547 100644
--- a/src/test/debug-info/generic-tuple-style-enum.rs
+++ b/src/test/debug-info/generic-tuple-style-enum.rs
@@ -10,7 +10,7 @@
 
 // compile-flags:-Z extra-debug-info
 // debugger:set print union on
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/lexical-scope-in-for-loop.rs b/src/test/debug-info/lexical-scope-in-for-loop.rs
index ed2f9e1a0c4..0a2cb953f00 100644
--- a/src/test/debug-info/lexical-scope-in-for-loop.rs
+++ b/src/test/debug-info/lexical-scope-in-for-loop.rs
@@ -11,7 +11,7 @@
 // xfail-win32
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // FIRST ITERATION
diff --git a/src/test/debug-info/lexical-scope-in-if.rs b/src/test/debug-info/lexical-scope-in-if.rs
index cc637f55fee..89fd84daede 100644
--- a/src/test/debug-info/lexical-scope-in-if.rs
+++ b/src/test/debug-info/lexical-scope-in-if.rs
@@ -11,7 +11,7 @@
 // xfail-win32
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // BEFORE if
diff --git a/src/test/debug-info/lexical-scope-in-managed-closure.rs b/src/test/debug-info/lexical-scope-in-managed-closure.rs
index 8af674d5ebd..96da78a9192 100644
--- a/src/test/debug-info/lexical-scope-in-managed-closure.rs
+++ b/src/test/debug-info/lexical-scope-in-managed-closure.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // debugger:finish
diff --git a/src/test/debug-info/lexical-scope-in-match.rs b/src/test/debug-info/lexical-scope-in-match.rs
index fe57f1f588e..1216e9fde1e 100644
--- a/src/test/debug-info/lexical-scope-in-match.rs
+++ b/src/test/debug-info/lexical-scope-in-match.rs
@@ -11,7 +11,7 @@
 // xfail-win32
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // debugger:finish
diff --git a/src/test/debug-info/lexical-scope-in-stack-closure.rs b/src/test/debug-info/lexical-scope-in-stack-closure.rs
index 101b076a460..744c77b2735 100644
--- a/src/test/debug-info/lexical-scope-in-stack-closure.rs
+++ b/src/test/debug-info/lexical-scope-in-stack-closure.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // debugger:finish
diff --git a/src/test/debug-info/lexical-scope-in-unconditional-loop.rs b/src/test/debug-info/lexical-scope-in-unconditional-loop.rs
index 6031a0ac714..beb9211cc32 100644
--- a/src/test/debug-info/lexical-scope-in-unconditional-loop.rs
+++ b/src/test/debug-info/lexical-scope-in-unconditional-loop.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // FIRST ITERATION
diff --git a/src/test/debug-info/lexical-scope-in-unique-closure.rs b/src/test/debug-info/lexical-scope-in-unique-closure.rs
index e167d7637ad..6d8ca457efe 100644
--- a/src/test/debug-info/lexical-scope-in-unique-closure.rs
+++ b/src/test/debug-info/lexical-scope-in-unique-closure.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // debugger:finish
diff --git a/src/test/debug-info/lexical-scope-in-while.rs b/src/test/debug-info/lexical-scope-in-while.rs
index 2a3071ba496..80010bdd262 100644
--- a/src/test/debug-info/lexical-scope-in-while.rs
+++ b/src/test/debug-info/lexical-scope-in-while.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // FIRST ITERATION
diff --git a/src/test/debug-info/lexical-scope-with-macro.rs b/src/test/debug-info/lexical-scope-with-macro.rs
index 1223786eb18..9e87eee692d 100644
--- a/src/test/debug-info/lexical-scope-with-macro.rs
+++ b/src/test/debug-info/lexical-scope-with-macro.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // debugger:finish
diff --git a/src/test/debug-info/lexical-scopes-in-block-expression.rs b/src/test/debug-info/lexical-scopes-in-block-expression.rs
index ea2a7f0d94a..652561c6aef 100644
--- a/src/test/debug-info/lexical-scopes-in-block-expression.rs
+++ b/src/test/debug-info/lexical-scopes-in-block-expression.rs
@@ -11,7 +11,7 @@
 // xfail-win32
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // STRUCT EXPRESSION
diff --git a/src/test/debug-info/managed-enum.rs b/src/test/debug-info/managed-enum.rs
index 99452dc255a..87aa3d1dfc1 100644
--- a/src/test/debug-info/managed-enum.rs
+++ b/src/test/debug-info/managed-enum.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/managed-pointer-within-unique-vec.rs b/src/test/debug-info/managed-pointer-within-unique-vec.rs
index 35df9454e10..d4ec7094e8c 100644
--- a/src/test/debug-info/managed-pointer-within-unique-vec.rs
+++ b/src/test/debug-info/managed-pointer-within-unique-vec.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/managed-pointer-within-unique.rs b/src/test/debug-info/managed-pointer-within-unique.rs
index e007f012ce2..9ea713c2982 100644
--- a/src/test/debug-info/managed-pointer-within-unique.rs
+++ b/src/test/debug-info/managed-pointer-within-unique.rs
@@ -10,7 +10,7 @@
 
 // compile-flags:-Z extra-debug-info
 // debugger:set print pretty off
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/method-on-enum.rs b/src/test/debug-info/method-on-enum.rs
index c68b4e7deed..d428d230d45 100644
--- a/src/test/debug-info/method-on-enum.rs
+++ b/src/test/debug-info/method-on-enum.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // STACK BY REF
diff --git a/src/test/debug-info/method-on-generic-struct.rs b/src/test/debug-info/method-on-generic-struct.rs
index 4c793a6d9c7..63fd6c996ff 100644
--- a/src/test/debug-info/method-on-generic-struct.rs
+++ b/src/test/debug-info/method-on-generic-struct.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // STACK BY REF
diff --git a/src/test/debug-info/method-on-struct.rs b/src/test/debug-info/method-on-struct.rs
index 5711c945b65..249c3a073a2 100644
--- a/src/test/debug-info/method-on-struct.rs
+++ b/src/test/debug-info/method-on-struct.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // STACK BY REF
diff --git a/src/test/debug-info/method-on-trait.rs b/src/test/debug-info/method-on-trait.rs
index c2f3a7f4324..07a29f3ece3 100644
--- a/src/test/debug-info/method-on-trait.rs
+++ b/src/test/debug-info/method-on-trait.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // STACK BY REF
diff --git a/src/test/debug-info/method-on-tuple-struct.rs b/src/test/debug-info/method-on-tuple-struct.rs
index e14880ae1a0..d4354709a86 100644
--- a/src/test/debug-info/method-on-tuple-struct.rs
+++ b/src/test/debug-info/method-on-tuple-struct.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // STACK BY REF
diff --git a/src/test/debug-info/multiple-functions-equal-var-names.rs b/src/test/debug-info/multiple-functions-equal-var-names.rs
index 32b3da07411..881e2547cfc 100644
--- a/src/test/debug-info/multiple-functions-equal-var-names.rs
+++ b/src/test/debug-info/multiple-functions-equal-var-names.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/multiple-functions.rs b/src/test/debug-info/multiple-functions.rs
index be26af4fe2f..880954ce531 100644
--- a/src/test/debug-info/multiple-functions.rs
+++ b/src/test/debug-info/multiple-functions.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/name-shadowing-and-scope-nesting.rs b/src/test/debug-info/name-shadowing-and-scope-nesting.rs
index 739d3aa78f4..273ca255061 100644
--- a/src/test/debug-info/name-shadowing-and-scope-nesting.rs
+++ b/src/test/debug-info/name-shadowing-and-scope-nesting.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // debugger:finish
diff --git a/src/test/debug-info/nil-enum.rs b/src/test/debug-info/nil-enum.rs
index 94e5b706ac6..9dc4edfb159 100644
--- a/src/test/debug-info/nil-enum.rs
+++ b/src/test/debug-info/nil-enum.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/option-like-enum.rs b/src/test/debug-info/option-like-enum.rs
index a75f4ff0086..5c0ffe24f0e 100644
--- a/src/test/debug-info/option-like-enum.rs
+++ b/src/test/debug-info/option-like-enum.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/packed-struct-with-destructor.rs b/src/test/debug-info/packed-struct-with-destructor.rs
index 90033b9c4e6..47e4a26ab4b 100644
--- a/src/test/debug-info/packed-struct-with-destructor.rs
+++ b/src/test/debug-info/packed-struct-with-destructor.rs
@@ -10,7 +10,7 @@
 
 // compile-flags:-Z extra-debug-info
 // debugger:set print pretty off
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/packed-struct.rs b/src/test/debug-info/packed-struct.rs
index 203f6595a04..8d3fc4babb8 100644
--- a/src/test/debug-info/packed-struct.rs
+++ b/src/test/debug-info/packed-struct.rs
@@ -10,7 +10,7 @@
 
 // compile-flags:-Z extra-debug-info
 // debugger:set print pretty off
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/self-in-default-method.rs b/src/test/debug-info/self-in-default-method.rs
index 426d2f46e6b..53b2e9ee21d 100644
--- a/src/test/debug-info/self-in-default-method.rs
+++ b/src/test/debug-info/self-in-default-method.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // STACK BY REF
diff --git a/src/test/debug-info/self-in-generic-default-method.rs b/src/test/debug-info/self-in-generic-default-method.rs
index 16a028808e7..47f58930760 100644
--- a/src/test/debug-info/self-in-generic-default-method.rs
+++ b/src/test/debug-info/self-in-generic-default-method.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // STACK BY REF
diff --git a/src/test/debug-info/shadowed-argument.rs b/src/test/debug-info/shadowed-argument.rs
index a6a7b34c87b..adc240e40d5 100644
--- a/src/test/debug-info/shadowed-argument.rs
+++ b/src/test/debug-info/shadowed-argument.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // debugger:finish
diff --git a/src/test/debug-info/shadowed-variable.rs b/src/test/debug-info/shadowed-variable.rs
index 9018e24691e..acc8cf3b654 100644
--- a/src/test/debug-info/shadowed-variable.rs
+++ b/src/test/debug-info/shadowed-variable.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // debugger:finish
diff --git a/src/test/debug-info/simple-lexical-scope.rs b/src/test/debug-info/simple-lexical-scope.rs
index 11e890c44fa..fbcee4f0ae2 100644
--- a/src/test/debug-info/simple-lexical-scope.rs
+++ b/src/test/debug-info/simple-lexical-scope.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // debugger:finish
diff --git a/src/test/debug-info/simple-struct.rs b/src/test/debug-info/simple-struct.rs
index 01cc163d7aa..a47472af1ef 100644
--- a/src/test/debug-info/simple-struct.rs
+++ b/src/test/debug-info/simple-struct.rs
@@ -10,7 +10,7 @@
 
 // compile-flags:-Z extra-debug-info
 // debugger:set print pretty off
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/simple-tuple.rs b/src/test/debug-info/simple-tuple.rs
index ee65e4dcb20..1e4c53427b2 100644
--- a/src/test/debug-info/simple-tuple.rs
+++ b/src/test/debug-info/simple-tuple.rs
@@ -10,7 +10,7 @@
 
 // compile-flags:-Z extra-debug-info
 // debugger:set print pretty off
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/static-method-on-struct-and-enum.rs b/src/test/debug-info/static-method-on-struct-and-enum.rs
index 5cf0bbdc8cf..0d1ce28094a 100644
--- a/src/test/debug-info/static-method-on-struct-and-enum.rs
+++ b/src/test/debug-info/static-method-on-struct-and-enum.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // STRUCT
diff --git a/src/test/debug-info/struct-in-enum.rs b/src/test/debug-info/struct-in-enum.rs
index 8542dd867f4..a821ce21d50 100644
--- a/src/test/debug-info/struct-in-enum.rs
+++ b/src/test/debug-info/struct-in-enum.rs
@@ -10,7 +10,7 @@
 
 // compile-flags:-Z extra-debug-info
 // debugger:set print union on
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/struct-in-struct.rs b/src/test/debug-info/struct-in-struct.rs
index 307d141c3e2..f1690fba354 100644
--- a/src/test/debug-info/struct-in-struct.rs
+++ b/src/test/debug-info/struct-in-struct.rs
@@ -10,7 +10,7 @@
 
 // compile-flags:-Z extra-debug-info
 // debugger:set print pretty off
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/struct-style-enum.rs b/src/test/debug-info/struct-style-enum.rs
index fe6845a9077..acd2526a68d 100644
--- a/src/test/debug-info/struct-style-enum.rs
+++ b/src/test/debug-info/struct-style-enum.rs
@@ -10,7 +10,7 @@
 
 // compile-flags:-Z extra-debug-info
 // debugger:set print union on
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/struct-with-destructor.rs b/src/test/debug-info/struct-with-destructor.rs
index 2dc1bfbf236..8994a582b58 100644
--- a/src/test/debug-info/struct-with-destructor.rs
+++ b/src/test/debug-info/struct-with-destructor.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 // debugger:print simple
diff --git a/src/test/debug-info/trait-generic-static-default-method.rs b/src/test/debug-info/trait-generic-static-default-method.rs
index 2d666bf4cf5..1f6e6992e27 100644
--- a/src/test/debug-info/trait-generic-static-default-method.rs
+++ b/src/test/debug-info/trait-generic-static-default-method.rs
@@ -11,7 +11,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 
 // debugger:finish
diff --git a/src/test/debug-info/tuple-in-struct.rs b/src/test/debug-info/tuple-in-struct.rs
index e5844cd19a7..25a08b3f57a 100644
--- a/src/test/debug-info/tuple-in-struct.rs
+++ b/src/test/debug-info/tuple-in-struct.rs
@@ -10,7 +10,7 @@
 
 // compile-flags:-Z extra-debug-info
 // debugger:set print pretty off
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/tuple-in-tuple.rs b/src/test/debug-info/tuple-in-tuple.rs
index 8a50760bcc2..14dd671bb94 100644
--- a/src/test/debug-info/tuple-in-tuple.rs
+++ b/src/test/debug-info/tuple-in-tuple.rs
@@ -10,7 +10,7 @@
 
 // compile-flags:-Z extra-debug-info
 // debugger:set print pretty off
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/tuple-struct.rs b/src/test/debug-info/tuple-struct.rs
index 762b8dcb38f..63a74ecbe4a 100644
--- a/src/test/debug-info/tuple-struct.rs
+++ b/src/test/debug-info/tuple-struct.rs
@@ -10,7 +10,7 @@
 
 // compile-flags:-Z extra-debug-info
 // debugger:set print pretty off
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/tuple-style-enum.rs b/src/test/debug-info/tuple-style-enum.rs
index 29950e6c766..fef6b449a9b 100644
--- a/src/test/debug-info/tuple-style-enum.rs
+++ b/src/test/debug-info/tuple-style-enum.rs
@@ -10,7 +10,7 @@
 
 // compile-flags:-Z extra-debug-info
 // debugger:set print union on
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/unique-enum.rs b/src/test/debug-info/unique-enum.rs
index 8c085b1c62b..0995cec11a3 100644
--- a/src/test/debug-info/unique-enum.rs
+++ b/src/test/debug-info/unique-enum.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/var-captured-in-managed-closure.rs b/src/test/debug-info/var-captured-in-managed-closure.rs
index 002bfbd2242..b20f40378d3 100644
--- a/src/test/debug-info/var-captured-in-managed-closure.rs
+++ b/src/test/debug-info/var-captured-in-managed-closure.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/var-captured-in-nested-closure.rs b/src/test/debug-info/var-captured-in-nested-closure.rs
index cd20209ddfd..920052eb80e 100644
--- a/src/test/debug-info/var-captured-in-nested-closure.rs
+++ b/src/test/debug-info/var-captured-in-nested-closure.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/var-captured-in-sendable-closure.rs b/src/test/debug-info/var-captured-in-sendable-closure.rs
index 01839ea7835..f113c6ea4be 100644
--- a/src/test/debug-info/var-captured-in-sendable-closure.rs
+++ b/src/test/debug-info/var-captured-in-sendable-closure.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/var-captured-in-stack-closure.rs b/src/test/debug-info/var-captured-in-stack-closure.rs
index 3ce7d6fd89b..e16539d3396 100644
--- a/src/test/debug-info/var-captured-in-stack-closure.rs
+++ b/src/test/debug-info/var-captured-in-stack-closure.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // compile-flags:-Z extra-debug-info
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 
diff --git a/src/test/debug-info/vec-slices.rs b/src/test/debug-info/vec-slices.rs
index 95679f3a616..9e5fb9236db 100644
--- a/src/test/debug-info/vec-slices.rs
+++ b/src/test/debug-info/vec-slices.rs
@@ -10,7 +10,7 @@
 
 // compile-flags:-Z extra-debug-info
 // debugger:set print pretty off
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 // debugger:print empty.size_in_bytes
diff --git a/src/test/debug-info/vec.rs b/src/test/debug-info/vec.rs
index 0dc52c7b220..bc10b5ec8b7 100644
--- a/src/test/debug-info/vec.rs
+++ b/src/test/debug-info/vec.rs
@@ -10,7 +10,7 @@
 
 // compile-flags:-Z extra-debug-info
 // debugger:set print pretty off
-// debugger:break zzz
+// debugger:rbreak zzz
 // debugger:run
 // debugger:finish
 // debugger:print a