2015-04-24 16:00:47 +12:00
|
|
|
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
2015-04-24 17:25:35 +12:00
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
2015-04-24 16:00:47 +12:00
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
2015-04-24 17:25:35 +12:00
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
2015-04-24 16:00:47 +12:00
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2015-04-24 17:25:35 +12:00
|
|
|
// Namespace Handling.
|
2015-04-24 16:00:47 +12:00
|
|
|
|
|
|
|
use super::utils::{DIB, debug_context};
|
|
|
|
|
|
|
|
use llvm;
|
|
|
|
use llvm::debuginfo::DIScope;
|
2016-03-29 12:54:26 +03:00
|
|
|
use rustc::hir::def_id::DefId;
|
2016-03-29 08:50:44 +03:00
|
|
|
use rustc::hir::map as hir_map;
|
2016-03-22 19:23:36 +02:00
|
|
|
use common::CrateContext;
|
2015-04-24 16:00:47 +12:00
|
|
|
|
|
|
|
use std::ffi::CString;
|
2016-04-06 13:51:55 +03:00
|
|
|
use std::iter::once;
|
2015-04-24 16:00:47 +12:00
|
|
|
use std::ptr;
|
|
|
|
use std::rc::{Rc, Weak};
|
2015-06-10 02:40:45 +03:00
|
|
|
use syntax::ast;
|
2015-04-24 16:00:47 +12:00
|
|
|
use syntax::parse::token;
|
|
|
|
|
|
|
|
pub struct NamespaceTreeNode {
|
|
|
|
pub name: ast::Name,
|
|
|
|
pub scope: DIScope,
|
|
|
|
pub parent: Option<Weak<NamespaceTreeNode>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
2016-02-09 21:24:11 +01:00
|
|
|
Some(ref parent) => fill_nested(&parent.upgrade().unwrap(), output),
|
2015-04-24 16:00:47 +12:00
|
|
|
None => {}
|
|
|
|
}
|
2015-07-28 18:07:20 +02:00
|
|
|
let string = node.name.as_str();
|
|
|
|
output.push_str(&string.len().to_string());
|
2015-04-24 16:00:47 +12:00
|
|
|
output.push_str(&string);
|
|
|
|
}
|
|
|
|
|
2015-06-08 16:55:35 +02:00
|
|
|
let mut name = String::from("_ZN");
|
2015-04-24 16:00:47 +12:00
|
|
|
fill_nested(self, &mut name);
|
2015-07-28 18:07:20 +02:00
|
|
|
name.push_str(&item_name.len().to_string());
|
2015-04-24 16:00:47 +12:00
|
|
|
name.push_str(item_name);
|
|
|
|
name.push('E');
|
|
|
|
name
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-16 06:32:28 -04:00
|
|
|
pub fn namespace_for_item(cx: &CrateContext, def_id: DefId) -> Rc<NamespaceTreeNode> {
|
2016-04-06 13:51:55 +03:00
|
|
|
// prepend crate name.
|
|
|
|
// This shouldn't need a roundtrip through InternedString.
|
|
|
|
let krate = token::intern(&cx.tcx().crate_name(def_id.krate));
|
|
|
|
let krate = hir_map::DefPathData::TypeNs(krate);
|
|
|
|
let path = cx.tcx().def_path(def_id).data;
|
|
|
|
let mut path = once(krate).chain(path.into_iter().map(|e| e.data)).peekable();
|
|
|
|
|
|
|
|
let mut current_key = Vec::new();
|
|
|
|
let mut parent_node: Option<Rc<NamespaceTreeNode>> = 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
|
2015-04-24 16:00:47 +12:00
|
|
|
};
|
2016-04-06 13:51:55 +03:00
|
|
|
// Ignore the name of the item (the last path element).
|
|
|
|
if path.peek().is_none() {
|
|
|
|
break;
|
2015-04-24 16:00:47 +12:00
|
|
|
}
|
|
|
|
|
2016-04-06 13:51:55 +03:00
|
|
|
// This shouldn't need a roundtrip through InternedString.
|
|
|
|
let namespace_name = path_element.as_interned_str();
|
|
|
|
let name = token::intern(&namespace_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,
|
2015-04-24 16:00:47 +12:00
|
|
|
None => {
|
2016-04-06 13:51:55 +03:00
|
|
|
// create and insert
|
|
|
|
let parent_scope = match parent_node {
|
|
|
|
Some(ref node) => node.scope,
|
|
|
|
None => ptr::null_mut()
|
|
|
|
};
|
|
|
|
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| Rc::downgrade(&parent)),
|
|
|
|
});
|
|
|
|
|
|
|
|
debug_context(cx).namespace_map.borrow_mut()
|
|
|
|
.insert(current_key.clone(), node.clone());
|
|
|
|
|
|
|
|
node
|
2015-04-24 16:00:47 +12:00
|
|
|
}
|
2016-04-06 13:51:55 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
parent_node = Some(current_node);
|
|
|
|
}
|
|
|
|
|
|
|
|
match parent_node {
|
|
|
|
Some(node) => node,
|
|
|
|
None => {
|
|
|
|
bug!("debuginfo::namespace_for_item: path too short for {:?}", def_id);
|
2015-04-24 16:00:47 +12:00
|
|
|
}
|
2016-04-06 13:51:55 +03:00
|
|
|
}
|
2015-04-24 16:00:47 +12:00
|
|
|
}
|