Skip to content

Commit d59f66d

Browse files
committed
Auto merge of #45897 - tromey:trait-object-debug, r=michaelwoerister
Trait object debug This enables better debugging of trait objects. See the individual commits for explanations. This required an LLVM bump.
2 parents d0f8e29 + ae4cc60 commit d59f66d

File tree

6 files changed

+137
-2
lines changed

6 files changed

+137
-2
lines changed

src/librustc_trans/debuginfo/metadata.rs

+91-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use super::utils::{debug_context, DIB, span_start, bytes_to_bits, size_and_align
1818
use super::namespace::mangled_name_of_item;
1919
use super::type_names::compute_debuginfo_type_name;
2020
use super::{CrateDebugContext};
21+
use abi;
2122
use context::SharedCrateContext;
2223

2324
use llvm::{self, ValueRef};
@@ -438,11 +439,38 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
438439
let trait_llvm_type = type_of::type_of(cx, trait_object_type);
439440
let file_metadata = unknown_file_metadata(cx);
440441

442+
443+
let ptr_type = cx.tcx().mk_ptr(ty::TypeAndMut {
444+
ty: cx.tcx().types.u8,
445+
mutbl: hir::MutImmutable
446+
});
447+
let ptr_type_metadata = type_metadata(cx, ptr_type, syntax_pos::DUMMY_SP);
448+
let llvm_type = type_of::type_of(cx, ptr_type);
449+
450+
assert_eq!(abi::FAT_PTR_ADDR, 0);
451+
assert_eq!(abi::FAT_PTR_EXTRA, 1);
452+
let member_descriptions = [
453+
MemberDescription {
454+
name: "pointer".to_string(),
455+
llvm_type: llvm_type,
456+
type_metadata: ptr_type_metadata,
457+
offset: ComputedMemberOffset,
458+
flags: DIFlags::FlagArtificial,
459+
},
460+
MemberDescription {
461+
name: "vtable".to_string(),
462+
llvm_type: llvm_type,
463+
type_metadata: ptr_type_metadata,
464+
offset: ComputedMemberOffset,
465+
flags: DIFlags::FlagArtificial,
466+
},
467+
];
468+
441469
composite_type_metadata(cx,
442470
trait_llvm_type,
443471
&trait_type_name[..],
444472
unique_type_id,
445-
&[],
473+
&member_descriptions,
446474
containing_scope,
447475
file_metadata,
448476
syntax_pos::DUMMY_SP)
@@ -1858,3 +1886,65 @@ pub fn extend_scope_to_file(ccx: &CrateContext,
18581886
file_metadata)
18591887
}
18601888
}
1889+
1890+
/// Creates debug information for the given vtable, which is for the
1891+
/// given type.
1892+
///
1893+
/// Adds the created metadata nodes directly to the crate's IR.
1894+
pub fn create_vtable_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
1895+
ty: ty::Ty<'tcx>,
1896+
vtable: ValueRef) {
1897+
if cx.dbg_cx().is_none() {
1898+
return;
1899+
}
1900+
1901+
let type_metadata = type_metadata(cx, ty, syntax_pos::DUMMY_SP);
1902+
let llvm_vtable_type = Type::vtable_ptr(cx).element_type();
1903+
let (struct_size, struct_align) = size_and_align_of(cx, llvm_vtable_type);
1904+
1905+
unsafe {
1906+
// LLVMRustDIBuilderCreateStructType() wants an empty array. A null
1907+
// pointer will lead to hard to trace and debug LLVM assertions
1908+
// later on in llvm/lib/IR/Value.cpp.
1909+
let empty_array = create_DIArray(DIB(cx), &[]);
1910+
1911+
let name = CString::new("vtable").unwrap();
1912+
1913+
// Create a new one each time. We don't want metadata caching
1914+
// here, because each vtable will refer to a unique containing
1915+
// type.
1916+
let vtable_type = llvm::LLVMRustDIBuilderCreateStructType(
1917+
DIB(cx),
1918+
NO_SCOPE_METADATA,
1919+
name.as_ptr(),
1920+
unknown_file_metadata(cx),
1921+
UNKNOWN_LINE_NUMBER,
1922+
bytes_to_bits(struct_size),
1923+
bytes_to_bits(struct_align),
1924+
DIFlags::FlagArtificial,
1925+
ptr::null_mut(),
1926+
empty_array,
1927+
0,
1928+
type_metadata,
1929+
name.as_ptr()
1930+
);
1931+
1932+
llvm::LLVMRustDIBuilderCreateStaticVariable(DIB(cx),
1933+
NO_SCOPE_METADATA,
1934+
name.as_ptr(),
1935+
// LLVM 3.9
1936+
// doesn't accept
1937+
// null here, so
1938+
// pass the name
1939+
// as the linkage
1940+
// name.
1941+
name.as_ptr(),
1942+
unknown_file_metadata(cx),
1943+
UNKNOWN_LINE_NUMBER,
1944+
vtable_type,
1945+
true,
1946+
vtable,
1947+
ptr::null_mut(),
1948+
0);
1949+
}
1950+
}

src/librustc_trans/debuginfo/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ mod source_loc;
5656
pub use self::create_scope_map::{create_mir_scopes, MirDebugScope};
5757
pub use self::source_loc::start_emitting_source_locations;
5858
pub use self::metadata::create_global_var_metadata;
59+
pub use self::metadata::create_vtable_metadata;
5960
pub use self::metadata::extend_scope_to_file;
6061
pub use self::source_loc::set_source_location;
6162

src/librustc_trans/meth.rs

+3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use monomorphize;
1818
use type_::Type;
1919
use value::Value;
2020
use rustc::ty::{self, Ty};
21+
use debuginfo;
2122

2223
#[derive(Copy, Clone, Debug)]
2324
pub struct VirtualIndex(usize);
@@ -99,6 +100,8 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
99100
let align = machine::llalign_of_pref(ccx, val_ty(vtable_const));
100101
let vtable = consts::addr_of(ccx, vtable_const, align, "vtable");
101102

103+
debuginfo::create_vtable_metadata(ccx, ty, vtable);
104+
102105
ccx.vtables().borrow_mut().insert((ty, trait_ref), vtable);
103106
vtable
104107
}

src/test/codegen/vtabletype.rs

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// This test depends on a patch that was committed to upstream LLVM
12+
// after 5.0, then backported to the Rust LLVM fork.
13+
14+
// ignore-tidy-linelength
15+
// ignore-windows
16+
// ignore-macos
17+
// min-system-llvm-version 5.1
18+
19+
// compile-flags: -g -C no-prepopulate-passes
20+
21+
// CHECK-LABEL: @main
22+
// CHECK: {{.*}}DICompositeType{{.*}}name: "vtable",{{.*}}vtableHolder:{{.*}}
23+
24+
pub trait T {
25+
}
26+
27+
impl T for f64 {
28+
}
29+
30+
pub fn main() {
31+
let d = 23.0f64;
32+
let td = &d as &T;
33+
}

src/tools/compiletest/src/header.rs

+8
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,14 @@ impl EarlyProps {
150150
// Ignore if actual version is smaller the minimum required
151151
// version
152152
&actual_version[..] < min_version
153+
} else if line.starts_with("min-system-llvm-version") {
154+
let min_version = line.trim_right()
155+
.rsplit(' ')
156+
.next()
157+
.expect("Malformed llvm version directive");
158+
// Ignore if using system LLVM and actual version
159+
// is smaller the minimum required version
160+
!(config.system_llvm && &actual_version[..] < min_version)
153161
} else {
154162
false
155163
}

0 commit comments

Comments
 (0)