mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-01 19:23:50 +00:00
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.
This commit is contained in:
commit
d59f66d9b8
@ -18,6 +18,7 @@ use super::utils::{debug_context, DIB, span_start, bytes_to_bits, size_and_align
|
||||
use super::namespace::mangled_name_of_item;
|
||||
use super::type_names::compute_debuginfo_type_name;
|
||||
use super::{CrateDebugContext};
|
||||
use abi;
|
||||
use context::SharedCrateContext;
|
||||
|
||||
use llvm::{self, ValueRef};
|
||||
@ -438,11 +439,38 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
let trait_llvm_type = type_of::type_of(cx, trait_object_type);
|
||||
let file_metadata = unknown_file_metadata(cx);
|
||||
|
||||
|
||||
let ptr_type = cx.tcx().mk_ptr(ty::TypeAndMut {
|
||||
ty: cx.tcx().types.u8,
|
||||
mutbl: hir::MutImmutable
|
||||
});
|
||||
let ptr_type_metadata = type_metadata(cx, ptr_type, syntax_pos::DUMMY_SP);
|
||||
let llvm_type = type_of::type_of(cx, ptr_type);
|
||||
|
||||
assert_eq!(abi::FAT_PTR_ADDR, 0);
|
||||
assert_eq!(abi::FAT_PTR_EXTRA, 1);
|
||||
let member_descriptions = [
|
||||
MemberDescription {
|
||||
name: "pointer".to_string(),
|
||||
llvm_type: llvm_type,
|
||||
type_metadata: ptr_type_metadata,
|
||||
offset: ComputedMemberOffset,
|
||||
flags: DIFlags::FlagArtificial,
|
||||
},
|
||||
MemberDescription {
|
||||
name: "vtable".to_string(),
|
||||
llvm_type: llvm_type,
|
||||
type_metadata: ptr_type_metadata,
|
||||
offset: ComputedMemberOffset,
|
||||
flags: DIFlags::FlagArtificial,
|
||||
},
|
||||
];
|
||||
|
||||
composite_type_metadata(cx,
|
||||
trait_llvm_type,
|
||||
&trait_type_name[..],
|
||||
unique_type_id,
|
||||
&[],
|
||||
&member_descriptions,
|
||||
containing_scope,
|
||||
file_metadata,
|
||||
syntax_pos::DUMMY_SP)
|
||||
@ -1858,3 +1886,65 @@ pub fn extend_scope_to_file(ccx: &CrateContext,
|
||||
file_metadata)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates debug information for the given vtable, which is for the
|
||||
/// given type.
|
||||
///
|
||||
/// Adds the created metadata nodes directly to the crate's IR.
|
||||
pub fn create_vtable_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
ty: ty::Ty<'tcx>,
|
||||
vtable: ValueRef) {
|
||||
if cx.dbg_cx().is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
let type_metadata = type_metadata(cx, ty, syntax_pos::DUMMY_SP);
|
||||
let llvm_vtable_type = Type::vtable_ptr(cx).element_type();
|
||||
let (struct_size, struct_align) = size_and_align_of(cx, llvm_vtable_type);
|
||||
|
||||
unsafe {
|
||||
// LLVMRustDIBuilderCreateStructType() wants an empty array. A null
|
||||
// pointer will lead to hard to trace and debug LLVM assertions
|
||||
// later on in llvm/lib/IR/Value.cpp.
|
||||
let empty_array = create_DIArray(DIB(cx), &[]);
|
||||
|
||||
let name = CString::new("vtable").unwrap();
|
||||
|
||||
// Create a new one each time. We don't want metadata caching
|
||||
// here, because each vtable will refer to a unique containing
|
||||
// type.
|
||||
let vtable_type = llvm::LLVMRustDIBuilderCreateStructType(
|
||||
DIB(cx),
|
||||
NO_SCOPE_METADATA,
|
||||
name.as_ptr(),
|
||||
unknown_file_metadata(cx),
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
bytes_to_bits(struct_size),
|
||||
bytes_to_bits(struct_align),
|
||||
DIFlags::FlagArtificial,
|
||||
ptr::null_mut(),
|
||||
empty_array,
|
||||
0,
|
||||
type_metadata,
|
||||
name.as_ptr()
|
||||
);
|
||||
|
||||
llvm::LLVMRustDIBuilderCreateStaticVariable(DIB(cx),
|
||||
NO_SCOPE_METADATA,
|
||||
name.as_ptr(),
|
||||
// LLVM 3.9
|
||||
// doesn't accept
|
||||
// null here, so
|
||||
// pass the name
|
||||
// as the linkage
|
||||
// name.
|
||||
name.as_ptr(),
|
||||
unknown_file_metadata(cx),
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
vtable_type,
|
||||
true,
|
||||
vtable,
|
||||
ptr::null_mut(),
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ mod source_loc;
|
||||
pub use self::create_scope_map::{create_mir_scopes, MirDebugScope};
|
||||
pub use self::source_loc::start_emitting_source_locations;
|
||||
pub use self::metadata::create_global_var_metadata;
|
||||
pub use self::metadata::create_vtable_metadata;
|
||||
pub use self::metadata::extend_scope_to_file;
|
||||
pub use self::source_loc::set_source_location;
|
||||
|
||||
|
@ -18,6 +18,7 @@ use monomorphize;
|
||||
use type_::Type;
|
||||
use value::Value;
|
||||
use rustc::ty::{self, Ty};
|
||||
use debuginfo;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct VirtualIndex(usize);
|
||||
@ -99,6 +100,8 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
let align = machine::llalign_of_pref(ccx, val_ty(vtable_const));
|
||||
let vtable = consts::addr_of(ccx, vtable_const, align, "vtable");
|
||||
|
||||
debuginfo::create_vtable_metadata(ccx, ty, vtable);
|
||||
|
||||
ccx.vtables().borrow_mut().insert((ty, trait_ref), vtable);
|
||||
vtable
|
||||
}
|
||||
|
2
src/llvm
2
src/llvm
@ -1 +1 @@
|
||||
Subproject commit b48f77c5ed570001957408f4adeec88ae010c4d9
|
||||
Subproject commit 51f104bf1cc6c3a588a11c90a3b4a4a18ee080ac
|
33
src/test/codegen/vtabletype.rs
Normal file
33
src/test/codegen/vtabletype.rs
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// This test depends on a patch that was committed to upstream LLVM
|
||||
// after 5.0, then backported to the Rust LLVM fork.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
// ignore-windows
|
||||
// ignore-macos
|
||||
// min-system-llvm-version 5.1
|
||||
|
||||
// compile-flags: -g -C no-prepopulate-passes
|
||||
|
||||
// CHECK-LABEL: @main
|
||||
// CHECK: {{.*}}DICompositeType{{.*}}name: "vtable",{{.*}}vtableHolder:{{.*}}
|
||||
|
||||
pub trait T {
|
||||
}
|
||||
|
||||
impl T for f64 {
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let d = 23.0f64;
|
||||
let td = &d as &T;
|
||||
}
|
@ -150,6 +150,14 @@ impl EarlyProps {
|
||||
// Ignore if actual version is smaller the minimum required
|
||||
// version
|
||||
&actual_version[..] < min_version
|
||||
} else if line.starts_with("min-system-llvm-version") {
|
||||
let min_version = line.trim_right()
|
||||
.rsplit(' ')
|
||||
.next()
|
||||
.expect("Malformed llvm version directive");
|
||||
// Ignore if using system LLVM and actual version
|
||||
// is smaller the minimum required version
|
||||
!(config.system_llvm && &actual_version[..] < min_version)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user