use rustc::hir::def_id::DefId;
use rustc::hir::map::DefPathData;
use rustc::ty::subst::Substs;
-use rustc::hir;
use abi::Abi;
-use common::{NodeIdAndSpan, CrateContext, FunctionContext, Block, BlockAndBuilder};
-use inline;
+use common::{CrateContext, FunctionContext, Block, BlockAndBuilder};
use monomorphize::{self, Instance};
use rustc::ty::{self, Ty};
+use rustc::mir::repr as mir;
use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
-use util::nodemap::{DefIdMap, NodeMap, FnvHashMap, FnvHashSet};
+use util::nodemap::{DefIdMap, FnvHashMap, FnvHashSet};
use libc::c_uint;
use std::cell::{Cell, RefCell};
use syntax_pos::{self, Span, Pos};
use syntax::ast;
-use syntax::attr::IntType;
+use rustc::ty::layout;
pub mod gdb;
mod utils;
mod create_scope_map;
mod source_loc;
-pub use self::create_scope_map::create_mir_scopes;
+pub use self::create_scope_map::{create_mir_scopes, MirDebugScope};
pub use self::source_loc::start_emitting_source_locations;
-pub use self::source_loc::get_cleanup_debug_loc_for_ast_node;
-pub use self::source_loc::with_source_location_override;
-pub use self::metadata::create_match_binding_metadata;
-pub use self::metadata::create_argument_metadata;
-pub use self::metadata::create_captured_var_metadata;
pub use self::metadata::create_global_var_metadata;
-pub use self::metadata::create_local_var_metadata;
+pub use self::metadata::extend_scope_to_file;
#[allow(non_upper_case_globals)]
const DW_TAG_auto_variable: c_uint = 0x100;
builder: DIBuilderRef,
current_debug_location: Cell<InternalDebugLocation>,
created_files: RefCell<FnvHashMap<String, DIFile>>,
- created_enum_disr_types: RefCell<FnvHashMap<(DefId, IntType), DIType>>,
+ created_enum_disr_types: RefCell<FnvHashMap<(DefId, layout::Integer), DIType>>,
type_map: RefCell<TypeMap<'tcx>>,
namespace_map: RefCell<DefIdMap<DIScope>>,
}
pub struct FunctionDebugContextData {
- scope_map: RefCell<NodeMap<DIScope>>,
fn_metadata: DISubprogram,
- argument_counter: Cell<usize>,
source_locations_enabled: Cell<bool>,
source_location_override: Cell<bool>,
}
instance: Instance<'tcx>,
sig: &ty::FnSig<'tcx>,
abi: Abi,
- llfn: ValueRef) -> FunctionDebugContext {
+ llfn: ValueRef,
+ mir: &mir::Mir) -> FunctionDebugContext {
if cx.sess().opts.debuginfo == NoDebugInfo {
return FunctionDebugContext::DebugInfoDisabled;
}
// Do this here already, in case we do an early exit from this function.
source_loc::set_debug_location(cx, None, UnknownLocation);
- let instance = inline::maybe_inline_instance(cx, instance);
- let (containing_scope, span) = get_containing_scope_and_span(cx, instance);
+ let containing_scope = get_containing_scope(cx, instance);
+ let span = mir.span;
// This can be the case for functions inlined from another crate
if span == syntax_pos::DUMMY_SP {
// Get_template_parameters() will append a `<...>` clause to the function
// name if necessary.
- let generics = cx.tcx().lookup_item_type(fn_def_id).generics;
+ let generics = cx.tcx().lookup_generics(fn_def_id);
let template_parameters = get_template_parameters(cx,
&generics,
instance.substs,
// Initialize fn debug context (including scope map and namespace map)
let fn_debug_context = box FunctionDebugContextData {
- scope_map: RefCell::new(NodeMap()),
fn_metadata: fn_metadata,
- argument_counter: Cell::new(1),
source_locations_enabled: Cell::new(false),
source_location_override: Cell::new(false),
};
fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
generics: &ty::Generics<'tcx>,
- param_substs: &Substs<'tcx>,
+ substs: &Substs<'tcx>,
file_metadata: DIFile,
name_to_append_suffix_to: &mut String)
-> DIArray
{
- let actual_types = param_substs.types.as_slice();
-
- if actual_types.is_empty() {
+ if substs.types().next().is_none() {
return create_DIArray(DIB(cx), &[]);
}
name_to_append_suffix_to.push('<');
- for (i, &actual_type) in actual_types.iter().enumerate() {
+ for (i, actual_type) in substs.types().enumerate() {
+ if i != 0 {
+ name_to_append_suffix_to.push_str(",");
+ }
+
let actual_type = cx.tcx().normalize_associated_type(&actual_type);
// Add actual type name to <...> clause of function name
let actual_type_name = compute_debuginfo_type_name(cx,
actual_type,
true);
name_to_append_suffix_to.push_str(&actual_type_name[..]);
-
- if i != actual_types.len() - 1 {
- name_to_append_suffix_to.push_str(",");
- }
}
name_to_append_suffix_to.push('>');
// Again, only create type information if full debuginfo is enabled
let template_params: Vec<_> = if cx.sess().opts.debuginfo == FullDebugInfo {
- generics.types.as_slice().iter().enumerate().map(|(i, param)| {
- let actual_type = cx.tcx().normalize_associated_type(&actual_types[i]);
+ let names = get_type_parameter_names(cx, generics);
+ substs.types().zip(names).map(|(ty, name)| {
+ let actual_type = cx.tcx().normalize_associated_type(&ty);
let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
- let name = CString::new(param.name.as_str().as_bytes()).unwrap();
+ let name = CString::new(name.as_str().as_bytes()).unwrap();
unsafe {
llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
DIB(cx),
return create_DIArray(DIB(cx), &template_params[..]);
}
- fn get_containing_scope_and_span<'ccx, 'tcx>(cx: &CrateContext<'ccx, 'tcx>,
- instance: Instance<'tcx>)
- -> (DIScope, Span) {
+ fn get_type_parameter_names<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+ generics: &ty::Generics<'tcx>)
+ -> Vec<ast::Name> {
+ let mut names = generics.parent.map_or(vec![], |def_id| {
+ get_type_parameter_names(cx, cx.tcx().lookup_generics(def_id))
+ });
+ names.extend(generics.types.iter().map(|param| param.name));
+ names
+ }
+
+ fn get_containing_scope<'ccx, 'tcx>(cx: &CrateContext<'ccx, 'tcx>,
+ instance: Instance<'tcx>)
+ -> DIScope {
// First, let's see if this is a method within an inherent impl. Because
// if yes, we want to make the result subroutine DIE a child of the
// subroutine's self-type.
if cx.tcx().trait_id_of_impl(impl_def_id).is_none() {
let impl_self_ty = cx.tcx().lookup_item_type(impl_def_id).ty;
let impl_self_ty = cx.tcx().erase_regions(&impl_self_ty);
- let impl_self_ty = monomorphize::apply_param_substs(cx.tcx(),
+ let impl_self_ty = monomorphize::apply_param_substs(cx.shared(),
instance.substs,
&impl_self_ty);
- Some(type_metadata(cx, impl_self_ty, syntax_pos::DUMMY_SP))
+
+ // Only "class" methods are generally understood by LLVM,
+ // so avoid methods on other types (e.g. `<*mut T>::null`).
+ match impl_self_ty.sty {
+ ty::TyAdt(..) => {
+ Some(type_metadata(cx, impl_self_ty, syntax_pos::DUMMY_SP))
+ }
+ _ => None
+ }
} else {
// For trait method impls we still use the "parallel namespace"
// strategy
}
});
- let containing_scope = self_type.unwrap_or_else(|| {
+ self_type.unwrap_or_else(|| {
namespace::item_namespace(cx, DefId {
krate: instance.def.krate,
index: cx.tcx()
.def_key(instance.def)
.parent
- .expect("get_containing_scope_and_span: missing parent?")
+ .expect("get_containing_scope: missing parent?")
})
- });
-
- // Try to get some span information, if we have an inlined item.
- let definition_span = cx.tcx()
- .map
- .def_id_span(instance.def, syntax_pos::DUMMY_SP);
-
- (containing_scope, definition_span)
- }
-}
-
-/// Computes the scope map for a function given its declaration and body.
-pub fn fill_scope_map_for_function<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
- fn_decl: &hir::FnDecl,
- top_level_block: &hir::Block,
- fn_ast_id: ast::NodeId) {
- match fcx.debug_context {
- FunctionDebugContext::RegularContext(box ref data) => {
- let scope_map = create_scope_map::create_scope_map(fcx.ccx,
- &fn_decl.inputs,
- top_level_block,
- data.fn_metadata,
- fn_ast_id);
- *data.scope_map.borrow_mut() = scope_map;
- }
- FunctionDebugContext::DebugInfoDisabled |
- FunctionDebugContext::FunctionWithoutDebugInfo => {}
+ })
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum DebugLoc {
- At(ast::NodeId, Span),
ScopeAt(DIScope, Span),
None
}
source_loc::set_source_location(bcx.fcx(), Some(bcx), self);
}
}
-
-pub trait ToDebugLoc {
- fn debug_loc(&self) -> DebugLoc;
-}
-
-impl ToDebugLoc for hir::Expr {
- fn debug_loc(&self) -> DebugLoc {
- DebugLoc::At(self.id, self.span)
- }
-}
-
-impl ToDebugLoc for NodeIdAndSpan {
- fn debug_loc(&self) -> DebugLoc {
- DebugLoc::At(self.id, self.span)
- }
-}
-
-impl ToDebugLoc for Option<NodeIdAndSpan> {
- fn debug_loc(&self) -> DebugLoc {
- match *self {
- Some(NodeIdAndSpan { id, span }) => DebugLoc::At(id, span),
- None => DebugLoc::None
- }
- }
-}