]> git.lizzy.rs Git - rust.git/blob - src/librustc_trans/trans/debuginfo/namespace.rs
fix spacing issue in trpl/documentation doc
[rust.git] / src / librustc_trans / trans / debuginfo / namespace.rs
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.
4 //
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.
10
11 // Namespace Handling.
12
13 use super::utils::{DIB, debug_context};
14
15 use llvm;
16 use llvm::debuginfo::DIScope;
17 use rustc::ast_map;
18 use trans::common::CrateContext;
19
20 use std::ffi::CString;
21 use std::ptr;
22 use std::rc::{Rc, Weak};
23 use syntax::ast;
24 use syntax::parse::token;
25
26 pub struct NamespaceTreeNode {
27     pub name: ast::Name,
28     pub scope: DIScope,
29     pub parent: Option<Weak<NamespaceTreeNode>>,
30 }
31
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) {
35             match node.parent {
36                 Some(ref parent) => fill_nested(&*parent.upgrade().unwrap(), output),
37                 None => {}
38             }
39             let string = node.name.as_str();
40             output.push_str(&string.len().to_string());
41             output.push_str(&string);
42         }
43
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);
48         name.push('E');
49         name
50     }
51 }
52
53 pub fn crate_root_namespace<'a>(cx: &'a CrateContext) -> &'a str {
54     &cx.link_meta().crate_name
55 }
56
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))
63         } else {
64             None
65         };
66         let mut path = krate.into_iter().chain(path).peekable();
67
68         let mut current_key = Vec::new();
69         let mut parent_node: Option<Rc<NamespaceTreeNode>> = None;
70
71         // Create/Lookup namespace for each element of the path.
72         loop {
73             // Emulate a for loop so we can use peek below.
74             let path_element = match path.next() {
75                 Some(e) => e,
76                 None => break
77             };
78             // Ignore the name of the item (the last path element).
79             if path.peek().is_none() {
80                 break;
81             }
82
83             let name = path_element.name();
84             current_key.push(name);
85
86             let existing_node = debug_context(cx).namespace_map.borrow()
87                                                  .get(&current_key).cloned();
88             let current_node = match existing_node {
89                 Some(existing_node) => existing_node,
90                 None => {
91                     // create and insert
92                     let parent_scope = match parent_node {
93                         Some(ref node) => node.scope,
94                         None => ptr::null_mut()
95                     };
96                     let namespace_name = name.as_str();
97                     let namespace_name = CString::new(namespace_name.as_bytes()).unwrap();
98                     let scope = unsafe {
99                         llvm::LLVMDIBuilderCreateNameSpace(
100                             DIB(cx),
101                             parent_scope,
102                             namespace_name.as_ptr(),
103                             // cannot reconstruct file ...
104                             ptr::null_mut(),
105                             // ... or line information, but that's not so important.
106                             0)
107                     };
108
109                     let node = Rc::new(NamespaceTreeNode {
110                         name: name,
111                         scope: scope,
112                         parent: parent_node.map(|parent| parent.downgrade()),
113                     });
114
115                     debug_context(cx).namespace_map.borrow_mut()
116                                      .insert(current_key.clone(), node.clone());
117
118                     node
119                 }
120             };
121
122             parent_node = Some(current_node);
123         }
124
125         match parent_node {
126             Some(node) => node,
127             None => {
128                 cx.sess().bug(&format!("debuginfo::namespace_for_item(): \
129                                        path too short for {:?}",
130                                       def_id));
131             }
132         }
133     })
134 }