Auto merge of #27689 - dotdash:die_odr, r=michaelwoerister

When using a generic enum type that was defined in an external crate,
our debuginfo currently claims that the concrete type (e.g. Option<i32>)
was defined in the current crate, where it was first used.

This means that if there are multiple crates that all use, for example,
Option<i32> values, they'll have conflicting debuginfo, each crate
claiming to have defined that type. This doesn't cause problems in
regular builds, but with LTO enabled, LLVM complains because it tries to
merge the debuginfo for those types and sees the ODR violations.

Since I couldn't find a way to get the file info for the external crate
that actually defined the enum, I'm working around the issue by using
"<unknown>" as the file for enum types. We'll want to re-visit and fix
this later, but this at least this fixes the ICE. And with the file
being unknown instead of wrong, the debuginfo isn't really worse than
before either.

Fixes #26447
This commit is contained in:
bors 2015-08-16 14:50:52 +00:00
commit 2f60268f54

View File

@ -62,8 +62,8 @@
pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
// ptr::null() doesn't work :(
const UNKNOWN_FILE_METADATA: DIFile = (0 as DIFile);
const UNKNOWN_SCOPE_METADATA: DIScope = (0 as DIScope);
const NO_FILE_METADATA: DIFile = (0 as DIFile);
const NO_SCOPE_METADATA: DIScope = (0 as DIScope);
const FLAGS_NONE: c_uint = 0;
@ -565,7 +565,7 @@ fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
&slice_type_name[..],
unique_type_id,
&member_descriptions,
UNKNOWN_SCOPE_METADATA,
NO_SCOPE_METADATA,
file_metadata,
span);
return MetadataCreationResult::new(metadata, false);
@ -610,7 +610,7 @@ fn subroutine_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
unsafe {
llvm::LLVMDIBuilderCreateSubroutineType(
DIB(cx),
UNKNOWN_FILE_METADATA,
NO_FILE_METADATA,
create_DIArray(DIB(cx), &signature_metadata[..]))
},
false);
@ -654,7 +654,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
unique_type_id,
&[],
containing_scope,
UNKNOWN_FILE_METADATA,
NO_FILE_METADATA,
codemap::DUMMY_SP)
}
@ -850,13 +850,6 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
}
pub fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
match debug_context(cx).created_files.borrow().get(full_path) {
Some(file_metadata) => return *file_metadata,
None => ()
}
debug!("file_metadata: {}", full_path);
// FIXME (#9639): This needs to handle non-utf8 paths
let work_dir = cx.sess().working_dir.to_str().unwrap();
let file_name =
@ -866,6 +859,24 @@ pub fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
full_path
};
file_metadata_(cx, full_path, file_name, &work_dir)
}
pub fn unknown_file_metadata(cx: &CrateContext) -> DIFile {
// Regular filenames should not be empty, so we abuse an empty name as the
// key for the special unknown file metadata
file_metadata_(cx, "", "<unknown>", "")
}
fn file_metadata_(cx: &CrateContext, key: &str, file_name: &str, work_dir: &str) -> DIFile {
match debug_context(cx).created_files.borrow().get(key) {
Some(file_metadata) => return *file_metadata,
None => ()
}
debug!("file_metadata: file_name: {}, work_dir: {}", file_name, work_dir);
let file_name = CString::new(file_name).unwrap();
let work_dir = CString::new(work_dir).unwrap();
let file_metadata = unsafe {
@ -874,8 +885,8 @@ pub fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
};
let mut created_files = debug_context(cx).created_files.borrow_mut();
created_files.insert(full_path.to_string(), file_metadata);
return file_metadata;
created_files.insert(key.to_string(), file_metadata);
file_metadata
}
/// Finds the scope metadata node for the given AST node.
@ -1226,7 +1237,7 @@ fn prepare_tuple_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
tuple_llvm_type,
&tuple_name[..],
unique_type_id,
UNKNOWN_SCOPE_METADATA),
NO_SCOPE_METADATA),
tuple_llvm_type,
TupleMDF(TupleMemberDescriptionFactory {
component_types: component_types.to_vec(),
@ -1569,9 +1580,14 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-> RecursiveTypeDescription<'tcx> {
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);
let file_metadata = file_metadata(cx, &loc.file.name);
let (containing_scope, _) = get_namespace_and_span_for_item(cx, enum_def_id);
// FIXME: This should emit actual file metadata for the enum, but we
// currently can't get the necessary information when it comes to types
// imported from other crates. Formerly we violated the ODR when performing
// LTO because we emitted debuginfo for the same type with varying file
// metadata, so as a workaround we pretend that the type comes from
// <unknown>
let file_metadata = unknown_file_metadata(cx);
let variants = &enum_type.ty_adt_def().unwrap().variants;
@ -1612,7 +1628,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
DIB(cx),
containing_scope,
name.as_ptr(),
UNKNOWN_FILE_METADATA,
NO_FILE_METADATA,
UNKNOWN_LINE_NUMBER,
bytes_to_bits(discriminant_size),
bytes_to_bits(discriminant_align),
@ -1758,7 +1774,7 @@ fn set_members_of_composite_type(cx: &CrateContext,
DIB(cx),
composite_type_metadata,
member_name.as_ptr(),
UNKNOWN_FILE_METADATA,
NO_FILE_METADATA,
UNKNOWN_LINE_NUMBER,
bytes_to_bits(member_size),
bytes_to_bits(member_align),
@ -1801,7 +1817,7 @@ fn create_struct_stub(cx: &CrateContext,
DIB(cx),
containing_scope,
name.as_ptr(),
UNKNOWN_FILE_METADATA,
NO_FILE_METADATA,
UNKNOWN_LINE_NUMBER,
bytes_to_bits(struct_size),
bytes_to_bits(struct_align),
@ -1862,7 +1878,7 @@ pub fn create_global_var_metadata(cx: &CrateContext,
let loc = span_start(cx, span);
(file_metadata(cx, &loc.file.name), loc.line as c_uint)
} else {
(UNKNOWN_FILE_METADATA, UNKNOWN_LINE_NUMBER)
(NO_FILE_METADATA, UNKNOWN_LINE_NUMBER)
};
let is_local_to_unit = is_node_local_to_unit(cx, node_id);