/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

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