From 4e6b178649b30b060cce043862dbaeedd361f2c7 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Wed, 6 Apr 2016 15:37:19 +0300 Subject: [PATCH] trans: use DefKey directly in debuginfo for paths. --- src/librustc_trans/base.rs | 29 +--- src/librustc_trans/closure.rs | 6 - src/librustc_trans/debuginfo/metadata.rs | 38 +---- src/librustc_trans/debuginfo/mod.rs | 54 ++++---- src/librustc_trans/debuginfo/namespace.rs | 162 +++++++++------------- src/librustc_trans/debuginfo/utils.rs | 15 +- 6 files changed, 112 insertions(+), 192 deletions(-) diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index f504a720cb5..956e1a5ce96 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -1400,15 +1400,11 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> { pub fn new(ccx: &'blk CrateContext<'blk, 'tcx>, llfndecl: ValueRef, fn_ty: FnType, - definition: Option<(Instance<'tcx>, - &ty::FnSig<'tcx>, - Abi, - &ty::Generics<'tcx>, - Option)>, + definition: Option<(Instance<'tcx>, &ty::FnSig<'tcx>, Abi)>, block_arena: &'blk TypedArena>) -> FunctionContext<'blk, 'tcx> { let (param_substs, def_id) = match definition { - Some((instance, _, _, _, _)) => { + Some((instance, _, _)) => { common::validate_substs(instance.substs); (instance.substs, Some(instance.def)) } @@ -1450,14 +1446,9 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> { None }; - let span = inlined_id.and_then(|id| ccx.tcx().map.opt_span(id)); - let debug_context = if let (false, Some(definition)) = (no_debug, definition) { - let (instance, sig, abi, generics, name) = definition; - debuginfo::create_function_debug_context(ccx, instance, sig, - abi, generics, name, - span.unwrap_or(DUMMY_SP), - llfndecl) + let (instance, sig, abi) = definition; + debuginfo::create_function_debug_context(ccx, instance, sig, abi, llfndecl) } else { debuginfo::empty_function_debug_context(ccx) }; @@ -1476,7 +1467,7 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> { lldropflag_hints: RefCell::new(DropFlagHintsMap::new()), fn_ty: fn_ty, param_substs: param_substs, - span: span, + span: inlined_id.and_then(|id| ccx.tcx().map.opt_span(id)), block_arena: block_arena, lpad_arena: TypedArena::new(), ccx: ccx, @@ -1831,8 +1822,6 @@ pub fn trans_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, inlined_id: ast::NodeId, sig: &ty::FnSig<'tcx>, abi: Abi, - generics: &ty::Generics<'tcx>, - name: Option, closure_env: closure::ClosureEnv) { ccx.stats().n_closures.set(ccx.stats().n_closures.get() + 1); @@ -1849,8 +1838,7 @@ pub fn trans_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, let (arena, fcx): (TypedArena<_>, FunctionContext); arena = TypedArena::new(); - fcx = FunctionContext::new(ccx, llfndecl, fn_ty, - Some((instance, sig, abi, generics, name)), &arena); + fcx = FunctionContext::new(ccx, llfndecl, fn_ty, Some((instance, sig, abi)), &arena); if fcx.mir.is_some() { return mir::trans_mir(&fcx); @@ -1931,8 +1919,7 @@ pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, } else { ccx.tcx().map.local_def_id(id) }; - let scheme = ccx.tcx().lookup_item_type(def_id); - let fn_ty = scheme.ty; + let fn_ty = ccx.tcx().lookup_item_type(def_id).ty; let fn_ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &fn_ty); let sig = ccx.tcx().erase_late_bound_regions(fn_ty.fn_sig()); let sig = infer::normalize_associated_type(ccx.tcx(), &sig); @@ -1945,8 +1932,6 @@ pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, id, &sig, abi, - &scheme.generics, - Some(ccx.tcx().item_name(def_id)), closure::ClosureEnv::NotClosure); } diff --git a/src/librustc_trans/closure.rs b/src/librustc_trans/closure.rs index 209f4b39319..c2031638044 100644 --- a/src/librustc_trans/closure.rs +++ b/src/librustc_trans/closure.rs @@ -235,10 +235,6 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>, variadic: false }; - // This is not quite right. It should actually inherit - // the generics of the enclosing function. - let generics = ty::Generics::empty(); - trans_closure(ccx, decl, body, @@ -247,8 +243,6 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>, id, &sig, Abi::RustCall, - &generics, - None, ClosureEnv::Closure(closure_def_id, id)); // Don't hoist this to the top of the function. It's perfectly legitimate diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 8471b6a274c..de403732269 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -16,7 +16,7 @@ use self::EnumDiscriminantInfo::*; use super::utils::{debug_context, DIB, span_start, bytes_to_bits, size_and_align_of, get_namespace_and_span_for_item, create_DIArray, fn_should_be_ignored, is_node_local_to_unit}; -use super::namespace::namespace_for_item; +use super::namespace::mangled_name_of_item; use super::type_names::{compute_debuginfo_type_name, push_debuginfo_type_name}; use super::{declare_local, VariableKind, VariableAccess}; @@ -68,8 +68,8 @@ pub const UNKNOWN_LINE_NUMBER: c_uint = 0; pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0; // ptr::null() doesn't work :( -const NO_FILE_METADATA: DIFile = (0 as DIFile); -const NO_SCOPE_METADATA: DIScope = (0 as DIScope); +pub const NO_FILE_METADATA: DIFile = (0 as DIFile); +pub const NO_SCOPE_METADATA: DIScope = (0 as DIScope); const FLAGS_NONE: c_uint = 0; @@ -1846,28 +1846,8 @@ pub fn create_global_var_metadata(cx: &CrateContext, return; } - let var_item = cx.tcx().map.get(node_id); - - let (name, span) = match var_item { - hir_map::NodeItem(item) => { - match item.node { - hir::ItemStatic(..) => (item.name, item.span), - hir::ItemConst(..) => (item.name, item.span), - _ => { - span_bug!(item.span, - "debuginfo::\ - create_global_var_metadata() - - Captured var-id refers to \ - unexpected ast_item variant: {:?}", - var_item) - } - } - }, - _ => bug!("debuginfo::create_global_var_metadata() \ - - Captured var-id refers to unexpected \ - hir_map variant: {:?}", - var_item) - }; + let node_def_id = cx.tcx().map.local_def_id(node_id); + let (var_scope, span) = get_namespace_and_span_for_item(cx, node_def_id); let (file_metadata, line_number) = if span != codemap::DUMMY_SP { let loc = span_start(cx, span); @@ -1879,12 +1859,8 @@ pub fn create_global_var_metadata(cx: &CrateContext, let is_local_to_unit = is_node_local_to_unit(cx, node_id); let variable_type = cx.tcx().node_id_to_type(node_id); let type_metadata = type_metadata(cx, variable_type, span); - let node_def_id = cx.tcx().map.local_def_id(node_id); - let namespace_node = namespace_for_item(cx, node_def_id); - let var_name = name.to_string(); - let linkage_name = - namespace_node.mangled_name_of_contained_item(&var_name[..]); - let var_scope = namespace_node.scope; + let var_name = cx.tcx().item_name(node_def_id).to_string(); + let linkage_name = mangled_name_of_item(cx, node_def_id, ""); let var_name = CString::new(var_name).unwrap(); let linkage_name = CString::new(linkage_name).unwrap(); diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index cf7d98f2f01..2ecd6c5ebf7 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -14,8 +14,9 @@ mod doc; use self::VariableAccess::*; use self::VariableKind::*; -use self::utils::{DIB, span_start, create_DIArray, is_node_local_to_unit}; -use self::namespace::{namespace_for_item, NamespaceTreeNode}; +use self::utils::{DIB, span_start, create_DIArray, is_node_local_to_unit, + get_namespace_and_span_for_item}; +use self::namespace::mangled_name_of_item; use self::type_names::compute_debuginfo_type_name; use self::metadata::{type_metadata, diverging_type_metadata}; use self::metadata::{file_metadata, scope_metadata, TypeMap, compile_unit_metadata}; @@ -26,6 +27,7 @@ use llvm::{ModuleRef, ContextRef, ValueRef}; use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray, FlagPrototyped}; use rustc::hir::def_id::DefId; +use rustc::hir::map::DefPathData; use rustc::ty::subst::Substs; use rustc::hir; @@ -34,18 +36,16 @@ use common::{NodeIdAndSpan, CrateContext, FunctionContext, Block}; use monomorphize::Instance; use rustc::ty::{self, Ty}; use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo}; -use util::nodemap::{NodeMap, FnvHashMap, FnvHashSet}; +use util::nodemap::{DefIdMap, NodeMap, FnvHashMap, FnvHashSet}; use libc::c_uint; use std::cell::{Cell, RefCell}; use std::ffi::CString; use std::ptr; -use std::rc::Rc; use syntax::codemap::{Span, Pos}; use syntax::{ast, codemap}; use syntax::attr::IntType; -use syntax::parse::token; pub mod gdb; mod utils; @@ -80,7 +80,7 @@ pub struct CrateDebugContext<'tcx> { created_enum_disr_types: RefCell>, type_map: RefCell>, - namespace_map: RefCell, Rc>>, + namespace_map: RefCell>, // This collection is used to assert that composite types (structs, enums, // ...) have their members only set once: @@ -100,7 +100,7 @@ impl<'tcx> CrateDebugContext<'tcx> { created_files: RefCell::new(FnvHashMap()), created_enum_disr_types: RefCell::new(FnvHashMap()), type_map: RefCell::new(TypeMap::new()), - namespace_map: RefCell::new(FnvHashMap()), + namespace_map: RefCell::new(DefIdMap()), composite_types_completed: RefCell::new(FnvHashSet()), }; } @@ -232,9 +232,6 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, instance: Instance<'tcx>, sig: &ty::FnSig<'tcx>, abi: Abi, - generics: &ty::Generics<'tcx>, - name: Option, - span: Span, llfn: ValueRef) -> FunctionDebugContext { if cx.sess().opts.debuginfo == NoDebugInfo { return FunctionDebugContext::DebugInfoDisabled; @@ -245,6 +242,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, source_loc::set_debug_location(cx, InternalDebugLocation::UnknownLocation); // This can be the case for functions inlined from another crate + let (containing_scope, span) = get_namespace_and_span_for_item(cx, instance.def); if span == codemap::DUMMY_SP { return FunctionDebugContext::FunctionWithoutDebugInfo; } @@ -257,38 +255,34 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature) }; + // Find the enclosing function, in case this is a closure. + let mut fn_def_id = instance.def; + let mut def_key = cx.tcx().def_key(fn_def_id); + let mut name = def_key.disambiguated_data.data.to_string(); + let name_len = name.len(); + while def_key.disambiguated_data.data == DefPathData::ClosureExpr { + fn_def_id.index = def_key.parent.expect("closure without a parent?"); + def_key = cx.tcx().def_key(fn_def_id); + } + // Get_template_parameters() will append a `<...>` clause to the function // name if necessary. - let mut function_name = name.map(|name| name.to_string()).unwrap_or_else(|| { - // We do this only for closures atm. - format!("fn{}", token::gensym("fn")) - }); + let generics = cx.tcx().lookup_item_type(fn_def_id).generics; let template_parameters = get_template_parameters(cx, - generics, + &generics, instance.substs, file_metadata, - &mut function_name); + &mut name); - // There is no hir_map::Path for hir::ExprClosure-type functions. For now, - // just don't put them into a namespace. In the future this could be improved - // somehow (storing a path in the hir_map, or construct a path using the - // enclosing function). - let (linkage_name, containing_scope) = if name.is_some() { - let namespace_node = namespace_for_item(cx, instance.def); - let linkage_name = namespace_node.mangled_name_of_contained_item( - &function_name[..]); - let containing_scope = namespace_node.scope; - (linkage_name, containing_scope) - } else { - (function_name.clone(), file_metadata) - }; + // Build the linkage_name out of the item path and "template" parameters. + let linkage_name = mangled_name_of_item(cx, instance.def, &name[name_len..]); let scope_line = span_start(cx, span).line; let local_id = cx.tcx().map.as_local_node_id(instance.def); let is_local_to_unit = local_id.map_or(false, |id| is_node_local_to_unit(cx, id)); - let function_name = CString::new(function_name).unwrap(); + let function_name = CString::new(name).unwrap(); let linkage_name = CString::new(linkage_name).unwrap(); let fn_metadata = unsafe { llvm::LLVMDIBuilderCreateFunction( diff --git a/src/librustc_trans/debuginfo/namespace.rs b/src/librustc_trans/debuginfo/namespace.rs index 5272a4fbbb7..fc31eaa4e74 100644 --- a/src/librustc_trans/debuginfo/namespace.rs +++ b/src/librustc_trans/debuginfo/namespace.rs @@ -10,118 +10,82 @@ // Namespace Handling. -use super::utils::{DIB, debug_context}; +use super::metadata::{file_metadata, NO_FILE_METADATA, UNKNOWN_LINE_NUMBER}; +use super::utils::{DIB, debug_context, span_start}; use llvm; use llvm::debuginfo::DIScope; use rustc::hir::def_id::DefId; -use rustc::hir::map as hir_map; +use rustc::hir::map::DefPathData; use common::CrateContext; +use libc::c_uint; use std::ffi::CString; -use std::iter::once; use std::ptr; -use std::rc::{Rc, Weak}; -use syntax::ast; -use syntax::parse::token; +use syntax::codemap::DUMMY_SP; -pub struct NamespaceTreeNode { - pub name: ast::Name, - pub scope: DIScope, - pub parent: Option>, -} - -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); +pub fn mangled_name_of_item(ccx: &CrateContext, def_id: DefId, extra: &str) -> String { + fn fill_nested(ccx: &CrateContext, def_id: DefId, extra: &str, output: &mut String) { + let def_key = ccx.tcx().def_key(def_id); + if let Some(parent) = def_key.parent { + fill_nested(ccx, DefId { + krate: def_id.krate, + index: parent + }, "", output); } - 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 namespace_for_item(cx: &CrateContext, def_id: DefId) -> Rc { - // 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> = 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; - } - - // 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, - None => { - // 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 - } + let name = match def_key.disambiguated_data.data { + DefPathData::CrateRoot => ccx.tcx().crate_name(def_id.krate), + data => data.as_interned_str() }; - parent_node = Some(current_node); + output.push_str(&(name.len() + extra.len()).to_string()); + output.push_str(&name); + output.push_str(extra); } - match parent_node { - Some(node) => node, - None => { - bug!("debuginfo::namespace_for_item: path too short for {:?}", def_id); - } - } + let mut name = String::from("_ZN"); + fill_nested(ccx, def_id, extra, &mut name); + name.push('E'); + name +} + +pub fn item_namespace(ccx: &CrateContext, def_id: DefId) -> DIScope { + if let Some(&scope) = debug_context(ccx).namespace_map.borrow().get(&def_id) { + return scope; + } + + let def_key = ccx.tcx().def_key(def_id); + let parent_scope = def_key.parent.map_or(ptr::null_mut(), |parent| { + item_namespace(ccx, DefId { + krate: def_id.krate, + index: parent + }) + }); + + let namespace_name = match def_key.disambiguated_data.data { + DefPathData::CrateRoot => ccx.tcx().crate_name(def_id.krate), + data => data.as_interned_str() + }; + + let namespace_name = CString::new(namespace_name.as_bytes()).unwrap(); + let span = ccx.tcx().map.def_id_span(def_id, DUMMY_SP); + let (file, line) = if span != DUMMY_SP { + let loc = span_start(ccx, span); + (file_metadata(ccx, &loc.file.name), loc.line as c_uint) + } else { + (NO_FILE_METADATA, UNKNOWN_LINE_NUMBER) + }; + + let scope = unsafe { + llvm::LLVMDIBuilderCreateNameSpace( + DIB(ccx), + parent_scope, + namespace_name.as_ptr(), + file, + line as c_uint) + }; + + debug_context(ccx).namespace_map.borrow_mut().insert(def_id, scope); + scope } diff --git a/src/librustc_trans/debuginfo/utils.rs b/src/librustc_trans/debuginfo/utils.rs index 805cb67986c..3fd97937184 100644 --- a/src/librustc_trans/debuginfo/utils.rs +++ b/src/librustc_trans/debuginfo/utils.rs @@ -11,7 +11,7 @@ // Utility Functions. use super::{FunctionDebugContext, CrateDebugContext}; -use super::namespace::namespace_for_item; +use super::namespace::item_namespace; use rustc::hir::def_id::DefId; @@ -79,10 +79,17 @@ pub fn fn_should_be_ignored(fcx: &FunctionContext) -> bool { pub fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: DefId) -> (DIScope, Span) { - let containing_scope = namespace_for_item(cx, def_id).scope; - let definition_span = cx.tcx().map.def_id_span(def_id, codemap::DUMMY_SP /* (1) */ ); + let containing_scope = item_namespace(cx, DefId { + krate: def_id.krate, + index: cx.tcx().def_key(def_id).parent + .expect("get_namespace_and_span_for_item: missing parent?") + }); - // (1) For external items there is no span information + // Try to get some span information, if we have an inlined item. + let definition_span = match cx.external().borrow().get(&def_id) { + Some(&Some(node_id)) => cx.tcx().map.span(node_id), + _ => cx.tcx().map.def_id_span(def_id, codemap::DUMMY_SP) + }; (containing_scope, definition_span) }