Skip to content

Commit

Permalink
debuginfo: Added test cases for structs, tuples, enums, etc passed by…
Browse files Browse the repository at this point in the history
… value.

Also updated documentation comments in debuginfo and renamed DebugContext to CrateDebugContext.
  • Loading branch information
michaelwoerister committed Aug 30, 2013
1 parent 5e040e9 commit dde633e
Show file tree
Hide file tree
Showing 9 changed files with 206 additions and 63 deletions.
4 changes: 2 additions & 2 deletions src/librustc/middle/trans/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ pub struct CrateContext {
// decl_gc_metadata knows whether to link to the module metadata, which
// is not emitted by LLVM's GC pass when no functions use GC.
uses_gc: bool,
dbg_cx: Option<debuginfo::DebugContext>,
dbg_cx: Option<debuginfo::CrateDebugContext>,
do_not_commit_warning_issued: bool
}

Expand Down Expand Up @@ -161,7 +161,7 @@ impl CrateContext {

let crate_map = decl_crate_map(sess, link_meta, llmod);
let dbg_cx = if sess.opts.debuginfo {
Some(debuginfo::DebugContext::new(llmod, name.to_owned()))
Some(debuginfo::CrateDebugContext::new(llmod, name.to_owned()))
} else {
None
};
Expand Down
49 changes: 28 additions & 21 deletions src/librustc/middle/trans/debuginfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ where possible. This will hopefully ease the adaption of this module to future L
The public API of the module is a set of functions that will insert the correct metadata into the
LLVM IR when called with the right parameters. The module is thus driven from an outside client with
functions like `debuginfo::local_var_metadata(bcx: block, local: &ast::local)`.
functions like `debuginfo::create_local_var_metadata(bcx: block, local: &ast::local)`.
Internally the module will try to reuse already created metadata by utilizing a cache. The way to
get a shared metadata node when needed is thus to just call the corresponding function in this
Expand All @@ -37,9 +37,8 @@ module:
The function will take care of probing the cache for an existing node for that exact file path.
All private state used by the module is stored within a DebugContext struct, which in turn is
contained in the CrateContext.
All private state used by the module is stored within either the CrateDebugContext struct (owned by
the CrateContext) or the FunctionDebugContext (owned by the FunctionContext).
This file consists of three conceptual sections:
1. The public interface of the module
Expand Down Expand Up @@ -92,7 +91,7 @@ static DW_ATE_unsigned_char: c_uint = 0x08;
//=-------------------------------------------------------------------------------------------------

/// A context object for maintaining all state needed by the debuginfo module.
pub struct DebugContext {
pub struct CrateDebugContext {
priv crate_file: ~str,
priv llcontext: ContextRef,
priv builder: DIBuilderRef,
Expand All @@ -101,13 +100,13 @@ pub struct DebugContext {
priv created_types: HashMap<uint, DIType>,
}

impl DebugContext {
pub fn new(llmod: ModuleRef, crate: ~str) -> DebugContext {
debug!("DebugContext::new");
impl CrateDebugContext {
pub fn new(llmod: ModuleRef, crate: ~str) -> CrateDebugContext {
debug!("CrateDebugContext::new");
let builder = unsafe { llvm::LLVMDIBuilderCreate(llmod) };
// DIBuilder inherits context from the module, so we'd better use the same one
let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
return DebugContext {
return CrateDebugContext {
crate_file: crate,
llcontext: llcontext,
builder: builder,
Expand Down Expand Up @@ -165,9 +164,9 @@ struct FunctionDebugContextData {
}

enum VariableAccess {
// The value given is a pointer to data
// The value given is a pointer to the data (T*)
DirectVariable,
// The value given has to be dereferenced once to get the pointer to data
// The value given has to be dereferenced once to get the pointer to data (T**)
IndirectVariable
}

Expand Down Expand Up @@ -224,9 +223,9 @@ pub fn create_local_var_metadata(bcx: @mut Block,
}
}

/// Creates debug information for a local variable introduced in the head of a match-statement arm.
/// Creates debug information for a variable captured in a closure.
///
// /// Adds the created metadata nodes directly to the crate's IR.
/// Adds the created metadata nodes directly to the crate's IR.
pub fn create_captured_var_metadata(bcx: @mut Block,
node_id: ast::NodeId,
llptr: ValueRef,
Expand Down Expand Up @@ -321,7 +320,8 @@ pub fn create_self_argument_metadata(bcx: @mut Block,
_) => {
explicit_self.span
}
_ => bcx.ccx().sess.bug(fmt!("create_self_argument_metadata: unexpected sort of node: %?", fnitem))
_ => bcx.ccx().sess.bug(
fmt!("create_self_argument_metadata: unexpected sort of node: %?", fnitem))
};

let scope_metadata = bcx.fcx.debug_context.get_ref(bcx.ccx(), span).fn_metadata;
Expand Down Expand Up @@ -361,14 +361,10 @@ pub fn create_argument_metadata(bcx: @mut Block,
let fcx = bcx.fcx;
let cx = fcx.ccx;

let pattern = arg.pat;
let filename = span_start(cx, pattern.span).file.name;

let def_map = cx.tcx.def_map;
let file_metadata = file_metadata(cx, filename);
let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata;

do pat_util::pat_bindings(def_map, pattern) |_, node_id, span, path_ref| {
do pat_util::pat_bindings(def_map, arg.pat) |_, node_id, span, path_ref| {

let llptr = match bcx.fcx.llargs.find_copy(&node_id) {
Some(v) => v,
Expand Down Expand Up @@ -429,13 +425,24 @@ pub fn set_source_location(fcx: &FunctionContext,
}
}

/// Enables emitting source locations for the given functions.
///
/// Since we don't want source locations to be emitted for the function prelude, they are disabled
/// when beginning to translate a new function. This functions switches source location emitting on
/// and must therefore be called before the first real statement/expression of the function is
/// translated.
pub fn start_emitting_source_locations(fcx: &mut FunctionContext) {
match fcx.debug_context {
FunctionDebugContext(~ref mut data) => data.source_locations_enabled = true,
_ => { /* safe to ignore */}
_ => { /* safe to ignore */ }
}
}

/// Creates the function-specific debug context.
///
/// Returns the FunctionDebugContext for the function which holds state needed for debug info
/// creation. The function may also return another variant of the FunctionDebugContext enum which
/// indicates why no debuginfo should be created for the function.
pub fn create_function_debug_context(cx: &mut CrateContext,
fn_ast_id: ast::NodeId,
param_substs: Option<@param_substs>,
Expand Down Expand Up @@ -1662,7 +1669,7 @@ fn bytes_to_bits(bytes: uint) -> c_ulonglong {
}

#[inline]
fn dbg_cx<'a>(cx: &'a mut CrateContext) -> &'a mut DebugContext {
fn dbg_cx<'a>(cx: &'a mut CrateContext) -> &'a mut CrateDebugContext {
cx.dbg_cx.get_mut_ref()
}

Expand Down
3 changes: 3 additions & 0 deletions src/rustllvm/rustllvm.def.in
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,9 @@ LLVMDIBuilderCreateEnumerator
LLVMDIBuilderCreateEnumerationType
LLVMDIBuilderCreateUnionType
LLVMDIBuilderCreateTemplateTypeParameter
LLVMDIBuilderCreateOpDeref
LLVMDIBuilderCreateOpPlus
LLVMDIBuilderCreateComplexVariable
LLVMSetUnnamedAddr
LLVMRustAddPass
LLVMRustAddAnalysisPasses
Expand Down
99 changes: 99 additions & 0 deletions src/test/debug-info/by-value-non-immediate-argument.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright 2013 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.

// compile-flags:-Z extra-debug-info
// debugger:break zzz
// debugger:run

// debugger:finish
// debugger:print s
// check:$1 = {a = 1, b = 2.5}
// debugger:continue

// debugger:finish
// debugger:print x
// check:$2 = {a = 3, b = 4.5}
// debugger:print y
// check:$3 = 5
// debugger:print z
// check:$4 = 6.5
// debugger:continue

// debugger:finish
// debugger:print a
// check:$5 = {7, 8, 9.5, 10.5}
// debugger:continue

// debugger:finish
// debugger:print a
// check:$6 = {11.5, 12.5, 13, 14}
// debugger:continue

// debugger:finish
// debugger:print x
// check:$7 = {{Case1, x = 0, y = 8970181431921507452}, {Case1, 0, 2088533116, 2088533116}}
// debugger:continue

#[deriving(Clone)]
struct Struct {
a: int,
b: float
}

#[deriving(Clone)]
struct StructStruct {
a: Struct,
b: Struct
}

fn fun(s: Struct) {
zzz();
}

fn fun_fun(StructStruct { a: x, b: Struct { a: y, b: z } }: StructStruct) {
zzz();
}

fn tup(a: (int, uint, float, float)) {
zzz();
}

struct Newtype(float, float, int, uint);

fn new_type(a: Newtype) {
zzz();
}

// The first element is to ensure proper alignment, irrespective of the machines word size. Since
// the size of the discriminant value is machine dependent, this has be taken into account when
// datatype layout should be predictable as in this case.
enum Enum {
Case1 { x: i64, y: i64 },
Case2 (i64, i32, i32),
}

fn by_val_enum(x: Enum) {
zzz();
}

fn main() {
fun(Struct { a: 1, b: 2.5 });
fun_fun(StructStruct { a: Struct { a: 3, b: 4.5 }, b: Struct { a: 5, b: 6.5 } });
tup((7, 8, 9.5, 10.5));
new_type(Newtype(11.5, 12.5, 13, 14));

// 0b0111110001111100011111000111110001111100011111000111110001111100 = 8970181431921507452
// 0b01111100011111000111110001111100 = 2088533116
// 0b0111110001111100 = 31868
// 0b01111100 = 124
by_val_enum(Case1 { x: 0, y: 8970181431921507452 });
}

fn zzz() {()}
34 changes: 0 additions & 34 deletions src/test/debug-info/by-value-struct-argument.rs

This file was deleted.

2 changes: 0 additions & 2 deletions src/test/debug-info/var-captured-in-managed-closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249

// compile-flags:-Z extra-debug-info
// debugger:break zzz
// debugger:run
Expand Down
74 changes: 74 additions & 0 deletions src/test/debug-info/var-captured-in-nested-closure.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright 2013 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.

// compile-flags:-Z extra-debug-info
// debugger:break zzz
// debugger:run
// debugger:finish

// debugger:print variable
// check:$1 = 1
// debugger:print constant
// check:$2 = 2
// debugger:print a_struct
// check:$3 = {a = -3, b = 4.5, c = 5}
// debugger:print *struct_ref
// check:$4 = {a = -3, b = 4.5, c = 5}
// debugger:print *owned
// check:$5 = 6
// debugger:print managed->val
// check:$6 = 7
// debugger:print closure_local
// check:$7 = 8
// debugger:continue

#[allow(unused_variable)];

struct Struct {
a: int,
b: float,
c: uint
}

fn main() {
let mut variable = 1;
let constant = 2;

let a_struct = Struct {
a: -3,
b: 4.5,
c: 5
};

let struct_ref = &a_struct;
let owned = ~6;
let managed = @7;

let closure = || {
let closure_local = 8;

let nested_closure = || {
zzz();
variable = constant + a_struct.a + struct_ref.a + *owned + *managed + closure_local;
};

// breaking here will yield a wrong value for 'constant'. In particular, GDB will
// read the value of the register that supposedly contains the pointer to 'constant'
// and try derefence it. The register, however, already contains the actual value, and
// not a pointer to it. -mw
// zzz();

nested_closure();
};

closure();
}

fn zzz() {()}
2 changes: 0 additions & 2 deletions src/test/debug-info/var-captured-in-sendable-closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249

// compile-flags:-Z extra-debug-info
// debugger:break zzz
// debugger:run
Expand Down
2 changes: 0 additions & 2 deletions src/test/debug-info/var-captured-in-stack-closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249

// compile-flags:-Z extra-debug-info
// debugger:break zzz
// debugger:run
Expand Down

3 comments on commit dde633e

@jdm
Copy link

@jdm jdm commented on dde633e Aug 30, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r+

@jdm
Copy link

@jdm jdm commented on dde633e Aug 30, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors: retry

@alexcrichton
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors: retry

Please sign in to comment.