/src/librustc_trans/trans/debuginfo/namespace.rs
https://gitlab.com/0072016/0072016-rusty · Rust · 135 lines · 100 code · 18 blank · 17 comment · 8 complexity · 2889dff1ca9a00521f9f975d1eea858b MD5 · raw file
- // 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 rustc::middle::def_id::DefId;
- use rustc::front::map as hir_map;
- use trans::common::CrateContext;
- use std::ffi::CString;
- use std::ptr;
- use std::rc::{Rc, Weak};
- use syntax::ast;
- 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 = node.name.as_str();
- output.push_str(&string.len().to_string());
- output.push_str(&string);
- }
- let mut name = String::from("_ZN");
- fill_nested(self, &mut name);
- name.push_str(&item_name.len().to_string());
- 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: DefId) -> Rc<NamespaceTreeNode> {
- cx.tcx().with_path(def_id, |path| {
- // prepend crate name if not already present
- let krate = if def_id.is_local() {
- let crate_namespace_name = token::intern(crate_root_namespace(cx));
- Some(hir_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 = name.as_str();
- 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
- }
- };
- 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));
- }
- }
- })
- }