diff --git a/src/librustc_trans/trans/debuginfo/mod.rs b/src/librustc_trans/trans/debuginfo/mod.rs index c1cdfb587b3e..ea0bbfd73ae2 100644 --- a/src/librustc_trans/trans/debuginfo/mod.rs +++ b/src/librustc_trans/trans/debuginfo/mod.rs @@ -14,11 +14,13 @@ mod doc; pub mod gdb; mod utils; mod create; +mod namespace; use self::utils::{debug_context, DIB, span_start, bytes_to_bits, size_and_align_of, assert_type_for_node_id, get_namespace_and_span_for_item, fn_should_be_ignored, contains_nodebug_attribute, create_scope_map}; use self::create::{declare_local, create_DIArray, is_node_local_to_unit}; +use self::namespace::{namespace_for_item, NamespaceTreeNode, crate_root_namespace}; use self::VariableAccess::*; use self::VariableKind::*; @@ -51,7 +53,7 @@ use std::cell::{Cell, RefCell}; use std::ffi::CString; use std::path::Path; use std::ptr; -use std::rc::{Rc, Weak}; +use std::rc::Rc; use syntax::util::interner::Interner; use syntax::codemap::{Span, Pos}; use syntax::{ast, codemap, ast_util, ast_map}; @@ -3103,118 +3105,3 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, output.push('>'); } } - - -//=----------------------------------------------------------------------------- -// Namespace Handling -//=----------------------------------------------------------------------------- - -struct NamespaceTreeNode { - name: ast::Name, - scope: DIScope, - parent: Option>, -} - -impl NamespaceTreeNode { - fn mangled_name_of_contained_item(&self, item_name: &str) -> String { - fn fill_nested(node: &NamespaceTreeNode, output: &mut String) { - match node.parent { - Some(ref parent) => fill_nested(&*parent.upgrade().unwrap(), output), - None => {} - } - let string = token::get_name(node.name); - output.push_str(&format!("{}", string.len())); - output.push_str(&string); - } - - let mut name = String::from_str("_ZN"); - fill_nested(self, &mut name); - name.push_str(&format!("{}", item_name.len())); - name.push_str(item_name); - name.push('E'); - name - } -} - -fn crate_root_namespace<'a>(cx: &'a CrateContext) -> &'a str { - &cx.link_meta().crate_name -} - -fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc { - ty::with_path(cx.tcx(), def_id, |path| { - // prepend crate name if not already present - let krate = if def_id.krate == ast::LOCAL_CRATE { - let crate_namespace_name = token::intern(crate_root_namespace(cx)); - Some(ast_map::PathMod(crate_namespace_name)) - } else { - None - }; - let mut path = krate.into_iter().chain(path).peekable(); - - let mut current_key = Vec::new(); - let mut parent_node: Option> = None; - - // Create/Lookup namespace for each element of the path. - loop { - // Emulate a for loop so we can use peek below. - let path_element = match path.next() { - Some(e) => e, - None => break - }; - // Ignore the name of the item (the last path element). - if path.peek().is_none() { - break; - } - - let name = path_element.name(); - current_key.push(name); - - let existing_node = debug_context(cx).namespace_map.borrow() - .get(¤t_key).cloned(); - let current_node = match existing_node { - Some(existing_node) => existing_node, - None => { - // create and insert - let parent_scope = match parent_node { - Some(ref node) => node.scope, - None => ptr::null_mut() - }; - let namespace_name = token::get_name(name); - let namespace_name = CString::new(namespace_name.as_bytes()).unwrap(); - let scope = unsafe { - llvm::LLVMDIBuilderCreateNameSpace( - DIB(cx), - parent_scope, - namespace_name.as_ptr(), - // cannot reconstruct file ... - ptr::null_mut(), - // ... or line information, but that's not so important. - 0) - }; - - let node = Rc::new(NamespaceTreeNode { - name: name, - scope: scope, - parent: parent_node.map(|parent| parent.downgrade()), - }); - - debug_context(cx).namespace_map.borrow_mut() - .insert(current_key.clone(), node.clone()); - - node - } - }; - - parent_node = Some(current_node); - } - - match parent_node { - Some(node) => node, - None => { - cx.sess().bug(&format!("debuginfo::namespace_for_item(): \ - path too short for {:?}", - def_id)); - } - } - }) -} diff --git a/src/librustc_trans/trans/debuginfo/namespace.rs b/src/librustc_trans/trans/debuginfo/namespace.rs new file mode 100644 index 000000000000..1300a2039183 --- /dev/null +++ b/src/librustc_trans/trans/debuginfo/namespace.rs @@ -0,0 +1,134 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Namespace Handling + +use super::utils::{DIB, debug_context}; + +use llvm; +use llvm::debuginfo::DIScope; +use trans::common::CrateContext; +use middle::ty::{self, ClosureTyper}; + +use std::ffi::CString; +use std::ptr; +use std::rc::{Rc, Weak}; +use syntax::{ast, ast_map}; +use syntax::parse::token; + +pub struct NamespaceTreeNode { + pub name: ast::Name, + pub scope: DIScope, + pub parent: Option>, +} + +impl NamespaceTreeNode { + pub fn mangled_name_of_contained_item(&self, item_name: &str) -> String { + fn fill_nested(node: &NamespaceTreeNode, output: &mut String) { + match node.parent { + Some(ref parent) => fill_nested(&*parent.upgrade().unwrap(), output), + None => {} + } + let string = token::get_name(node.name); + output.push_str(&format!("{}", string.len())); + output.push_str(&string); + } + + let mut name = String::from_str("_ZN"); + fill_nested(self, &mut name); + name.push_str(&format!("{}", item_name.len())); + name.push_str(item_name); + name.push('E'); + name + } +} + +pub fn crate_root_namespace<'a>(cx: &'a CrateContext) -> &'a str { + &cx.link_meta().crate_name +} + +pub fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc { + ty::with_path(cx.tcx(), def_id, |path| { + // prepend crate name if not already present + let krate = if def_id.krate == ast::LOCAL_CRATE { + let crate_namespace_name = token::intern(crate_root_namespace(cx)); + Some(ast_map::PathMod(crate_namespace_name)) + } else { + None + }; + let mut path = krate.into_iter().chain(path).peekable(); + + let mut current_key = Vec::new(); + let mut parent_node: Option> = None; + + // Create/Lookup namespace for each element of the path. + loop { + // Emulate a for loop so we can use peek below. + let path_element = match path.next() { + Some(e) => e, + None => break + }; + // Ignore the name of the item (the last path element). + if path.peek().is_none() { + break; + } + + let name = path_element.name(); + current_key.push(name); + + let existing_node = debug_context(cx).namespace_map.borrow() + .get(¤t_key).cloned(); + let current_node = match existing_node { + Some(existing_node) => existing_node, + None => { + // create and insert + let parent_scope = match parent_node { + Some(ref node) => node.scope, + None => ptr::null_mut() + }; + let namespace_name = token::get_name(name); + let namespace_name = CString::new(namespace_name.as_bytes()).unwrap(); + let scope = unsafe { + llvm::LLVMDIBuilderCreateNameSpace( + DIB(cx), + parent_scope, + namespace_name.as_ptr(), + // cannot reconstruct file ... + ptr::null_mut(), + // ... or line information, but that's not so important. + 0) + }; + + let node = Rc::new(NamespaceTreeNode { + name: name, + scope: scope, + parent: parent_node.map(|parent| parent.downgrade()), + }); + + debug_context(cx).namespace_map.borrow_mut() + .insert(current_key.clone(), node.clone()); + + node + } + }; + + parent_node = Some(current_node); + } + + match parent_node { + Some(node) => node, + None => { + cx.sess().bug(&format!("debuginfo::namespace_for_item(): \ + path too short for {:?}", + def_id)); + } + } + }) +} diff --git a/src/librustc_trans/trans/debuginfo/utils.rs b/src/librustc_trans/trans/debuginfo/utils.rs index 161128279fed..858fb2be4f74 100644 --- a/src/librustc_trans/trans/debuginfo/utils.rs +++ b/src/librustc_trans/trans/debuginfo/utils.rs @@ -10,7 +10,8 @@ // Utility Functions. -use super::{FunctionDebugContext, CrateDebugContext, namespace_for_item, file_metadata}; +use super::{FunctionDebugContext, CrateDebugContext, file_metadata}; +use super::namespace::namespace_for_item; use llvm; use llvm::debuginfo::{DIScope, DISubprogram, DIBuilderRef};