Skip to content

Commit d17d2dd

Browse files
committed
Workaround ODR violations in enum debuginfo
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 rust-lang#26447
1 parent 58b0aa5 commit d17d2dd

File tree

1 file changed

+38
-22
lines changed

1 file changed

+38
-22
lines changed

src/librustc_trans/trans/debuginfo/metadata.rs

+38-22
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ pub const UNKNOWN_LINE_NUMBER: c_uint = 0;
6363
pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
6464

6565
// ptr::null() doesn't work :(
66-
const UNKNOWN_FILE_METADATA: DIFile = (0 as DIFile);
67-
const UNKNOWN_SCOPE_METADATA: DIScope = (0 as DIScope);
66+
const NO_FILE_METADATA: DIFile = (0 as DIFile);
67+
const NO_SCOPE_METADATA: DIScope = (0 as DIScope);
6868

6969
const FLAGS_NONE: c_uint = 0;
7070

@@ -566,7 +566,7 @@ fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
566566
&slice_type_name[..],
567567
unique_type_id,
568568
&member_descriptions,
569-
UNKNOWN_SCOPE_METADATA,
569+
NO_SCOPE_METADATA,
570570
file_metadata,
571571
span);
572572
return MetadataCreationResult::new(metadata, false);
@@ -611,7 +611,7 @@ fn subroutine_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
611611
unsafe {
612612
llvm::LLVMDIBuilderCreateSubroutineType(
613613
DIB(cx),
614-
UNKNOWN_FILE_METADATA,
614+
NO_FILE_METADATA,
615615
create_DIArray(DIB(cx), &signature_metadata[..]))
616616
},
617617
false);
@@ -655,7 +655,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
655655
unique_type_id,
656656
&[],
657657
containing_scope,
658-
UNKNOWN_FILE_METADATA,
658+
NO_FILE_METADATA,
659659
codemap::DUMMY_SP)
660660
}
661661

@@ -851,13 +851,6 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
851851
}
852852

853853
pub fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
854-
match debug_context(cx).created_files.borrow().get(full_path) {
855-
Some(file_metadata) => return *file_metadata,
856-
None => ()
857-
}
858-
859-
debug!("file_metadata: {}", full_path);
860-
861854
// FIXME (#9639): This needs to handle non-utf8 paths
862855
let work_dir = cx.sess().working_dir.to_str().unwrap();
863856
let file_name =
@@ -867,6 +860,24 @@ pub fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
867860
full_path
868861
};
869862

863+
file_metadata_(cx, full_path, file_name, &work_dir)
864+
}
865+
866+
pub fn unknown_file_metadata(cx: &CrateContext) -> DIFile {
867+
// Regular filenames should not be empty, so we abuse an empty name as the
868+
// key for the special unknown file metadata
869+
file_metadata_(cx, "", "<unknown>", "")
870+
871+
}
872+
873+
fn file_metadata_(cx: &CrateContext, key: &str, file_name: &str, work_dir: &str) -> DIFile {
874+
match debug_context(cx).created_files.borrow().get(key) {
875+
Some(file_metadata) => return *file_metadata,
876+
None => ()
877+
}
878+
879+
debug!("file_metadata: file_name: {}, work_dir: {}", file_name, work_dir);
880+
870881
let file_name = CString::new(file_name).unwrap();
871882
let work_dir = CString::new(work_dir).unwrap();
872883
let file_metadata = unsafe {
@@ -875,8 +886,8 @@ pub fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
875886
};
876887

877888
let mut created_files = debug_context(cx).created_files.borrow_mut();
878-
created_files.insert(full_path.to_string(), file_metadata);
879-
return file_metadata;
889+
created_files.insert(key.to_string(), file_metadata);
890+
file_metadata
880891
}
881892

882893
/// Finds the scope metadata node for the given AST node.
@@ -1227,7 +1238,7 @@ fn prepare_tuple_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
12271238
tuple_llvm_type,
12281239
&tuple_name[..],
12291240
unique_type_id,
1230-
UNKNOWN_SCOPE_METADATA),
1241+
NO_SCOPE_METADATA),
12311242
tuple_llvm_type,
12321243
TupleMDF(TupleMemberDescriptionFactory {
12331244
component_types: component_types.to_vec(),
@@ -1570,9 +1581,14 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
15701581
-> RecursiveTypeDescription<'tcx> {
15711582
let enum_name = compute_debuginfo_type_name(cx, enum_type, false);
15721583

1573-
let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, enum_def_id);
1574-
let loc = span_start(cx, definition_span);
1575-
let file_metadata = file_metadata(cx, &loc.file.name);
1584+
let (containing_scope, _) = get_namespace_and_span_for_item(cx, enum_def_id);
1585+
// FIXME: This should emit actual file metadata for the enum, but we
1586+
// currently can't get the necessary information when it comes to types
1587+
// imported from other crates. Formerly we violated the ODR when performing
1588+
// LTO because we emitted debuginfo for the same type with varying file
1589+
// metadata, so as a workaround we pretend that the type comes from
1590+
// <unknown>
1591+
let file_metadata = unknown_file_metadata(cx);
15761592

15771593
let variants = &enum_type.ty_adt_def().unwrap().variants;
15781594

@@ -1613,7 +1629,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
16131629
DIB(cx),
16141630
containing_scope,
16151631
name.as_ptr(),
1616-
UNKNOWN_FILE_METADATA,
1632+
NO_FILE_METADATA,
16171633
UNKNOWN_LINE_NUMBER,
16181634
bytes_to_bits(discriminant_size),
16191635
bytes_to_bits(discriminant_align),
@@ -1765,7 +1781,7 @@ fn set_members_of_composite_type(cx: &CrateContext,
17651781
DIB(cx),
17661782
composite_type_metadata,
17671783
member_name.as_ptr(),
1768-
UNKNOWN_FILE_METADATA,
1784+
NO_FILE_METADATA,
17691785
UNKNOWN_LINE_NUMBER,
17701786
bytes_to_bits(member_size),
17711787
bytes_to_bits(member_align),
@@ -1808,7 +1824,7 @@ fn create_struct_stub(cx: &CrateContext,
18081824
DIB(cx),
18091825
containing_scope,
18101826
name.as_ptr(),
1811-
UNKNOWN_FILE_METADATA,
1827+
NO_FILE_METADATA,
18121828
UNKNOWN_LINE_NUMBER,
18131829
bytes_to_bits(struct_size),
18141830
bytes_to_bits(struct_align),
@@ -1869,7 +1885,7 @@ pub fn create_global_var_metadata(cx: &CrateContext,
18691885
let loc = span_start(cx, span);
18701886
(file_metadata(cx, &loc.file.name), loc.line as c_uint)
18711887
} else {
1872-
(UNKNOWN_FILE_METADATA, UNKNOWN_LINE_NUMBER)
1888+
(NO_FILE_METADATA, UNKNOWN_LINE_NUMBER)
18731889
};
18741890

18751891
let is_local_to_unit = is_node_local_to_unit(cx, node_id);

0 commit comments

Comments
 (0)