debuginfo: extract namespace.rs
This commit is contained in:
parent
5b53de1775
commit
488694cf0d
3 changed files with 139 additions and 117 deletions
|
|
@ -14,11 +14,13 @@ mod doc;
|
|||
pub mod gdb;
|
||||
mod utils;
|
||||
mod create;
|
||||
mod namespace;
|
||||
|
||||
use self::utils::{debug_context, DIB, span_start, bytes_to_bits, size_and_align_of,
|
||||
assert_type_for_node_id, get_namespace_and_span_for_item, fn_should_be_ignored,
|
||||
contains_nodebug_attribute, create_scope_map};
|
||||
use self::create::{declare_local, create_DIArray, is_node_local_to_unit};
|
||||
use self::namespace::{namespace_for_item, NamespaceTreeNode, crate_root_namespace};
|
||||
|
||||
use self::VariableAccess::*;
|
||||
use self::VariableKind::*;
|
||||
|
|
@ -51,7 +53,7 @@ use std::cell::{Cell, RefCell};
|
|||
use std::ffi::CString;
|
||||
use std::path::Path;
|
||||
use std::ptr;
|
||||
use std::rc::{Rc, Weak};
|
||||
use std::rc::Rc;
|
||||
use syntax::util::interner::Interner;
|
||||
use syntax::codemap::{Span, Pos};
|
||||
use syntax::{ast, codemap, ast_util, ast_map};
|
||||
|
|
@ -3103,118 +3105,3 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
output.push('>');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=-----------------------------------------------------------------------------
|
||||
// Namespace Handling
|
||||
//=-----------------------------------------------------------------------------
|
||||
|
||||
struct NamespaceTreeNode {
|
||||
name: ast::Name,
|
||||
scope: DIScope,
|
||||
parent: Option<Weak<NamespaceTreeNode>>,
|
||||
}
|
||||
|
||||
impl NamespaceTreeNode {
|
||||
fn mangled_name_of_contained_item(&self, item_name: &str) -> String {
|
||||
fn fill_nested(node: &NamespaceTreeNode, output: &mut String) {
|
||||
match node.parent {
|
||||
Some(ref parent) => fill_nested(&*parent.upgrade().unwrap(), output),
|
||||
None => {}
|
||||
}
|
||||
let string = token::get_name(node.name);
|
||||
output.push_str(&format!("{}", string.len()));
|
||||
output.push_str(&string);
|
||||
}
|
||||
|
||||
let mut name = String::from_str("_ZN");
|
||||
fill_nested(self, &mut name);
|
||||
name.push_str(&format!("{}", item_name.len()));
|
||||
name.push_str(item_name);
|
||||
name.push('E');
|
||||
name
|
||||
}
|
||||
}
|
||||
|
||||
fn crate_root_namespace<'a>(cx: &'a CrateContext) -> &'a str {
|
||||
&cx.link_meta().crate_name
|
||||
}
|
||||
|
||||
fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTreeNode> {
|
||||
ty::with_path(cx.tcx(), def_id, |path| {
|
||||
// prepend crate name if not already present
|
||||
let krate = if def_id.krate == ast::LOCAL_CRATE {
|
||||
let crate_namespace_name = token::intern(crate_root_namespace(cx));
|
||||
Some(ast_map::PathMod(crate_namespace_name))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let mut path = krate.into_iter().chain(path).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
|
||||
};
|
||||
// Ignore the name of the item (the last path element).
|
||||
if path.peek().is_none() {
|
||||
break;
|
||||
}
|
||||
|
||||
let name = path_element.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,
|
||||
None => {
|
||||
// create and insert
|
||||
let parent_scope = match parent_node {
|
||||
Some(ref node) => node.scope,
|
||||
None => ptr::null_mut()
|
||||
};
|
||||
let namespace_name = token::get_name(name);
|
||||
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| parent.downgrade()),
|
||||
});
|
||||
|
||||
debug_context(cx).namespace_map.borrow_mut()
|
||||
.insert(current_key.clone(), node.clone());
|
||||
|
||||
node
|
||||
}
|
||||
};
|
||||
|
||||
parent_node = Some(current_node);
|
||||
}
|
||||
|
||||
match parent_node {
|
||||
Some(node) => node,
|
||||
None => {
|
||||
cx.sess().bug(&format!("debuginfo::namespace_for_item(): \
|
||||
path too short for {:?}",
|
||||
def_id));
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
134
src/librustc_trans/trans/debuginfo/namespace.rs
Normal file
134
src/librustc_trans/trans/debuginfo/namespace.rs
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://!rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://!www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://!opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Namespace Handling
|
||||
|
||||
use super::utils::{DIB, debug_context};
|
||||
|
||||
use llvm;
|
||||
use llvm::debuginfo::DIScope;
|
||||
use trans::common::CrateContext;
|
||||
use middle::ty::{self, ClosureTyper};
|
||||
|
||||
use std::ffi::CString;
|
||||
use std::ptr;
|
||||
use std::rc::{Rc, Weak};
|
||||
use syntax::{ast, ast_map};
|
||||
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 {
|
||||
Some(ref parent) => fill_nested(&*parent.upgrade().unwrap(), output),
|
||||
None => {}
|
||||
}
|
||||
let string = token::get_name(node.name);
|
||||
output.push_str(&format!("{}", string.len()));
|
||||
output.push_str(&string);
|
||||
}
|
||||
|
||||
let mut name = String::from_str("_ZN");
|
||||
fill_nested(self, &mut name);
|
||||
name.push_str(&format!("{}", item_name.len()));
|
||||
name.push_str(item_name);
|
||||
name.push('E');
|
||||
name
|
||||
}
|
||||
}
|
||||
|
||||
pub fn crate_root_namespace<'a>(cx: &'a CrateContext) -> &'a str {
|
||||
&cx.link_meta().crate_name
|
||||
}
|
||||
|
||||
pub fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTreeNode> {
|
||||
ty::with_path(cx.tcx(), def_id, |path| {
|
||||
// prepend crate name if not already present
|
||||
let krate = if def_id.krate == ast::LOCAL_CRATE {
|
||||
let crate_namespace_name = token::intern(crate_root_namespace(cx));
|
||||
Some(ast_map::PathMod(crate_namespace_name))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let mut path = krate.into_iter().chain(path).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
|
||||
};
|
||||
// Ignore the name of the item (the last path element).
|
||||
if path.peek().is_none() {
|
||||
break;
|
||||
}
|
||||
|
||||
let name = path_element.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,
|
||||
None => {
|
||||
// create and insert
|
||||
let parent_scope = match parent_node {
|
||||
Some(ref node) => node.scope,
|
||||
None => ptr::null_mut()
|
||||
};
|
||||
let namespace_name = token::get_name(name);
|
||||
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| parent.downgrade()),
|
||||
});
|
||||
|
||||
debug_context(cx).namespace_map.borrow_mut()
|
||||
.insert(current_key.clone(), node.clone());
|
||||
|
||||
node
|
||||
}
|
||||
};
|
||||
|
||||
parent_node = Some(current_node);
|
||||
}
|
||||
|
||||
match parent_node {
|
||||
Some(node) => node,
|
||||
None => {
|
||||
cx.sess().bug(&format!("debuginfo::namespace_for_item(): \
|
||||
path too short for {:?}",
|
||||
def_id));
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -10,7 +10,8 @@
|
|||
|
||||
// Utility Functions.
|
||||
|
||||
use super::{FunctionDebugContext, CrateDebugContext, namespace_for_item, file_metadata};
|
||||
use super::{FunctionDebugContext, CrateDebugContext, file_metadata};
|
||||
use super::namespace::namespace_for_item;
|
||||
|
||||
use llvm;
|
||||
use llvm::debuginfo::{DIScope, DISubprogram, DIBuilderRef};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue