]> git.proxmox.com Git - rustc.git/blob - src/librustc_trans/trans/debuginfo/namespace.rs
Imported Upstream version 1.2.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 rustc::ast_map;
18 use trans::common::CrateContext;
19 use middle::ty::{self, ClosureTyper};
20
21 use std::ffi::CString;
22 use std::ptr;
23 use std::rc::{Rc, Weak};
24 use syntax::ast;
25 use syntax::parse::token;
26
27 pub struct NamespaceTreeNode {
28 pub name: ast::Name,
29 pub scope: DIScope,
30 pub parent: Option<Weak<NamespaceTreeNode>>,
31 }
32
33 impl NamespaceTreeNode {
34 pub fn mangled_name_of_contained_item(&self, item_name: &str) -> String {
35 fn fill_nested(node: &NamespaceTreeNode, output: &mut String) {
36 match node.parent {
37 Some(ref parent) => fill_nested(&*parent.upgrade().unwrap(), output),
38 None => {}
39 }
40 let string = token::get_name(node.name);
41 output.push_str(&format!("{}", string.len()));
42 output.push_str(&string);
43 }
44
45 let mut name = String::from("_ZN");
46 fill_nested(self, &mut name);
47 name.push_str(&format!("{}", item_name.len()));
48 name.push_str(item_name);
49 name.push('E');
50 name
51 }
52 }
53
54 pub fn crate_root_namespace<'a>(cx: &'a CrateContext) -> &'a str {
55 &cx.link_meta().crate_name
56 }
57
58 pub fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTreeNode> {
59 ty::with_path(cx.tcx(), def_id, |path| {
60 // prepend crate name if not already present
61 let krate = if def_id.krate == ast::LOCAL_CRATE {
62 let crate_namespace_name = token::intern(crate_root_namespace(cx));
63 Some(ast_map::PathMod(crate_namespace_name))
64 } else {
65 None
66 };
67 let mut path = krate.into_iter().chain(path).peekable();
68
69 let mut current_key = Vec::new();
70 let mut parent_node: Option<Rc<NamespaceTreeNode>> = None;
71
72 // Create/Lookup namespace for each element of the path.
73 loop {
74 // Emulate a for loop so we can use peek below.
75 let path_element = match path.next() {
76 Some(e) => e,
77 None => break
78 };
79 // Ignore the name of the item (the last path element).
80 if path.peek().is_none() {
81 break;
82 }
83
84 let name = path_element.name();
85 current_key.push(name);
86
87 let existing_node = debug_context(cx).namespace_map.borrow()
88 .get(&current_key).cloned();
89 let current_node = match existing_node {
90 Some(existing_node) => existing_node,
91 None => {
92 // create and insert
93 let parent_scope = match parent_node {
94 Some(ref node) => node.scope,
95 None => ptr::null_mut()
96 };
97 let namespace_name = token::get_name(name);
98 let namespace_name = CString::new(namespace_name.as_bytes()).unwrap();
99 let scope = unsafe {
100 llvm::LLVMDIBuilderCreateNameSpace(
101 DIB(cx),
102 parent_scope,
103 namespace_name.as_ptr(),
104 // cannot reconstruct file ...
105 ptr::null_mut(),
106 // ... or line information, but that's not so important.
107 0)
108 };
109
110 let node = Rc::new(NamespaceTreeNode {
111 name: name,
112 scope: scope,
113 parent: parent_node.map(|parent| parent.downgrade()),
114 });
115
116 debug_context(cx).namespace_map.borrow_mut()
117 .insert(current_key.clone(), node.clone());
118
119 node
120 }
121 };
122
123 parent_node = Some(current_node);
124 }
125
126 match parent_node {
127 Some(node) => node,
128 None => {
129 cx.sess().bug(&format!("debuginfo::namespace_for_item(): \
130 path too short for {:?}",
131 def_id));
132 }
133 }
134 })
135 }