1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 // Namespace Handling.
13 use super::utils::{DIB, debug_context};
16 use llvm::debuginfo::DIScope;
18 use trans::common::CrateContext;
20 use std::ffi::CString;
22 use std::rc::{Rc, Weak};
24 use syntax::parse::token;
26 pub struct NamespaceTreeNode {
29 pub parent: Option<Weak<NamespaceTreeNode>>,
32 impl NamespaceTreeNode {
33 pub fn mangled_name_of_contained_item(&self, item_name: &str) -> String {
34 fn fill_nested(node: &NamespaceTreeNode, output: &mut String) {
36 Some(ref parent) => fill_nested(&*parent.upgrade().unwrap(), output),
39 let string = node.name.as_str();
40 output.push_str(&string.len().to_string());
41 output.push_str(&string);
44 let mut name = String::from("_ZN");
45 fill_nested(self, &mut name);
46 name.push_str(&item_name.len().to_string());
47 name.push_str(item_name);
53 pub fn crate_root_namespace<'a>(cx: &'a CrateContext) -> &'a str {
54 &cx.link_meta().crate_name
57 pub fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTreeNode> {
58 cx.tcx().with_path(def_id, |path| {
59 // prepend crate name if not already present
60 let krate = if def_id.krate == ast::LOCAL_CRATE {
61 let crate_namespace_name = token::intern(crate_root_namespace(cx));
62 Some(ast_map::PathMod(crate_namespace_name))
66 let mut path = krate.into_iter().chain(path).peekable();
68 let mut current_key = Vec::new();
69 let mut parent_node: Option<Rc<NamespaceTreeNode>> = None;
71 // Create/Lookup namespace for each element of the path.
73 // Emulate a for loop so we can use peek below.
74 let path_element = match path.next() {
78 // Ignore the name of the item (the last path element).
79 if path.peek().is_none() {
83 let name = path_element.name();
84 current_key.push(name);
86 let existing_node = debug_context(cx).namespace_map.borrow()
87 .get(¤t_key).cloned();
88 let current_node = match existing_node {
89 Some(existing_node) => existing_node,
92 let parent_scope = match parent_node {
93 Some(ref node) => node.scope,
94 None => ptr::null_mut()
96 let namespace_name = name.as_str();
97 let namespace_name = CString::new(namespace_name.as_bytes()).unwrap();
99 llvm::LLVMDIBuilderCreateNameSpace(
102 namespace_name.as_ptr(),
103 // cannot reconstruct file ...
105 // ... or line information, but that's not so important.
109 let node = Rc::new(NamespaceTreeNode {
112 parent: parent_node.map(|parent| parent.downgrade()),
115 debug_context(cx).namespace_map.borrow_mut()
116 .insert(current_key.clone(), node.clone());
122 parent_node = Some(current_node);
128 cx.sess().bug(&format!("debuginfo::namespace_for_item(): \
129 path too short for {:?}",