]> git.proxmox.com Git - rustc.git/blob - src/librustc_trans/trans/debuginfo/namespace.rs
Imported Upstream version 1.1.0+dfsg1
[rustc.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 trans::common::CrateContext;
18 use middle::ty::{self, ClosureTyper};
19
20 use std::ffi::CString;
21 use std::ptr;
22 use std::rc::{Rc, Weak};
23 use syntax::{ast, ast_map};
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 = token::get_name(node.name);
40 output.push_str(&format!("{}", string.len()));
41 output.push_str(&string);
42 }
43
44 let mut name = String::from_str("_ZN");
45 fill_nested(self, &mut name);
46 name.push_str(&format!("{}", item_name.len()));
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 ty::with_path(cx.tcx(), 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 = token::get_name(name);
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 }