|
|
@@ -222,6 +222,13 @@ static DW_ATE_signed: c_uint = 0x05; |
|
|
|
static DW_ATE_unsigned: c_uint = 0x07; |
|
|
|
static DW_ATE_unsigned_char: c_uint = 0x08; |
|
|
|
|
|
|
|
static UNKNOWN_LINE_NUMBER: c_uint = 0; |
|
|
|
static UNKNOWN_COLUMN_NUMBER: c_uint = 0; |
|
|
|
|
|
|
|
// ptr::null() doesn't work :( |
|
|
|
static UNKNOWN_FILE_METADATA: DIFile = (0 as DIFile); |
|
|
|
static UNKNOWN_SCOPE_METADATA: DIScope = (0 as DIScope); |
|
|
|
|
|
|
|
//=----------------------------------------------------------------------------- |
|
|
|
// Public Interface of debuginfo module |
|
|
|
//=----------------------------------------------------------------------------- |
|
|
@@ -330,15 +337,15 @@ impl TypeMap { |
|
|
|
unique_type_id.push_char('{'); |
|
|
|
|
|
|
|
match ty::get(type_).sty { |
|
|
|
ty::ty_nil | |
|
|
|
ty::ty_bot | |
|
|
|
ty::ty_bool | |
|
|
|
ty::ty_char | |
|
|
|
ty::ty_str | |
|
|
|
ty::ty_int(_) | |
|
|
|
ty::ty_uint(_) | |
|
|
|
ty::ty_nil | |
|
|
|
ty::ty_bot | |
|
|
|
ty::ty_bool | |
|
|
|
ty::ty_char | |
|
|
|
ty::ty_str | |
|
|
|
ty::ty_int(_) | |
|
|
|
ty::ty_uint(_) | |
|
|
|
ty::ty_float(_) => { |
|
|
|
unique_type_id.push_str(ppaux::ty_to_str(cx.tcx(), type_).as_slice()); |
|
|
|
push_debuginfo_type_name(cx, type_, false, &mut unique_type_id); |
|
|
|
}, |
|
|
|
ty::ty_enum(def_id, ref substs) => { |
|
|
|
unique_type_id.push_str("enum "); |
|
|
@@ -587,7 +594,7 @@ impl TypeMap { |
|
|
|
element_type: ty::t) |
|
|
|
-> UniqueTypeId { |
|
|
|
let element_type_id = self.get_unique_type_id_of_type(cx, element_type); |
|
|
|
let heap_vec_box_type_id = format!("$$HEAP_VEC_BOX<{}>$$", |
|
|
|
let heap_vec_box_type_id = format!("{{HEAP_VEC_BOX<{}>}}", |
|
|
|
self.get_unique_type_id_as_string(element_type_id) |
|
|
|
.as_slice()); |
|
|
|
let interner_key = self.unique_id_interner.intern(Rc::new(heap_vec_box_type_id)); |
|
|
@@ -599,14 +606,27 @@ impl TypeMap { |
|
|
|
element_type: ty::t) |
|
|
|
-> UniqueTypeId { |
|
|
|
let element_type_id = self.get_unique_type_id_of_type(cx, element_type); |
|
|
|
let gc_box_type_id = format!("$$GC_BOX<{}>$$", |
|
|
|
let gc_box_type_id = format!("{{GC_BOX<{}>}}", |
|
|
|
self.get_unique_type_id_as_string(element_type_id) |
|
|
|
.as_slice()); |
|
|
|
let interner_key = self.unique_id_interner.intern(Rc::new(gc_box_type_id)); |
|
|
|
UniqueTypeId(interner_key) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Returns from the enclosing function if the type metadata with the given |
|
|
|
// unique id can be found in the type map |
|
|
|
macro_rules! return_if_metadata_created_in_meantime( |
|
|
|
($cx: expr, $unique_type_id: expr) => ( |
|
|
|
match debug_context($cx).type_map |
|
|
|
.borrow() |
|
|
|
.find_metadata_for_unique_id($unique_type_id) { |
|
|
|
Some(metadata) => return MetadataCreationResult::new(metadata, true), |
|
|
|
None => { /* proceed normally */ } |
|
|
|
}; |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
/// A context object for maintaining all state needed by the debuginfo module. |
|
|
|
pub struct CrateDebugContext { |
|
|
@@ -1304,9 +1324,12 @@ pub fn create_function_debug_context(cx: &CrateContext, |
|
|
|
if has_self_type { |
|
|
|
let actual_self_type = self_type.unwrap(); |
|
|
|
// Add self type name to <...> clause of function name |
|
|
|
let actual_self_type_name = ppaux::ty_to_str(cx.tcx(), actual_self_type); |
|
|
|
name_to_append_suffix_to.push_str( |
|
|
|
actual_self_type_name.as_slice()); |
|
|
|
let actual_self_type_name = compute_debuginfo_type_name( |
|
|
|
cx, |
|
|
|
actual_self_type, |
|
|
|
true); |
|
|
|
|
|
|
|
name_to_append_suffix_to.push_str(actual_self_type_name.as_slice()); |
|
|
|
|
|
|
|
if generics.is_type_parameterized() { |
|
|
|
name_to_append_suffix_to.push_str(","); |
|
|
@@ -1343,7 +1366,9 @@ pub fn create_function_debug_context(cx: &CrateContext, |
|
|
|
for (index, &ast::TyParam{ ident: ident, .. }) in generics.ty_params.iter().enumerate() { |
|
|
|
let actual_type = *actual_types.get(index); |
|
|
|
// Add actual type name to <...> clause of function name |
|
|
|
let actual_type_name = ppaux::ty_to_str(cx.tcx(), actual_type); |
|
|
|
let actual_type_name = compute_debuginfo_type_name(cx, |
|
|
|
actual_type, |
|
|
|
true); |
|
|
|
name_to_append_suffix_to.push_str(actual_type_name.as_slice()); |
|
|
|
|
|
|
|
if index != generics.ty_params.len() - 1 { |
|
|
@@ -1646,7 +1671,7 @@ fn pointer_type_metadata(cx: &CrateContext, |
|
|
|
-> DIType { |
|
|
|
let pointer_llvm_type = type_of::type_of(cx, pointer_type); |
|
|
|
let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type); |
|
|
|
let name = ppaux::ty_to_str(cx.tcx(), pointer_type); |
|
|
|
let name = compute_debuginfo_type_name(cx, pointer_type, false); |
|
|
|
let ptr_metadata = name.as_slice().with_c_str(|name| { |
|
|
|
unsafe { |
|
|
|
llvm::LLVMDIBuilderCreatePointerType( |
|
|
@@ -1719,7 +1744,6 @@ enum RecursiveTypeDescription { |
|
|
|
unique_type_id: UniqueTypeId, |
|
|
|
metadata_stub: DICompositeType, |
|
|
|
llvm_type: Type, |
|
|
|
file_metadata: DIFile, |
|
|
|
member_description_factory: MemberDescriptionFactory, |
|
|
|
}, |
|
|
|
FinalMetadata(DICompositeType) |
|
|
@@ -1731,7 +1755,6 @@ fn create_and_register_recursive_type_forward_declaration( |
|
|
|
unique_type_id: UniqueTypeId, |
|
|
|
metadata_stub: DICompositeType, |
|
|
|
llvm_type: Type, |
|
|
|
file_metadata: DIFile, |
|
|
|
member_description_factory: MemberDescriptionFactory) |
|
|
|
-> RecursiveTypeDescription { |
|
|
|
|
|
|
@@ -1745,7 +1768,6 @@ fn create_and_register_recursive_type_forward_declaration( |
|
|
|
unique_type_id: unique_type_id, |
|
|
|
metadata_stub: metadata_stub, |
|
|
|
llvm_type: llvm_type, |
|
|
|
file_metadata: file_metadata, |
|
|
|
member_description_factory: member_description_factory, |
|
|
|
} |
|
|
|
} |
|
|
@@ -1761,8 +1783,8 @@ impl RecursiveTypeDescription { |
|
|
|
unique_type_id, |
|
|
|
metadata_stub, |
|
|
|
llvm_type, |
|
|
|
file_metadata, |
|
|
|
ref member_description_factory |
|
|
|
ref member_description_factory, |
|
|
|
.. |
|
|
|
} => { |
|
|
|
// Make sure that we have a forward declaration of the type in |
|
|
|
// the TypeMap so that recursive references are possible. This |
|
|
@@ -1788,9 +1810,7 @@ impl RecursiveTypeDescription { |
|
|
|
set_members_of_composite_type(cx, |
|
|
|
metadata_stub, |
|
|
|
llvm_type, |
|
|
|
member_descriptions.as_slice(), |
|
|
|
file_metadata, |
|
|
|
codemap::DUMMY_SP); |
|
|
|
member_descriptions.as_slice()); |
|
|
|
return MetadataCreationResult::new(metadata_stub, true); |
|
|
|
} |
|
|
|
} |
|
|
@@ -1845,28 +1865,24 @@ impl StructMemberDescriptionFactory { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fn prepare_struct_metadata(cx: &CrateContext, |
|
|
|
struct_type: ty::t, |
|
|
|
def_id: ast::DefId, |
|
|
|
substs: &subst::Substs, |
|
|
|
unique_type_id: UniqueTypeId, |
|
|
|
span: Span) |
|
|
|
-> RecursiveTypeDescription { |
|
|
|
let struct_name = ppaux::ty_to_str(cx.tcx(), struct_type); |
|
|
|
let struct_name = compute_debuginfo_type_name(cx, struct_type, false); |
|
|
|
let struct_llvm_type = type_of::type_of(cx, struct_type); |
|
|
|
|
|
|
|
let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id); |
|
|
|
|
|
|
|
let file_name = span_start(cx, definition_span).file.name.clone(); |
|
|
|
let file_metadata = file_metadata(cx, file_name.as_slice()); |
|
|
|
let (containing_scope, _) = get_namespace_and_span_for_item(cx, def_id); |
|
|
|
|
|
|
|
let struct_metadata_stub = create_struct_stub(cx, |
|
|
|
struct_llvm_type, |
|
|
|
struct_name.as_slice(), |
|
|
|
unique_type_id, |
|
|
|
containing_scope, |
|
|
|
file_metadata, |
|
|
|
definition_span); |
|
|
|
containing_scope); |
|
|
|
|
|
|
|
let fields = ty::struct_fields(cx.tcx(), def_id, substs); |
|
|
|
|
|
|
@@ -1876,7 +1892,6 @@ fn prepare_struct_metadata(cx: &CrateContext, |
|
|
|
unique_type_id, |
|
|
|
struct_metadata_stub, |
|
|
|
struct_llvm_type, |
|
|
|
file_metadata, |
|
|
|
StructMDF(StructMemberDescriptionFactory { |
|
|
|
fields: fields, |
|
|
|
is_simd: ty::type_is_simd(cx.tcx(), struct_type), |
|
|
@@ -1916,12 +1931,9 @@ fn prepare_tuple_metadata(cx: &CrateContext, |
|
|
|
unique_type_id: UniqueTypeId, |
|
|
|
span: Span) |
|
|
|
-> RecursiveTypeDescription { |
|
|
|
let tuple_name = ppaux::ty_to_str(cx.tcx(), tuple_type); |
|
|
|
let tuple_name = compute_debuginfo_type_name(cx, tuple_type, false); |
|
|
|
let tuple_llvm_type = type_of::type_of(cx, tuple_type); |
|
|
|
|
|
|
|
let loc = span_start(cx, span); |
|
|
|
let file_metadata = file_metadata(cx, loc.file.name.as_slice()); |
|
|
|
|
|
|
|
create_and_register_recursive_type_forward_declaration( |
|
|
|
cx, |
|
|
|
tuple_type, |
|
|
@@ -1930,11 +1942,8 @@ fn prepare_tuple_metadata(cx: &CrateContext, |
|
|
|
tuple_llvm_type, |
|
|
|
tuple_name.as_slice(), |
|
|
|
unique_type_id, |
|
|
|
file_metadata, |
|
|
|
file_metadata, |
|
|
|
span), |
|
|
|
UNKNOWN_SCOPE_METADATA), |
|
|
|
tuple_llvm_type, |
|
|
|
file_metadata, |
|
|
|
TupleMDF(TupleMemberDescriptionFactory { |
|
|
|
component_types: Vec::from_slice(component_types), |
|
|
|
span: span, |
|
|
@@ -1982,7 +1991,6 @@ impl EnumMemberDescriptionFactory { |
|
|
|
&**self.variants.get(i), |
|
|
|
discriminant_info, |
|
|
|
self.containing_scope, |
|
|
|
self.file_metadata, |
|
|
|
self.span); |
|
|
|
|
|
|
|
let member_descriptions = member_desc_factory |
|
|
@@ -1991,9 +1999,7 @@ impl EnumMemberDescriptionFactory { |
|
|
|
set_members_of_composite_type(cx, |
|
|
|
variant_type_metadata, |
|
|
|
variant_llvm_type, |
|
|
|
member_descriptions.as_slice(), |
|
|
|
self.file_metadata, |
|
|
|
codemap::DUMMY_SP); |
|
|
|
member_descriptions.as_slice()); |
|
|
|
MemberDescription { |
|
|
|
name: "".to_string(), |
|
|
|
llvm_type: variant_llvm_type, |
|
|
@@ -2017,7 +2023,6 @@ impl EnumMemberDescriptionFactory { |
|
|
|
&**self.variants.get(0), |
|
|
|
NoDiscriminant, |
|
|
|
self.containing_scope, |
|
|
|
self.file_metadata, |
|
|
|
self.span); |
|
|
|
|
|
|
|
let member_descriptions = |
|
|
@@ -2026,9 +2031,7 @@ impl EnumMemberDescriptionFactory { |
|
|
|
set_members_of_composite_type(cx, |
|
|
|
variant_type_metadata, |
|
|
|
variant_llvm_type, |
|
|
|
member_descriptions.as_slice(), |
|
|
|
self.file_metadata, |
|
|
|
codemap::DUMMY_SP); |
|
|
|
member_descriptions.as_slice()); |
|
|
|
vec![ |
|
|
|
MemberDescription { |
|
|
|
name: "".to_string(), |
|
|
@@ -2119,7 +2122,6 @@ impl EnumMemberDescriptionFactory { |
|
|
|
&**self.variants.get(nndiscr as uint), |
|
|
|
OptimizedDiscriminant(ptrfield), |
|
|
|
self.containing_scope, |
|
|
|
self.file_metadata, |
|
|
|
self.span); |
|
|
|
|
|
|
|
let variant_member_descriptions = |
|
|
@@ -2128,9 +2130,7 @@ impl EnumMemberDescriptionFactory { |
|
|
|
set_members_of_composite_type(cx, |
|
|
|
variant_type_metadata, |
|
|
|
variant_llvm_type, |
|
|
|
variant_member_descriptions.as_slice(), |
|
|
|
self.file_metadata, |
|
|
|
codemap::DUMMY_SP); |
|
|
|
variant_member_descriptions.as_slice()); |
|
|
|
|
|
|
|
// Encode the information about the null variant in the union |
|
|
|
// member's name. |
|
|
@@ -2195,7 +2195,6 @@ fn describe_enum_variant(cx: &CrateContext, |
|
|
|
variant_info: &ty::VariantInfo, |
|
|
|
discriminant_info: EnumDiscriminantInfo, |
|
|
|
containing_scope: DIScope, |
|
|
|
file_metadata: DIFile, |
|
|
|
span: Span) |
|
|
|
-> (DICompositeType, Type, MemberDescriptionFactory) { |
|
|
|
let variant_llvm_type = |
|
|
@@ -2207,14 +2206,6 @@ fn describe_enum_variant(cx: &CrateContext, |
|
|
|
struct_def.packed); |
|
|
|
// Could do some consistency checks here: size, align, field count, discr type |
|
|
|
|
|
|
|
// Find the source code location of the variant's definition |
|
|
|
let variant_definition_span = if variant_info.id.krate == ast::LOCAL_CRATE { |
|
|
|
cx.tcx.map.span(variant_info.id.node) |
|
|
|
} else { |
|
|
|
// For definitions from other crates we have no location information available. |
|
|
|
codemap::DUMMY_SP |
|
|
|
}; |
|
|
|
|
|
|
|
let variant_name = token::get_ident(variant_info.name); |
|
|
|
let variant_name = variant_name.get(); |
|
|
|
let unique_type_id = debug_context(cx).type_map |
|
|
@@ -2228,9 +2219,7 @@ fn describe_enum_variant(cx: &CrateContext, |
|
|
|
variant_llvm_type, |
|
|
|
variant_name, |
|
|
|
unique_type_id, |
|
|
|
containing_scope, |
|
|
|
file_metadata, |
|
|
|
variant_definition_span); |
|
|
|
containing_scope); |
|
|
|
|
|
|
|
// Get the argument names from the enum variant info |
|
|
|
let mut arg_names: Vec<_> = match variant_info.arg_names { |
|
|
@@ -2276,7 +2265,7 @@ fn prepare_enum_metadata(cx: &CrateContext, |
|
|
|
unique_type_id: UniqueTypeId, |
|
|
|
span: Span) |
|
|
|
-> RecursiveTypeDescription { |
|
|
|
let enum_name = ppaux::ty_to_str(cx.tcx(), enum_type); |
|
|
|
let enum_name = compute_debuginfo_type_name(cx, enum_type, false); |
|
|
|
|
|
|
|
let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, enum_def_id); |
|
|
|
let loc = span_start(cx, definition_span); |
|
|
@@ -2323,8 +2312,8 @@ fn prepare_enum_metadata(cx: &CrateContext, |
|
|
|
DIB(cx), |
|
|
|
containing_scope, |
|
|
|
name, |
|
|
|
file_metadata, |
|
|
|
loc.line as c_uint, |
|
|
|
UNKNOWN_FILE_METADATA, |
|
|
|
UNKNOWN_LINE_NUMBER, |
|
|
|
bytes_to_bits(discriminant_size), |
|
|
|
bytes_to_bits(discriminant_align), |
|
|
|
create_DIArray(DIB(cx), enumerators_metadata.as_slice()), |
|
|
@@ -2368,8 +2357,8 @@ fn prepare_enum_metadata(cx: &CrateContext, |
|
|
|
DIB(cx), |
|
|
|
containing_scope, |
|
|
|
enum_name, |
|
|
|
file_metadata, |
|
|
|
loc.line as c_uint, |
|
|
|
UNKNOWN_FILE_METADATA, |
|
|
|
UNKNOWN_LINE_NUMBER, |
|
|
|
bytes_to_bits(enum_type_size), |
|
|
|
bytes_to_bits(enum_type_align), |
|
|
|
0, // Flags |
|
|
@@ -2386,7 +2375,6 @@ fn prepare_enum_metadata(cx: &CrateContext, |
|
|
|
unique_type_id, |
|
|
|
enum_metadata, |
|
|
|
enum_llvm_type, |
|
|
|
file_metadata, |
|
|
|
EnumMDF(EnumMemberDescriptionFactory { |
|
|
|
enum_type: enum_type, |
|
|
|
type_rep: type_rep.clone(), |
|
|
@@ -2421,34 +2409,31 @@ fn composite_type_metadata(cx: &CrateContext, |
|
|
|
composite_type_unique_id: UniqueTypeId, |
|
|
|
member_descriptions: &[MemberDescription], |
|
|
|
containing_scope: DIScope, |
|
|
|
file_metadata: DIFile, |
|
|
|
definition_span: Span) |
|
|
|
|
|
|
|
// Ignore source location information as long as it |
|
|
|
// can't be reconstructed for non-local crates. |
|
|
|
_file_metadata: DIFile, |
|
|
|
_definition_span: Span) |
|
|
|
-> DICompositeType { |
|
|
|
// Create the (empty) struct metadata node ... |
|
|
|
let composite_type_metadata = create_struct_stub(cx, |
|
|
|
composite_llvm_type, |
|
|
|
composite_type_name, |
|
|
|
composite_type_unique_id, |
|
|
|
containing_scope, |
|
|
|
file_metadata, |
|
|
|
definition_span); |
|
|
|
containing_scope); |
|
|
|
// ... and immediately create and add the member descriptions. |
|
|
|
set_members_of_composite_type(cx, |
|
|
|
composite_type_metadata, |
|
|
|
composite_llvm_type, |
|
|
|
member_descriptions, |
|
|
|
file_metadata, |
|
|
|
definition_span); |
|
|
|
member_descriptions); |
|
|
|
|
|
|
|
return composite_type_metadata; |
|
|
|
} |
|
|
|
|
|
|
|
fn set_members_of_composite_type(cx: &CrateContext, |
|
|
|
composite_type_metadata: DICompositeType, |
|
|
|
composite_llvm_type: Type, |
|
|
|
member_descriptions: &[MemberDescription], |
|
|
|
file_metadata: DIFile, |
|
|
|
definition_span: Span) { |
|
|
|
member_descriptions: &[MemberDescription]) { |
|
|
|
// In some rare cases LLVM metadata uniquing would lead to an existing type |
|
|
|
// description being used instead of a new one created in create_struct_stub. |
|
|
|
// This would cause a hard to trace assertion in DICompositeType::SetTypeArray(). |
|
|
@@ -2483,8 +2468,6 @@ fn set_members_of_composite_type(cx: &CrateContext, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
let loc = span_start(cx, definition_span); |
|
|
|
|
|
|
|
let member_metadata: Vec<DIDescriptor> = member_descriptions |
|
|
|
.iter() |
|
|
|
.enumerate() |
|
|
@@ -2501,8 +2484,8 @@ fn set_members_of_composite_type(cx: &CrateContext, |
|
|
|
DIB(cx), |
|
|
|
composite_type_metadata, |
|
|
|
member_name, |
|
|
|
file_metadata, |
|
|
|
loc.line as c_uint, |
|
|
|
UNKNOWN_FILE_METADATA, |
|
|
|
UNKNOWN_LINE_NUMBER, |
|
|
|
bytes_to_bits(member_size), |
|
|
|
bytes_to_bits(member_align), |
|
|
|
bytes_to_bits(member_offset), |
|
|
@@ -2526,11 +2509,8 @@ fn create_struct_stub(cx: &CrateContext, |
|
|
|
struct_llvm_type: Type, |
|
|
|
struct_type_name: &str, |
|
|
|
unique_type_id: UniqueTypeId, |
|
|
|
containing_scope: DIScope, |
|
|
|
file_metadata: DIFile, |
|
|
|
definition_span: Span) |
|
|
|
containing_scope: DIScope) |
|
|
|
-> DICompositeType { |
|
|
|
let loc = span_start(cx, definition_span); |
|
|
|
let (struct_size, struct_align) = size_and_align_of(cx, struct_llvm_type); |
|
|
|
|
|
|
|
let unique_type_id_str = debug_context(cx).type_map |
|
|
@@ -2548,8 +2528,8 @@ fn create_struct_stub(cx: &CrateContext, |
|
|
|
DIB(cx), |
|
|
|
containing_scope, |
|
|
|
name, |
|
|
|
file_metadata, |
|
|
|
loc.line as c_uint, |
|
|
|
UNKNOWN_FILE_METADATA, |
|
|
|
UNKNOWN_LINE_NUMBER, |
|
|
|
bytes_to_bits(struct_size), |
|
|
|
bytes_to_bits(struct_align), |
|
|
|
0, |
|
|
@@ -2572,12 +2552,9 @@ fn at_box_metadata(cx: &CrateContext, |
|
|
|
-> MetadataCreationResult { |
|
|
|
let content_type_metadata = type_metadata(cx, content_type, codemap::DUMMY_SP); |
|
|
|
|
|
|
|
match debug_context(cx).type_map.borrow().find_metadata_for_unique_id(unique_type_id) { |
|
|
|
Some(metadata) => return MetadataCreationResult::new(metadata, true), |
|
|
|
None => { /* proceed */ } |
|
|
|
}; |
|
|
|
return_if_metadata_created_in_meantime!(cx, unique_type_id); |
|
|
|
|
|
|
|
let content_type_name = ppaux::ty_to_str(cx.tcx(), content_type); |
|
|
|
let content_type_name = compute_debuginfo_type_name(cx, content_type, true); |
|
|
|
let content_type_name = content_type_name.as_slice(); |
|
|
|
let content_llvm_type = type_of::type_of(cx, content_type); |
|
|
|
|
|
|
@@ -2593,7 +2570,6 @@ fn at_box_metadata(cx: &CrateContext, |
|
|
|
let nil_pointer_type_metadata = type_metadata(cx, |
|
|
|
nil_pointer_type, |
|
|
|
codemap::DUMMY_SP); |
|
|
|
|
|
|
|
let member_descriptions = [ |
|
|
|
MemberDescription { |
|
|
|
name: "refcnt".to_string(), |
|
|
@@ -2627,9 +2603,6 @@ fn at_box_metadata(cx: &CrateContext, |
|
|
|
} |
|
|
|
]; |
|
|
|
|
|
|
|
let loc = span_start(cx, codemap::DUMMY_SP); |
|
|
|
let file_metadata = file_metadata(cx, loc.file.name.as_slice()); |
|
|
|
|
|
|
|
let gc_box_unique_id = debug_context(cx).type_map |
|
|
|
.borrow_mut() |
|
|
|
.get_unique_type_id_of_gc_box(cx, content_type); |
|
|
@@ -2640,8 +2613,8 @@ fn at_box_metadata(cx: &CrateContext, |
|
|
|
box_type_name.as_slice(), |
|
|
|
gc_box_unique_id, |
|
|
|
member_descriptions, |
|
|
|
file_metadata, |
|
|
|
file_metadata, |
|
|
|
UNKNOWN_SCOPE_METADATA, |
|
|
|
UNKNOWN_FILE_METADATA, |
|
|
|
codemap::DUMMY_SP); |
|
|
|
|
|
|
|
let gc_pointer_metadata = pointer_type_metadata(cx, |
|
|
@@ -2674,10 +2647,7 @@ fn fixed_vec_metadata(cx: &CrateContext, |
|
|
|
-> MetadataCreationResult { |
|
|
|
let element_type_metadata = type_metadata(cx, element_type, span); |
|
|
|
|
|
|
|
match debug_context(cx).type_map.borrow().find_metadata_for_unique_id(unique_type_id) { |
|
|
|
Some(metadata) => return MetadataCreationResult::new(metadata, true), |
|
|
|
None => { /* proceed */ } |
|
|
|
}; |
|
|
|
return_if_metadata_created_in_meantime!(cx, unique_type_id); |
|
|
|
|
|
|
|
let element_llvm_type = type_of::type_of(cx, element_type); |
|
|
|
let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type); |
|
|
@@ -2712,13 +2682,12 @@ fn heap_vec_metadata(cx: &CrateContext, |
|
|
|
let element_llvm_type = type_of::type_of(cx, element_type); |
|
|
|
let (element_size, element_align) = size_and_align_of(cx, element_llvm_type); |
|
|
|
|
|
|
|
match debug_context(cx).type_map.borrow().find_metadata_for_unique_id(unique_type_id) { |
|
|
|
Some(metadata) => return MetadataCreationResult::new(metadata, true), |
|
|
|
None => { /* proceed */ } |
|
|
|
}; |
|
|
|
return_if_metadata_created_in_meantime!(cx, unique_type_id); |
|
|
|
|
|
|
|
let vecbox_llvm_type = Type::vec(cx, &element_llvm_type); |
|
|
|
let vec_pointer_type_name = ppaux::ty_to_str(cx.tcx(), vec_pointer_type); |
|
|
|
let vec_pointer_type_name = compute_debuginfo_type_name(cx, |
|
|
|
vec_pointer_type, |
|
|
|
true); |
|
|
|
let vec_pointer_type_name = vec_pointer_type_name.as_slice(); |
|
|
|
|
|
|
|
let member_llvm_types = vecbox_llvm_type.field_types(); |
|
|
@@ -2769,7 +2738,7 @@ fn heap_vec_metadata(cx: &CrateContext, |
|
|
|
vec_pointer_type_name, |
|
|
|
vec_box_unique_id, |
|
|
|
member_descriptions, |
|
|
|
file_metadata, |
|
|
|
UNKNOWN_SCOPE_METADATA, |
|
|
|
file_metadata, |
|
|
|
span); |
|
|
|
|
|
|
@@ -2791,13 +2760,10 @@ fn vec_slice_metadata(cx: &CrateContext, |
|
|
|
|
|
|
|
let element_type_metadata = type_metadata(cx, data_ptr_type, span); |
|
|
|
|
|
|
|
match debug_context(cx).type_map.borrow().find_metadata_for_unique_id(unique_type_id) { |
|
|
|
Some(metadata) => return MetadataCreationResult::new(metadata, true), |
|
|
|
None => { /* proceed */ } |
|
|
|
}; |
|
|
|
return_if_metadata_created_in_meantime!(cx, unique_type_id); |
|
|
|
|
|
|
|
let slice_llvm_type = type_of::type_of(cx, vec_type); |
|
|
|
let slice_type_name = ppaux::ty_to_str(cx.tcx(), vec_type); |
|
|
|
let slice_type_name = compute_debuginfo_type_name(cx, vec_type, true); |
|
|
|
|
|
|
|
let member_llvm_types = slice_llvm_type.field_types(); |
|
|
|
assert!(slice_layout_is_correct(cx, |
|
|
@@ -2828,7 +2794,7 @@ fn vec_slice_metadata(cx: &CrateContext, |
|
|
|
slice_type_name.as_slice(), |
|
|
|
unique_type_id, |
|
|
|
member_descriptions, |
|
|
|
file_metadata, |
|
|
|
UNKNOWN_SCOPE_METADATA, |
|
|
|
file_metadata, |
|
|
|
span); |
|
|
|
return MetadataCreationResult::new(metadata, false); |
|
|
@@ -2848,8 +2814,6 @@ fn subroutine_type_metadata(cx: &CrateContext, |
|
|
|
signature: &ty::FnSig, |
|
|
|
span: Span) |
|
|
|
-> MetadataCreationResult { |
|
|
|
let loc = span_start(cx, span); |
|
|
|
let file_metadata = file_metadata(cx, loc.file.name.as_slice()); |
|
|
|
let mut signature_metadata: Vec<DIType> = Vec::with_capacity(signature.inputs.len() + 1); |
|
|
|
|
|
|
|
// return type |
|
|
@@ -2863,57 +2827,64 @@ fn subroutine_type_metadata(cx: &CrateContext, |
|
|
|
signature_metadata.push(type_metadata(cx, argument_type, span)); |
|
|
|
} |
|
|
|
|
|
|
|
match debug_context(cx).type_map.borrow().find_metadata_for_unique_id(unique_type_id) { |
|
|
|
Some(metadata) => return MetadataCreationResult::new(metadata, true), |
|
|
|
None => { /* proceed */ } |
|
|
|
}; |
|
|
|
return_if_metadata_created_in_meantime!(cx, unique_type_id); |
|
|
|
|
|
|
|
return MetadataCreationResult::new( |
|
|
|
unsafe { |
|
|
|
llvm::LLVMDIBuilderCreateSubroutineType( |
|
|
|
DIB(cx), |
|
|
|
file_metadata, |
|
|
|
UNKNOWN_FILE_METADATA, |
|
|
|
create_DIArray(DIB(cx), signature_metadata.as_slice())) |
|
|
|
}, |
|
|
|
false); |
|
|
|
} |
|
|
|
|
|
|
|
fn trait_metadata(cx: &CrateContext, |
|
|
|
def_id: ast::DefId, |
|
|
|
trait_type: ty::t, |
|
|
|
substs: &subst::Substs, |
|
|
|
trait_store: ty::TraitStore, |
|
|
|
_: &ty::BuiltinBounds, |
|
|
|
unique_type_id: UniqueTypeId) |
|
|
|
-> DIType { |
|
|
|
fn trait_pointer_metadata(cx: &CrateContext, |
|
|
|
// trait_pointer_type must be the type of the fat |
|
|
|
// pointer to the concrete trait object |
|
|
|
trait_pointer_type: ty::t, |
|
|
|
unique_type_id: UniqueTypeId) |
|
|
|
-> DIType { |
|
|
|
// The implementation provided here is a stub. It makes sure that the trait |
|
|
|
// type is assigned the correct name, size, namespace, and source location. |
|
|
|
// But it does not describe the trait's methods. |
|
|
|
let last = ty::with_path(cx.tcx(), def_id, |mut path| path.last().unwrap()); |
|
|
|
let ident_string = token::get_name(last.name()); |
|
|
|
let mut name = ppaux::trait_store_to_str(cx.tcx(), trait_store); |
|
|
|
name.push_str(ident_string.get()); |
|
|
|
|
|
|
|
// Add type and region parameters |
|
|
|
let trait_def = ty::lookup_trait_def(cx.tcx(), def_id); |
|
|
|
let name = ppaux::parameterized(cx.tcx(), name.as_slice(), |
|
|
|
substs, &trait_def.generics); |
|
|
|
let trait_object_type = match ty::get(trait_pointer_type).sty { |
|
|
|
ty::ty_uniq(pointee_type) => pointee_type, |
|
|
|
ty::ty_rptr(_, ty::mt { ty, .. }) => ty, |
|
|
|
_ => { |
|
|
|
let pp_type_name = ppaux::ty_to_str(cx.tcx(), trait_pointer_type); |
|
|
|
cx.sess().bug(format!("debuginfo: Unexpected trait-pointer type in \ |
|
|
|
trait_pointer_metadata(): {}", |
|
|
|
pp_type_name.as_slice()).as_slice()); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
let def_id = match ty::get(trait_object_type).sty { |
|
|
|
ty::ty_trait(box ty::TyTrait { def_id, .. }) => def_id, |
|
|
|
_ => { |
|
|
|
let pp_type_name = ppaux::ty_to_str(cx.tcx(), trait_object_type); |
|
|
|
cx.sess().bug(format!("debuginfo: Unexpected trait-object type in \ |
|
|
|
trait_pointer_metadata(): {}", |
|
|
|
pp_type_name.as_slice()).as_slice()); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id); |
|
|
|
let trait_pointer_type_name = |
|
|
|
compute_debuginfo_type_name(cx, trait_pointer_type, false); |
|
|
|
|
|
|
|
let file_name = span_start(cx, definition_span).file.name.clone(); |
|
|
|
let file_metadata = file_metadata(cx, file_name.as_slice()); |
|
|
|
let (containing_scope, _) = get_namespace_and_span_for_item(cx, def_id); |
|
|
|
|
|
|
|
let trait_llvm_type = type_of::type_of(cx, trait_type); |
|
|
|
let trait_pointer_llvm_type = type_of::type_of(cx, trait_pointer_type); |
|
|
|
|
|
|
|
composite_type_metadata(cx, |
|
|
|
trait_llvm_type, |
|
|
|
name.as_slice(), |
|
|
|
trait_pointer_llvm_type, |
|
|
|
trait_pointer_type_name.as_slice(), |
|
|
|
unique_type_id, |
|
|
|
[], |
|
|
|
containing_scope, |
|
|
|
file_metadata, |
|
|
|
definition_span) |
|
|
|
UNKNOWN_FILE_METADATA, |
|
|
|
codemap::DUMMY_SP) |
|
|
|
} |
|
|
|
|
|
|
|
fn type_metadata(cx: &CrateContext, |
|
|
@@ -2955,15 +2926,6 @@ fn type_metadata(cx: &CrateContext, |
|
|
|
|
|
|
|
debug!("type_metadata: {:?}", ty::get(t)); |
|
|
|
|
|
|
|
macro_rules! return_if_created_in_meantime( |
|
|
|
() => ( |
|
|
|
match debug_context(cx).type_map.borrow().find_metadata_for_unique_id(unique_type_id) { |
|
|
|
Some(metadata) => return metadata, |
|
|
|
None => { /* proceed normally */ } |
|
|
|
}; |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
let sty = &ty::get(t).sty; |
|
|
|
let MetadataCreationResult { metadata, already_stored_in_typemap } = match *sty { |
|
|
|
ty::ty_nil | |
|
|
@@ -2993,19 +2955,22 @@ fn type_metadata(cx: &CrateContext, |
|
|
|
let i8_t = ty::mk_i8(); |
|
|
|
heap_vec_metadata(cx, pointee_type, i8_t, unique_type_id, usage_site_span) |
|
|
|
} |
|
|
|
ty::ty_trait(box ty::TyTrait { |
|
|
|
def_id, |
|
|
|
ref substs, |
|
|
|
ref bounds |
|
|
|
}) => { |
|
|
|
ty::ty_trait(..) => { |
|
|
|
MetadataCreationResult::new( |
|
|
|
trait_metadata(cx, def_id, t, substs, ty::UniqTraitStore, |
|
|
|
bounds, unique_type_id), |
|
|
|
false) |
|
|
|
trait_pointer_metadata(cx, t, unique_type_id), |
|
|
|
false) |
|
|
|
} |
|
|
|
_ => { |
|
|
|
let pointee_metadata = type_metadata(cx, pointee_type, usage_site_span); |
|
|
|
return_if_created_in_meantime!(); |
|
|
|
let pointee_metadata = type_metadata(cx, |
|
|
|
pointee_type, |
|
|
|
usage_site_span); |
|
|
|
match debug_context(cx).type_map |
|
|
|
.borrow() |
|
|
|
.find_metadata_for_unique_id(unique_type_id) { |
|
|
|
Some(metadata) => return metadata, |
|
|
|
None => { /* proceed normally */ } |
|
|
|
}; |
|
|
|
|
|
|
|
MetadataCreationResult::new(pointer_type_metadata(cx, t, pointee_metadata), |
|
|
|
false) |
|
|
|
} |
|
|
@@ -3017,22 +2982,23 @@ fn type_metadata(cx: &CrateContext, |
|
|
|
vec_slice_metadata(cx, t, mt.ty, unique_type_id, usage_site_span) |
|
|
|
} |
|
|
|
ty::ty_str => { |
|
|
|
vec_slice_metadata(cx, t, ty::mk_i8(), unique_type_id, usage_site_span) |
|
|
|
vec_slice_metadata(cx, t, ty::mk_u8(), unique_type_id, usage_site_span) |
|
|
|
} |
|
|
|
ty::ty_trait(box ty::TyTrait { |
|
|
|
def_id, |
|
|
|
ref substs, |
|
|
|
ref bounds |
|
|
|
}) => { |
|
|
|
ty::ty_trait(..) => { |
|
|
|
MetadataCreationResult::new( |
|
|
|
trait_metadata(cx, def_id, t, substs, |
|
|
|
ty::RegionTraitStore(ty::ReStatic, mt.mutbl), |
|
|
|
bounds, unique_type_id), |
|
|
|
false) |
|
|
|
trait_pointer_metadata(cx, t, unique_type_id), |
|
|
|
false) |
|
|
|
} |
|
|
|
_ => { |
|
|
|
let pointee = type_metadata(cx, mt.ty, usage_site_span); |
|
|
|
return_if_created_in_meantime!(); |
|
|
|
|
|
|
|
match debug_context(cx).type_map |
|
|
|
.borrow() |
|
|
|
.find_metadata_for_unique_id(unique_type_id) { |
|
|
|
Some(metadata) => return metadata, |
|
|
|
None => { /* proceed normally */ } |
|
|
|
}; |
|
|
|
|
|
|
|
MetadataCreationResult::new(pointer_type_metadata(cx, t, pointee), false) |
|
|
|
} |
|
|
|
} |
|
|
@@ -3150,7 +3116,8 @@ fn set_debug_location(cx: &CrateContext, debug_location: DebugLocation) { |
|
|
|
|
|
|
|
match debug_location { |
|
|
|
KnownLocation { scope, line, .. } => { |
|
|
|
let col = 0u; // Always set the column to zero like Clang and GCC |
|
|
|
// Always set the column to zero like Clang and GCC |
|
|
|
let col = UNKNOWN_COLUMN_NUMBER; |
|
|
|
debug!("setting debug location to {} {}", line, col); |
|
|
|
let elements = [C_i32(cx, line as i32), C_i32(cx, col as i32), |
|
|
|
scope, ptr::mut_null()]; |
|
|
@@ -3700,6 +3667,265 @@ fn populate_scope_map(cx: &CrateContext, |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//=----------------------------------------------------------------------------- |
|
|
|
// Type Names for Debug Info |
|
|
|
//=----------------------------------------------------------------------------- |
|
|
|
|
|
|
|
// Compute the name of the type as it should be stored in debuginfo. Does not do |
|
|
|
// any caching, i.e. calling the function twice with the same type will also do |
|
|
|
// the work twice. The `qualified` parameter only affects the first level of the |
|
|
|
// type name, further levels (i.e. type parameters) are always fully qualified. |
|
|
|
fn compute_debuginfo_type_name(cx: &CrateContext, |
|
|
|
t: ty::t, |
|
|
|
qualified: bool) |
|
|
|
-> String { |
|
|
|
let mut result = String::with_capacity(64); |
|
|
|
push_debuginfo_type_name(cx, t, qualified, &mut result); |
|
|
|
result |
|
|
|
} |
|
|
|
|
|
|
|
// Pushes the name of the type as it should be stored in debuginfo on the |
|
|
|
// `output` String. See also compute_debuginfo_type_name(). |
|
|
|
fn push_debuginfo_type_name(cx: &CrateContext, |
|
|
|
t: ty::t, |
|
|
|
qualified: bool, |
|
|
|
output:&mut String) { |
|
|
|
match ty::get(t).sty { |
|
|
|
ty::ty_nil => output.push_str("()"), |
|
|
|
ty::ty_bot => output.push_str("!"), |
|
|
|
ty::ty_bool => output.push_str("bool"), |
|
|
|
ty::ty_char => output.push_str("char"), |
|
|
|
ty::ty_str => output.push_str("str"), |
|
|
|
ty::ty_int(ast::TyI) => output.push_str("int"), |
|
|
|
ty::ty_int(ast::TyI8) => output.push_str("i8"), |
|
|
|
ty::ty_int(ast::TyI16) => output.push_str("i16"), |
|
|
|
ty::ty_int(ast::TyI32) => output.push_str("i32"), |
|
|
|
ty::ty_int(ast::TyI64) => output.push_str("i64"), |
|
|
|
ty::ty_uint(ast::TyU) => output.push_str("uint"), |
|
|
|
ty::ty_uint(ast::TyU8) => output.push_str("u8"), |
|
|
|
ty::ty_uint(ast::TyU16) => output.push_str("u16"), |
|
|
|
ty::ty_uint(ast::TyU32) => output.push_str("u32"), |
|
|
|
ty::ty_uint(ast::TyU64) => output.push_str("u64"), |
|
|
|
ty::ty_float(ast::TyF32) => output.push_str("f32"), |
|
|
|
ty::ty_float(ast::TyF64) => output.push_str("f64"), |
|
|
|
ty::ty_struct(def_id, ref substs) | |
|
|
|
ty::ty_enum(def_id, ref substs) => { |
|
|
|
push_item_name(cx, def_id, qualified, output); |
|
|
|
push_type_params(cx, substs, output); |
|
|
|
}, |
|
|
|
ty::ty_tup(ref component_types) => { |
|
|
|
output.push_char('('); |
|
|
|
for &component_type in component_types.iter() { |
|
|
|
push_debuginfo_type_name(cx, component_type, true, output); |
|
|
|
output.push_str(", "); |
|
|
|
} |
|
|
|
output.pop_char(); |
|
|
|
output.pop_char(); |
|
|
|
output.push_char(')'); |
|
|
|
}, |
|
|
|
ty::ty_uniq(inner_type) => { |
|
|
|
output.push_str("Box<"); |
|
|
|
push_debuginfo_type_name(cx, inner_type, true, output); |
|
|
|
output.push_char('>'); |
|
|
|
}, |
|
|
|
ty::ty_box(inner_type) => { |
|
|
|
output.push_char('@'); |
|
|
|
push_debuginfo_type_name(cx, inner_type, true, output); |
|
|
|
}, |
|
|
|
ty::ty_ptr(ty::mt { ty: inner_type, mutbl } ) => { |
|
|
|
output.push_char('*'); |
|
|
|
match mutbl { |
|
|
|
ast::MutImmutable => output.push_str("const "), |
|
|
|
ast::MutMutable => output.push_str("mut "), |
|
|
|
} |
|
|
|
|
|
|
|
push_debuginfo_type_name(cx, inner_type, true, output); |
|
|
|
}, |
|
|
|
ty::ty_rptr(_, ty::mt { ty: inner_type, mutbl }) => { |
|
|
|
output.push_char('&'); |
|
|
|
if mutbl == ast::MutMutable { |
|
|
|
output.push_str("mut "); |
|
|
|
} |
|
|
|
|
|
|
|
push_debuginfo_type_name(cx, inner_type, true, output); |
|
|
|
}, |
|
|
|
ty::ty_vec(ty::mt { ty: inner_type, .. }, optional_length) => { |
|
|
|
output.push_char('['); |
|
|
|
push_debuginfo_type_name(cx, inner_type, true, output); |
|
|
|
|
|
|
|
match optional_length { |
|
|
|
Some(len) => { |
|
|
|
output.push_str(format!(", ..{}", len).as_slice()); |
|
|
|
} |
|
|
|
None => { /* nothing to do */ } |
|
|
|
}; |
|
|
|
|
|
|
|
output.push_char(']'); |
|
|
|
}, |
|
|
|
ty::ty_trait(ref trait_data) => { |
|
|
|
push_item_name(cx, trait_data.def_id, false, output); |
|
|
|
push_type_params(cx, &trait_data.substs, output); |
|
|
|
}, |
|
|
|
ty::ty_bare_fn(ty::BareFnTy{ fn_style, abi, ref sig } ) => { |
|
|
|
if fn_style == ast::UnsafeFn { |
|
|
|
output.push_str("unsafe "); |
|
|
|
} |
|
|
|
|
|
|
|
if abi != ::syntax::abi::Rust { |
|
|
|
output.push_str("extern \""); |
|
|
|
output.push_str(abi.name()); |
|
|
|
output.push_str("\" "); |
|
|
|
} |
|
|
|
|
|
|
|
output.push_str("fn("); |
|
|
|
|
|
|
|
if sig.inputs.len() > 0 { |
|
|
|
for ¶meter_type in sig.inputs.iter() { |
|
|
|
push_debuginfo_type_name(cx, parameter_type, true, output); |
|
|
|
output.push_str(", "); |
|
|
|
} |
|
|
|
output.pop_char(); |
|
|
|
output.pop_char(); |
|
|
|
} |
|
|
|
|
|
|
|
if sig.variadic { |
|
|
|
if sig.inputs.len() > 0 { |
|
|
|
output.push_str(", ..."); |
|
|
|
} else { |
|
|
|
output.push_str("..."); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
output.push_char(')'); |
|
|
|
|
|
|
|
if !ty::type_is_nil(sig.output) { |
|
|
|
output.push_str(" -> "); |
|
|
|
push_debuginfo_type_name(cx, sig.output, true, output); |
|
|
|
} |
|
|
|
}, |
|
|
|
ty::ty_closure(box ty::ClosureTy { fn_style, |
|
|
|
onceness, |
|
|
|
store, |
|
|
|
ref sig, |
|
|
|
.. // omitting bounds ... |
|
|
|
}) => { |
|
|
|
if fn_style == ast::UnsafeFn { |
|
|
|
output.push_str("unsafe "); |
|
|
|
} |
|
|
|
|
|
|
|
if onceness == ast::Once { |
|
|
|
output.push_str("once "); |
|
|
|
} |
|
|
|
|
|
|
|
let param_list_closing_char; |
|
|
|
match store { |
|
|
|
ty::UniqTraitStore => { |
|
|
|
output.push_str("proc("); |
|
|
|
param_list_closing_char = ')'; |
|
|
|
} |
|
|
|
ty::RegionTraitStore(_, ast::MutMutable) => { |
|
|
|
output.push_str("&mut|"); |
|
|
|
param_list_closing_char = '|'; |
|
|
|
} |
|
|
|
ty::RegionTraitStore(_, ast::MutImmutable) => { |
|
|
|
output.push_str("&|"); |
|
|
|
param_list_closing_char = '|'; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
if sig.inputs.len() > 0 { |
|
|
|
for ¶meter_type in sig.inputs.iter() { |
|
|
|
push_debuginfo_type_name(cx, parameter_type, true, output); |
|
|
|
output.push_str(", "); |
|
|
|
} |
|
|
|
output.pop_char(); |
|
|
|
output.pop_char(); |
|
|
|
} |
|
|
|
|
|
|
|
if sig.variadic { |
|
|
|
if sig.inputs.len() > 0 { |
|
|
|
output.push_str(", ..."); |
|
|
|
} else { |
|
|
|
output.push_str("..."); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
output.push_char(param_list_closing_char); |
|
|
|
|
|
|
|
if !ty::type_is_nil(sig.output) { |
|
|
|
output.push_str(" -> "); |
|
|
|
push_debuginfo_type_name(cx, sig.output, true, output); |
|
|
|
} |
|
|
|
}, |
|
|
|
ty::ty_err | |
|
|
|
ty::ty_infer(_) | |
|
|
|
ty::ty_param(_) => { |
|
|
|
cx.sess().bug(format!("debuginfo: Trying to create type name for \ |
|
|
|
unexpected type: {}", ppaux::ty_to_str(cx.tcx(), t)).as_slice()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
fn push_item_name(cx: &CrateContext, |
|
|
|
def_id: ast::DefId, |
|
|
|
qualified: bool, |
|
|
|
output: &mut String) { |
|
|
|
ty::with_path(cx.tcx(), def_id, |mut path| { |
|
|
|
if qualified { |
|
|
|
if def_id.krate == ast::LOCAL_CRATE { |
|
|
|
output.push_str(crate_root_namespace(cx)); |
|
|
|
output.push_str("::"); |
|
|
|
} |
|
|
|
|
|
|
|
let mut path_element_count = 0u; |
|
|
|
for path_element in path { |
|
|
|
let name = token::get_name(path_element.name()); |
|
|
|
output.push_str(name.get()); |
|
|
|
output.push_str("::"); |
|
|
|
path_element_count += 1; |
|
|
|
} |
|
|
|
|
|
|
|
if path_element_count == 0 { |
|
|
|
cx.sess().bug("debuginfo: Encountered empty item path!"); |
|
|
|
} |
|
|
|
|
|
|
|
output.pop_char(); |
|
|
|
output.pop_char(); |
|
|
|
} else { |
|
|
|
let name = token::get_name(path.last() |
|
|
|
.expect("debuginfo: Empty item path?") |
|
|
|
.name()); |
|
|
|
output.push_str(name.get()); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
// Pushes the type parameters in the given `Substs` to the output string. |
|
|
|
// This ignores region parameters, since they can't reliably be |
|
|
|
// reconstructed for items from non-local crates. For local crates, this |
|
|
|
// would be possible but with inlining and LTO we have to use the least |
|
|
|
// common denominator - otherwise we would run into conflicts. |
|
|
|
fn push_type_params(cx: &CrateContext, |
|
|
|
substs: &subst::Substs, |
|
|
|
output: &mut String) { |
|
|
|
if substs.types.is_empty() { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
output.push_char('<'); |
|
|
|
|
|
|
|
for &type_parameter in substs.types.iter() { |
|
|
|
push_debuginfo_type_name(cx, type_parameter, true, output); |
|
|
|
output.push_str(", "); |
|
|
|
} |
|
|
|
|
|
|
|
output.pop_char(); |
|
|
|
output.pop_char(); |
|
|
|
|
|
|
|
output.push_char('>'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//=----------------------------------------------------------------------------- |
|
|
|
// Namespace Handling |
|
|
|
//=----------------------------------------------------------------------------- |
|
|
@@ -3731,14 +3957,15 @@ impl NamespaceTreeNode { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
fn crate_root_namespace<'a>(cx: &'a CrateContext) -> &'a str { |
|
|
|
cx.link_meta.crateid.name.as_slice() |
|
|
|
} |
|
|
|
|
|
|
|
fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTreeNode> { |
|
|
|
ty::with_path(cx.tcx(), def_id, |path| { |
|
|
|
// prepend crate name if not already present |
|
|
|
let krate = if def_id.krate == ast::LOCAL_CRATE { |
|
|
|
let crate_namespace_ident = token::str_to_ident(cx.link_meta |
|
|
|
.crateid |
|
|
|
.name |
|
|
|
.as_slice()); |
|
|
|
let crate_namespace_ident = token::str_to_ident(crate_root_namespace(cx)); |
|
|
|
Some(ast_map::PathMod(crate_namespace_ident.name)) |
|
|
|
} else { |
|
|
|
None |
|
|
|