Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

debuginfo: Fixes and improvements for #12840, #12886, and #13213 #13441

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 79 additions & 32 deletions src/librustc/middle/trans/debuginfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ use driver::session::{FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
use lib::llvm::llvm;
use lib::llvm::{ModuleRef, ContextRef, ValueRef};
use lib::llvm::debuginfo::*;
use metadata::csearch;
use middle::trans::adt;
use middle::trans::common::*;
use middle::trans::datum::{Datum, Lvalue};
Expand Down Expand Up @@ -178,6 +179,7 @@ pub struct CrateDebugContext {
current_debug_location: Cell<DebugLocation>,
created_files: RefCell<HashMap<~str, DIFile>>,
created_types: RefCell<HashMap<uint, DIType>>,
created_enum_disr_types: RefCell<HashMap<ast::DefId, DIType>>,
namespace_map: RefCell<HashMap<Vec<ast::Name> , @NamespaceTreeNode>>,
// This collection is used to assert that composite types (structs, enums, ...) have their
// members only set once:
Expand All @@ -196,6 +198,7 @@ impl CrateDebugContext {
current_debug_location: Cell::new(UnknownLocation),
created_files: RefCell::new(HashMap::new()),
created_types: RefCell::new(HashMap::new()),
created_enum_disr_types: RefCell::new(HashMap::new()),
namespace_map: RefCell::new(HashMap::new()),
composite_types_completed: RefCell::new(HashSet::new()),
};
Expand Down Expand Up @@ -290,6 +293,13 @@ pub fn create_global_var_metadata(cx: &CrateContext,
return;
}

// Don't create debuginfo for globals inlined from other crates. The other crate should already
// contain debuginfo for it. More importantly, the global might not even exist in un-inlined
// form anywhere which would lead to a linker errors.
if cx.external_srcs.borrow().contains_key(&node_id) {
return;
}

let var_item = cx.tcx.map.get(node_id);

let (ident, span) = match var_item {
Expand Down Expand Up @@ -533,21 +543,26 @@ pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
pub fn set_source_location(fcx: &FunctionContext,
node_id: ast::NodeId,
span: Span) {
if fn_should_be_ignored(fcx) {
return;
}

let cx = fcx.ccx;
match fcx.debug_context {
DebugInfoDisabled => return,
FunctionWithoutDebugInfo => {
set_debug_location(fcx.ccx, UnknownLocation);
return;
}
FunctionDebugContext(~ref function_debug_context) => {
let cx = fcx.ccx;

debug!("set_source_location: {}", cx.sess().codemap().span_to_str(span));
debug!("set_source_location: {}", cx.sess().codemap().span_to_str(span));

if fcx.debug_context.get_ref(cx, span).source_locations_enabled.get() {
let loc = span_start(cx, span);
let scope = scope_metadata(fcx, node_id, span);
if function_debug_context.source_locations_enabled.get() {
let loc = span_start(cx, span);
let scope = scope_metadata(fcx, node_id, span);

set_debug_location(cx, DebugLocation::new(scope, loc.line, loc.col.to_uint()));
} else {
set_debug_location(cx, UnknownLocation);
set_debug_location(cx, DebugLocation::new(scope, loc.line, loc.col.to_uint()));
} else {
set_debug_location(cx, UnknownLocation);
}
}
}
}

Expand Down Expand Up @@ -590,6 +605,10 @@ pub fn create_function_debug_context(cx: &CrateContext,
return DebugInfoDisabled;
}

// Clear the debug location so we don't assign them in the function prelude. Do this here
// already, in case we do an early exit from this function.
set_debug_location(cx, UnknownLocation);

if fn_ast_id == -1 {
return FunctionWithoutDebugInfo;
}
Expand Down Expand Up @@ -740,9 +759,6 @@ pub fn create_function_debug_context(cx: &CrateContext,
fn_metadata,
&mut *fn_debug_context.scope_map.borrow_mut());

// Clear the debug location so we don't assign them in the function prelude
set_debug_location(cx, UnknownLocation);

return FunctionDebugContext(fn_debug_context);

fn get_function_signature(cx: &CrateContext,
Expand Down Expand Up @@ -1536,24 +1552,45 @@ fn prepare_enum_metadata(cx: &CrateContext,
.collect();

let discriminant_type_metadata = |inttype| {
let discriminant_llvm_type = adt::ll_inttype(cx, inttype);
let (discriminant_size, discriminant_align) = size_and_align_of(cx, discriminant_llvm_type);
let discriminant_base_type_metadata = type_metadata(cx, adt::ty_of_inttype(inttype),
codemap::DUMMY_SP);
enum_name.with_c_str(|enum_name| {
unsafe {
llvm::LLVMDIBuilderCreateEnumerationType(
DIB(cx),
containing_scope,
enum_name,
file_metadata,
loc.line as c_uint,
bytes_to_bits(discriminant_size),
bytes_to_bits(discriminant_align),
create_DIArray(DIB(cx), enumerators_metadata.as_slice()),
discriminant_base_type_metadata)
// We can reuse the type of the discriminant for all monomorphized instances of an enum
// because it doesn't depend on any type parameters. The def_id, uniquely identifying the
// enum's polytype acts as key in this cache.
let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types
.borrow()
.find_copy(&enum_def_id);
match cached_discriminant_type_metadata {
Some(discriminant_type_metadata) => discriminant_type_metadata,
None => {
let discriminant_llvm_type = adt::ll_inttype(cx, inttype);
let (discriminant_size, discriminant_align) =
size_and_align_of(cx, discriminant_llvm_type);
let discriminant_base_type_metadata = type_metadata(cx,
adt::ty_of_inttype(inttype),
codemap::DUMMY_SP);
let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);

let discriminant_type_metadata = discriminant_name.get().with_c_str(|name| {
unsafe {
llvm::LLVMDIBuilderCreateEnumerationType(
DIB(cx),
containing_scope,
name,
file_metadata,
loc.line as c_uint,
bytes_to_bits(discriminant_size),
bytes_to_bits(discriminant_align),
create_DIArray(DIB(cx), enumerators_metadata.as_slice()),
discriminant_base_type_metadata)
}
});

debug_context(cx).created_enum_disr_types
.borrow_mut()
.insert(enum_def_id, discriminant_type_metadata);

discriminant_type_metadata
}
})
}
};

let type_rep = adt::represent_type(cx, enum_type);
Expand Down Expand Up @@ -1642,6 +1679,16 @@ fn prepare_enum_metadata(cx: &CrateContext,
}
}
};

fn get_enum_discriminant_name(cx: &CrateContext, def_id: ast::DefId) -> token::InternedString {
let name = if def_id.krate == ast::LOCAL_CRATE {
cx.tcx.map.get_path_elem(def_id.node).name()
} else {
csearch::get_item_path(&cx.tcx, def_id).last().unwrap().name()
};

token::get_name(name)
}
}

enum MemberOffset {
Expand Down
27 changes: 27 additions & 0 deletions src/test/auxiliary/issue13213aux.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2013-2014 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.

#![crate_type = "lib"]
// compile-flags:-g

pub use private::P;

pub struct S {
p: P,
}

mod private {
pub struct P {
p: i32,
}
pub static THREE: P = P { p: 3 };
}

pub static A: S = S { p: private::THREE };
26 changes: 26 additions & 0 deletions src/test/debug-info/issue13213.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2013-2014 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.

// ignore-android: FIXME(#10381)

// aux-build:issue13213aux.rs
extern crate issue13213aux;

// compile-flags:-g

// This tests make sure that we get no linker error when using a completely inlined static. Some
// statics that are marked with AvailableExternallyLinkage in the importing crate, may actually not
// be available because they have been optimized out from the exporting crate.
fn main() {
let b: issue13213aux::S = issue13213aux::A;
zzz();
}

fn zzz() {()}