trans: use DefKey directly in debuginfo for paths.
This commit is contained in:
parent
e945b2852e
commit
4e6b178649
6 changed files with 112 additions and 192 deletions
|
@ -1400,15 +1400,11 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
|
||||||
pub fn new(ccx: &'blk CrateContext<'blk, 'tcx>,
|
pub fn new(ccx: &'blk CrateContext<'blk, 'tcx>,
|
||||||
llfndecl: ValueRef,
|
llfndecl: ValueRef,
|
||||||
fn_ty: FnType,
|
fn_ty: FnType,
|
||||||
definition: Option<(Instance<'tcx>,
|
definition: Option<(Instance<'tcx>, &ty::FnSig<'tcx>, Abi)>,
|
||||||
&ty::FnSig<'tcx>,
|
|
||||||
Abi,
|
|
||||||
&ty::Generics<'tcx>,
|
|
||||||
Option<ast::Name>)>,
|
|
||||||
block_arena: &'blk TypedArena<common::BlockS<'blk, 'tcx>>)
|
block_arena: &'blk TypedArena<common::BlockS<'blk, 'tcx>>)
|
||||||
-> FunctionContext<'blk, 'tcx> {
|
-> FunctionContext<'blk, 'tcx> {
|
||||||
let (param_substs, def_id) = match definition {
|
let (param_substs, def_id) = match definition {
|
||||||
Some((instance, _, _, _, _)) => {
|
Some((instance, _, _)) => {
|
||||||
common::validate_substs(instance.substs);
|
common::validate_substs(instance.substs);
|
||||||
(instance.substs, Some(instance.def))
|
(instance.substs, Some(instance.def))
|
||||||
}
|
}
|
||||||
|
@ -1450,14 +1446,9 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
|
||||||
None
|
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 debug_context = if let (false, Some(definition)) = (no_debug, definition) {
|
||||||
let (instance, sig, abi, generics, name) = definition;
|
let (instance, sig, abi) = definition;
|
||||||
debuginfo::create_function_debug_context(ccx, instance, sig,
|
debuginfo::create_function_debug_context(ccx, instance, sig, abi, llfndecl)
|
||||||
abi, generics, name,
|
|
||||||
span.unwrap_or(DUMMY_SP),
|
|
||||||
llfndecl)
|
|
||||||
} else {
|
} else {
|
||||||
debuginfo::empty_function_debug_context(ccx)
|
debuginfo::empty_function_debug_context(ccx)
|
||||||
};
|
};
|
||||||
|
@ -1476,7 +1467,7 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
|
||||||
lldropflag_hints: RefCell::new(DropFlagHintsMap::new()),
|
lldropflag_hints: RefCell::new(DropFlagHintsMap::new()),
|
||||||
fn_ty: fn_ty,
|
fn_ty: fn_ty,
|
||||||
param_substs: param_substs,
|
param_substs: param_substs,
|
||||||
span: span,
|
span: inlined_id.and_then(|id| ccx.tcx().map.opt_span(id)),
|
||||||
block_arena: block_arena,
|
block_arena: block_arena,
|
||||||
lpad_arena: TypedArena::new(),
|
lpad_arena: TypedArena::new(),
|
||||||
ccx: ccx,
|
ccx: ccx,
|
||||||
|
@ -1831,8 +1822,6 @@ pub fn trans_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||||
inlined_id: ast::NodeId,
|
inlined_id: ast::NodeId,
|
||||||
sig: &ty::FnSig<'tcx>,
|
sig: &ty::FnSig<'tcx>,
|
||||||
abi: Abi,
|
abi: Abi,
|
||||||
generics: &ty::Generics<'tcx>,
|
|
||||||
name: Option<ast::Name>,
|
|
||||||
closure_env: closure::ClosureEnv) {
|
closure_env: closure::ClosureEnv) {
|
||||||
ccx.stats().n_closures.set(ccx.stats().n_closures.get() + 1);
|
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);
|
let (arena, fcx): (TypedArena<_>, FunctionContext);
|
||||||
arena = TypedArena::new();
|
arena = TypedArena::new();
|
||||||
fcx = FunctionContext::new(ccx, llfndecl, fn_ty,
|
fcx = FunctionContext::new(ccx, llfndecl, fn_ty, Some((instance, sig, abi)), &arena);
|
||||||
Some((instance, sig, abi, generics, name)), &arena);
|
|
||||||
|
|
||||||
if fcx.mir.is_some() {
|
if fcx.mir.is_some() {
|
||||||
return mir::trans_mir(&fcx);
|
return mir::trans_mir(&fcx);
|
||||||
|
@ -1931,8 +1919,7 @@ pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||||
} else {
|
} else {
|
||||||
ccx.tcx().map.local_def_id(id)
|
ccx.tcx().map.local_def_id(id)
|
||||||
};
|
};
|
||||||
let scheme = ccx.tcx().lookup_item_type(def_id);
|
let fn_ty = ccx.tcx().lookup_item_type(def_id).ty;
|
||||||
let fn_ty = scheme.ty;
|
|
||||||
let fn_ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &fn_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 = ccx.tcx().erase_late_bound_regions(fn_ty.fn_sig());
|
||||||
let sig = infer::normalize_associated_type(ccx.tcx(), &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,
|
id,
|
||||||
&sig,
|
&sig,
|
||||||
abi,
|
abi,
|
||||||
&scheme.generics,
|
|
||||||
Some(ccx.tcx().item_name(def_id)),
|
|
||||||
closure::ClosureEnv::NotClosure);
|
closure::ClosureEnv::NotClosure);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -235,10 +235,6 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
|
||||||
variadic: false
|
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,
|
trans_closure(ccx,
|
||||||
decl,
|
decl,
|
||||||
body,
|
body,
|
||||||
|
@ -247,8 +243,6 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
|
||||||
id,
|
id,
|
||||||
&sig,
|
&sig,
|
||||||
Abi::RustCall,
|
Abi::RustCall,
|
||||||
&generics,
|
|
||||||
None,
|
|
||||||
ClosureEnv::Closure(closure_def_id, id));
|
ClosureEnv::Closure(closure_def_id, id));
|
||||||
|
|
||||||
// Don't hoist this to the top of the function. It's perfectly legitimate
|
// Don't hoist this to the top of the function. It's perfectly legitimate
|
||||||
|
|
|
@ -16,7 +16,7 @@ use self::EnumDiscriminantInfo::*;
|
||||||
use super::utils::{debug_context, DIB, span_start, bytes_to_bits, size_and_align_of,
|
use super::utils::{debug_context, DIB, span_start, bytes_to_bits, size_and_align_of,
|
||||||
get_namespace_and_span_for_item, create_DIArray,
|
get_namespace_and_span_for_item, create_DIArray,
|
||||||
fn_should_be_ignored, is_node_local_to_unit};
|
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::type_names::{compute_debuginfo_type_name, push_debuginfo_type_name};
|
||||||
use super::{declare_local, VariableKind, VariableAccess};
|
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;
|
pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
|
||||||
|
|
||||||
// ptr::null() doesn't work :(
|
// ptr::null() doesn't work :(
|
||||||
const NO_FILE_METADATA: DIFile = (0 as DIFile);
|
pub const NO_FILE_METADATA: DIFile = (0 as DIFile);
|
||||||
const NO_SCOPE_METADATA: DIScope = (0 as DIScope);
|
pub const NO_SCOPE_METADATA: DIScope = (0 as DIScope);
|
||||||
|
|
||||||
const FLAGS_NONE: c_uint = 0;
|
const FLAGS_NONE: c_uint = 0;
|
||||||
|
|
||||||
|
@ -1846,28 +1846,8 @@ pub fn create_global_var_metadata(cx: &CrateContext,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let var_item = cx.tcx().map.get(node_id);
|
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 (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 (file_metadata, line_number) = if span != codemap::DUMMY_SP {
|
let (file_metadata, line_number) = if span != codemap::DUMMY_SP {
|
||||||
let loc = span_start(cx, span);
|
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 is_local_to_unit = is_node_local_to_unit(cx, node_id);
|
||||||
let variable_type = cx.tcx().node_id_to_type(node_id);
|
let variable_type = cx.tcx().node_id_to_type(node_id);
|
||||||
let type_metadata = type_metadata(cx, variable_type, span);
|
let type_metadata = type_metadata(cx, variable_type, span);
|
||||||
let node_def_id = cx.tcx().map.local_def_id(node_id);
|
let var_name = cx.tcx().item_name(node_def_id).to_string();
|
||||||
let namespace_node = namespace_for_item(cx, node_def_id);
|
let linkage_name = mangled_name_of_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 = CString::new(var_name).unwrap();
|
let var_name = CString::new(var_name).unwrap();
|
||||||
let linkage_name = CString::new(linkage_name).unwrap();
|
let linkage_name = CString::new(linkage_name).unwrap();
|
||||||
|
|
|
@ -14,8 +14,9 @@ mod doc;
|
||||||
use self::VariableAccess::*;
|
use self::VariableAccess::*;
|
||||||
use self::VariableKind::*;
|
use self::VariableKind::*;
|
||||||
|
|
||||||
use self::utils::{DIB, span_start, create_DIArray, is_node_local_to_unit};
|
use self::utils::{DIB, span_start, create_DIArray, is_node_local_to_unit,
|
||||||
use self::namespace::{namespace_for_item, NamespaceTreeNode};
|
get_namespace_and_span_for_item};
|
||||||
|
use self::namespace::mangled_name_of_item;
|
||||||
use self::type_names::compute_debuginfo_type_name;
|
use self::type_names::compute_debuginfo_type_name;
|
||||||
use self::metadata::{type_metadata, diverging_type_metadata};
|
use self::metadata::{type_metadata, diverging_type_metadata};
|
||||||
use self::metadata::{file_metadata, scope_metadata, TypeMap, compile_unit_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,
|
use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray,
|
||||||
FlagPrototyped};
|
FlagPrototyped};
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
|
use rustc::hir::map::DefPathData;
|
||||||
use rustc::ty::subst::Substs;
|
use rustc::ty::subst::Substs;
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
|
|
||||||
|
@ -34,18 +36,16 @@ use common::{NodeIdAndSpan, CrateContext, FunctionContext, Block};
|
||||||
use monomorphize::Instance;
|
use monomorphize::Instance;
|
||||||
use rustc::ty::{self, Ty};
|
use rustc::ty::{self, Ty};
|
||||||
use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
|
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 libc::c_uint;
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use syntax::codemap::{Span, Pos};
|
use syntax::codemap::{Span, Pos};
|
||||||
use syntax::{ast, codemap};
|
use syntax::{ast, codemap};
|
||||||
use syntax::attr::IntType;
|
use syntax::attr::IntType;
|
||||||
use syntax::parse::token;
|
|
||||||
|
|
||||||
pub mod gdb;
|
pub mod gdb;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
@ -80,7 +80,7 @@ pub struct CrateDebugContext<'tcx> {
|
||||||
created_enum_disr_types: RefCell<FnvHashMap<(DefId, IntType), DIType>>,
|
created_enum_disr_types: RefCell<FnvHashMap<(DefId, IntType), DIType>>,
|
||||||
|
|
||||||
type_map: RefCell<TypeMap<'tcx>>,
|
type_map: RefCell<TypeMap<'tcx>>,
|
||||||
namespace_map: RefCell<FnvHashMap<Vec<ast::Name>, Rc<NamespaceTreeNode>>>,
|
namespace_map: RefCell<DefIdMap<DIScope>>,
|
||||||
|
|
||||||
// This collection is used to assert that composite types (structs, enums,
|
// This collection is used to assert that composite types (structs, enums,
|
||||||
// ...) have their members only set once:
|
// ...) have their members only set once:
|
||||||
|
@ -100,7 +100,7 @@ impl<'tcx> CrateDebugContext<'tcx> {
|
||||||
created_files: RefCell::new(FnvHashMap()),
|
created_files: RefCell::new(FnvHashMap()),
|
||||||
created_enum_disr_types: RefCell::new(FnvHashMap()),
|
created_enum_disr_types: RefCell::new(FnvHashMap()),
|
||||||
type_map: RefCell::new(TypeMap::new()),
|
type_map: RefCell::new(TypeMap::new()),
|
||||||
namespace_map: RefCell::new(FnvHashMap()),
|
namespace_map: RefCell::new(DefIdMap()),
|
||||||
composite_types_completed: RefCell::new(FnvHashSet()),
|
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>,
|
instance: Instance<'tcx>,
|
||||||
sig: &ty::FnSig<'tcx>,
|
sig: &ty::FnSig<'tcx>,
|
||||||
abi: Abi,
|
abi: Abi,
|
||||||
generics: &ty::Generics<'tcx>,
|
|
||||||
name: Option<ast::Name>,
|
|
||||||
span: Span,
|
|
||||||
llfn: ValueRef) -> FunctionDebugContext {
|
llfn: ValueRef) -> FunctionDebugContext {
|
||||||
if cx.sess().opts.debuginfo == NoDebugInfo {
|
if cx.sess().opts.debuginfo == NoDebugInfo {
|
||||||
return FunctionDebugContext::DebugInfoDisabled;
|
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);
|
source_loc::set_debug_location(cx, InternalDebugLocation::UnknownLocation);
|
||||||
|
|
||||||
// This can be the case for functions inlined from another crate
|
// 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 {
|
if span == codemap::DUMMY_SP {
|
||||||
return FunctionDebugContext::FunctionWithoutDebugInfo;
|
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)
|
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
|
// Get_template_parameters() will append a `<...>` clause to the function
|
||||||
// name if necessary.
|
// name if necessary.
|
||||||
let mut function_name = name.map(|name| name.to_string()).unwrap_or_else(|| {
|
let generics = cx.tcx().lookup_item_type(fn_def_id).generics;
|
||||||
// We do this only for closures atm.
|
|
||||||
format!("fn{}", token::gensym("fn"))
|
|
||||||
});
|
|
||||||
let template_parameters = get_template_parameters(cx,
|
let template_parameters = get_template_parameters(cx,
|
||||||
generics,
|
&generics,
|
||||||
instance.substs,
|
instance.substs,
|
||||||
file_metadata,
|
file_metadata,
|
||||||
&mut function_name);
|
&mut name);
|
||||||
|
|
||||||
// There is no hir_map::Path for hir::ExprClosure-type functions. For now,
|
// Build the linkage_name out of the item path and "template" parameters.
|
||||||
// just don't put them into a namespace. In the future this could be improved
|
let linkage_name = mangled_name_of_item(cx, instance.def, &name[name_len..]);
|
||||||
// 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)
|
|
||||||
};
|
|
||||||
|
|
||||||
let scope_line = span_start(cx, span).line;
|
let scope_line = span_start(cx, span).line;
|
||||||
|
|
||||||
let local_id = cx.tcx().map.as_local_node_id(instance.def);
|
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 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 linkage_name = CString::new(linkage_name).unwrap();
|
||||||
let fn_metadata = unsafe {
|
let fn_metadata = unsafe {
|
||||||
llvm::LLVMDIBuilderCreateFunction(
|
llvm::LLVMDIBuilderCreateFunction(
|
||||||
|
|
|
@ -10,118 +10,82 @@
|
||||||
|
|
||||||
// Namespace Handling.
|
// 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;
|
||||||
use llvm::debuginfo::DIScope;
|
use llvm::debuginfo::DIScope;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::hir::map as hir_map;
|
use rustc::hir::map::DefPathData;
|
||||||
use common::CrateContext;
|
use common::CrateContext;
|
||||||
|
|
||||||
|
use libc::c_uint;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::iter::once;
|
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::rc::{Rc, Weak};
|
use syntax::codemap::DUMMY_SP;
|
||||||
use syntax::ast;
|
|
||||||
use syntax::parse::token;
|
|
||||||
|
|
||||||
pub struct NamespaceTreeNode {
|
pub fn mangled_name_of_item(ccx: &CrateContext, def_id: DefId, extra: &str) -> String {
|
||||||
pub name: ast::Name,
|
fn fill_nested(ccx: &CrateContext, def_id: DefId, extra: &str, output: &mut String) {
|
||||||
pub scope: DIScope,
|
let def_key = ccx.tcx().def_key(def_id);
|
||||||
pub parent: Option<Weak<NamespaceTreeNode>>,
|
if let Some(parent) = def_key.parent {
|
||||||
}
|
fill_nested(ccx, DefId {
|
||||||
|
krate: def_id.krate,
|
||||||
impl NamespaceTreeNode {
|
index: parent
|
||||||
pub fn mangled_name_of_contained_item(&self, item_name: &str) -> String {
|
}, "", output);
|
||||||
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");
|
let name = match def_key.disambiguated_data.data {
|
||||||
fill_nested(self, &mut name);
|
DefPathData::CrateRoot => ccx.tcx().crate_name(def_id.krate),
|
||||||
name.push_str(&item_name.len().to_string());
|
data => data.as_interned_str()
|
||||||
name.push_str(item_name);
|
|
||||||
name.push('E');
|
|
||||||
name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn namespace_for_item(cx: &CrateContext, def_id: DefId) -> Rc<NamespaceTreeNode> {
|
|
||||||
// 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
|
|
||||||
};
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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 {
|
let mut name = String::from("_ZN");
|
||||||
Some(node) => node,
|
fill_nested(ccx, def_id, extra, &mut name);
|
||||||
None => {
|
name.push('E');
|
||||||
bug!("debuginfo::namespace_for_item: path too short for {:?}", def_id);
|
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
// Utility Functions.
|
// Utility Functions.
|
||||||
|
|
||||||
use super::{FunctionDebugContext, CrateDebugContext};
|
use super::{FunctionDebugContext, CrateDebugContext};
|
||||||
use super::namespace::namespace_for_item;
|
use super::namespace::item_namespace;
|
||||||
|
|
||||||
use rustc::hir::def_id::DefId;
|
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)
|
pub fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: DefId)
|
||||||
-> (DIScope, Span) {
|
-> (DIScope, Span) {
|
||||||
let containing_scope = namespace_for_item(cx, def_id).scope;
|
let containing_scope = item_namespace(cx, DefId {
|
||||||
let definition_span = cx.tcx().map.def_id_span(def_id, codemap::DUMMY_SP /* (1) */ );
|
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)
|
(containing_scope, definition_span)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue