From 203f96f71d86cc6a2d95b8337977835ac1a41c36 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 12 Jul 2013 10:16:54 +0200 Subject: [PATCH 1/5] debuginfo: Implemented support for destructured locals. Conflicts: src/librustc/middle/trans/debuginfo.rs src/test/debug-info/destructured-local.rs --- src/librustc/middle/trans/debuginfo.rs | 110 +++++++------ src/test/debug-info/destructured-local.rs | 187 +++++++++++++++++++++- 2 files changed, 236 insertions(+), 61 deletions(-) diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index cc690f070ccfc..574f7aad119cb 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -60,6 +60,7 @@ use middle::trans::type_::Type; use middle::trans::adt; use middle::trans; use middle::ty; +use middle::pat_util; use util::ppaux::ty_to_str; use std::hashmap::HashMap; @@ -71,15 +72,15 @@ use syntax::{ast, codemap, ast_util, ast_map}; static DW_LANG_RUST: int = 0x9000; -static DW_TAG_auto_variable: int = 0x100; -static DW_TAG_arg_variable: int = 0x101; +static DW_TAG_auto_variable: c_uint = 0x100; +static DW_TAG_arg_variable: c_uint = 0x101; -static DW_ATE_boolean: int = 0x02; -static DW_ATE_float: int = 0x04; -static DW_ATE_signed: int = 0x05; -static DW_ATE_signed_char: int = 0x06; -static DW_ATE_unsigned: int = 0x07; -static DW_ATE_unsigned_char: int = 0x08; +static DW_ATE_boolean: c_uint = 0x02; +static DW_ATE_float: c_uint = 0x04; +static DW_ATE_signed: c_uint = 0x05; +static DW_ATE_signed_char: c_uint = 0x06; +static DW_ATE_unsigned: c_uint = 0x07; +static DW_ATE_unsigned_char: c_uint = 0x08; @@ -132,65 +133,62 @@ pub fn finalize(cx: @mut CrateContext) { /// Creates debug information for the given local variable. /// /// Adds the created metadata nodes directly to the crate's IR. -/// The return value should be ignored if called from outside of the debuginfo module. -pub fn create_local_var_metadata(bcx: @mut Block, local: @ast::Local) -> DIVariable { +pub fn create_local_var_metadata(bcx: @mut Block, local: &ast::Local) { let cx = bcx.ccx(); - - let ident = match local.pat.node { - ast::pat_ident(_, ref pth, _) => ast_util::path_to_ident(pth), - // FIXME this should be handled (#2533) - _ => { - bcx.sess().span_note(local.span, "debuginfo for pattern bindings NYI"); - return ptr::null(); - } - }; - - let name: &str = cx.sess.str_of(ident); - debug!("create_local_var_metadata: %s", name); - - let loc = span_start(cx, local.span); - let ty = node_id_type(bcx, local.id); - let type_metadata = type_metadata(cx, ty, local.ty.span); - let file_metadata = file_metadata(cx, loc.file.name); + let def_map = cx.tcx.def_map; + let pattern = local.node.pat; let context = match bcx.parent { None => create_function_metadata(bcx.fcx), Some(_) => lexical_block_metadata(bcx) }; - let var_metadata = do name.as_c_str |name| { + do pat_util::pat_bindings(def_map, pattern) |_, node_id, span, path_ref| { + + let ident = ast_util::path_to_ident(path_ref); + let name: &str = cx.sess.str_of(ident); + debug!("create_local_var_metadata: %s", name); + let loc = span_start(cx, span); + let ty = node_id_type(bcx, node_id); + let type_metadata = type_metadata(cx, ty, span); + let file_metadata = file_metadata(cx, loc.file.name); + + let var_metadata = do as_c_str(name) |name| { + unsafe { + llvm::LLVMDIBuilderCreateLocalVariable( + DIB(cx), + DW_TAG_auto_variable, + context, + name, + file_metadata, + loc.line as c_uint, + type_metadata, + false, + 0, + 0) + } + }; + + let llptr = match bcx.fcx.lllocals.find_copy(&node_id) { + Some(v) => v, + None => { + bcx.tcx().sess.span_bug( + local.span, + fmt!("No entry in lllocals table for %?", local.node.id)); + } + }; + + set_debug_location(cx, lexical_block_metadata(bcx), loc.line, loc.col.to_uint()); unsafe { - llvm::LLVMDIBuilderCreateLocalVariable( + let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd( DIB(cx), - DW_TAG_auto_variable as u32, - context, - name, - file_metadata, - loc.line as c_uint, - type_metadata, - false, - 0, - 0) - } - }; + llptr, + var_metadata, + bcx.llbb); - // FIXME(#6814) Should use `pat_util::pat_bindings` for pats like (a, b) etc - let llptr = match bcx.fcx.lllocals.find_copy(&local.pat.id) { - Some(v) => v, - None => { - bcx.tcx().sess.span_bug( - local.span, - fmt!("No entry in lllocals table for %?", local.id)); + llvm::LLVMSetInstDebugLocation(trans::build::B(bcx), instr); } - }; - - set_debug_location(cx, lexical_block_metadata(bcx), loc.line, loc.col.to_uint()); - unsafe { - let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(DIB(cx), llptr, var_metadata, bcx.llbb); - llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr); } - - return var_metadata; } /// Creates debug information for the given function argument. @@ -527,7 +525,7 @@ fn basic_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType { name, bytes_to_bits(size), bytes_to_bits(align), - encoding as c_uint) + encoding) } }; diff --git a/src/test/debug-info/destructured-local.rs b/src/test/debug-info/destructured-local.rs index 207899fe3b510..6d85b99a79d6c 100644 --- a/src/test/debug-info/destructured-local.rs +++ b/src/test/debug-info/destructured-local.rs @@ -8,21 +8,198 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// xfail-test - // compile-flags:-Z extra-debug-info // debugger:break zzz // debugger:run // debugger:finish // debugger:print a -// check:$1 = 9898 - +// check:$1 = 1 // debugger:print b // check:$2 = false +// debugger:print c +// check:$3 = 2 +// debugger:print d +// check:$4 = 3 +// debugger:print e +// check:$5 = 4 + +// debugger:print f +// check:$6 = 5 +// debugger:print g +// check:$7 = {6, 7} + +// debugger:print h +// check:$8 = 8 +// debugger:print i +// check:$9 = {a = 9, b = 10} +// debugger:print j +// check:$10 = 11 + +// debugger:print k +// check:$11 = 12 +// debugger:print l +// check:$12 = 13 + +// debugger:print m +// check:$13 = 14 +// debugger:print n +// check:$14 = 16 + +// debugger:print o +// check:$15 = 18 + +// debugger:print p +// check:$16 = 19 +// debugger:print q +// check:$17 = 20 +// debugger:print r +// check:$18 = {a = 21, b = 22} + +// debugger:print s +// check:$19 = 24 +// debugger:print t +// check:$20 = 23 + +// debugger:print u +// check:$21 = 25 +// debugger:print v +// check:$22 = 26 +// debugger:print w +// check:$23 = 27 +// debugger:print x +// check:$24 = 28 +// debugger:print y +// check:$25 = 29 +// debugger:print z +// check:$26 = 30 +// debugger:print ae +// check:$27 = 31 +// debugger:print oe +// check:$28 = 32 +// debugger:print ue +// check:$29 = 33 + +// debugger:print aa +// check:$30 = {34, 35} + +// debugger:print bb +// check:$31 = {36, 37} + +// debugger:print cc +// check:$32 = 38 + +// debugger:print dd +// check:$33 = {40, 41, 42} + +// debugger:print *ee +// check:$34 = {43, 44, 45} + +// debugger:print *ff +// check:$35 = 46 + +// debugger:print gg +// check:$36 = {47, 48} + +// debugger:print *hh +// check:$37 = 50 + +// debugger:print ii +// check:$38 = 51 + +// debugger:print *jj +// check:$39 = 52 + +// debugger:print kk +// check:$40 = 53 + +// debugger:print ll +// check:$41 = 54 + +// debugger:print mm +// check:$42 = 55 + +// debugger:print *nn +// check:$43 = 56 + + +struct Struct { + a: i64, + b: i32 +} + +enum Univariant { + Unit(i32) +} + +struct TupleStruct (float, int); + + fn main() { - let (a, b): (int, bool) = (9898, false); + // simple tuple + let (a, b) : (int, bool) = (1, false); + + // nested tuple + let (c, (d, e)) : (int, (u16, u16)) = (2, (3, 4)); + + // bind tuple-typed value to one name (destructure only first level) + let (f, g) : (int, (u32, u32)) = (5, (6, 7)); + + // struct as tuple element + let (h, i, j) : (i16, Struct, i16) = (8, Struct { a: 9, b: 10 }, 11); + + // struct pattern + let Struct { a: k, b: l } = Struct { a: 12, b: 13 }; + + // ignored tuple element + let (m, _, n) = (14, 15, 16); + + // ignored struct field + let Struct { b: o, _ } = Struct { a: 17, b: 18 }; + + // one struct destructured, one not + let (Struct { a: p, b: q }, r) = (Struct { a: 19, b: 20 }, Struct { a: 21, b: 22 }); + + // different order of struct fields + let Struct { b: s, a: t } = Struct { a: 23, b: 24 }; + + // complex nesting + let ((u, v), ((w, (x, Struct { a: y, b: z})), Struct { a: ae, b: oe }), ue) = + ((25, 26), ((27, (28, Struct { a: 29, b: 30})), Struct { a: 31, b: 32 }), 33); + + // managed box + let @aa = @(34, 35); + + // borrowed pointer + let &bb = &(36, 37); + + // contained borrowed pointer + let (&cc, _) = (&38, 39); + + // unique pointer + let ~dd = ~(40, 41, 42); + + // ref binding + let ref ee = (43, 44, 45); + + // ref binding in tuple + let (ref ff, gg) = (46, (47, 48)); + + // ref binding in struct + let Struct { b: ref hh, _ } = Struct { a: 49, b: 50 }; + + // univariant enum + let Unit(ii) = Unit(51); + + // univariant enum with ref binding + let Unit(ref jj) = Unit(52); + + // tuple struct + let TupleStruct(kk, ll) = TupleStruct(53.0, 54); + + // tuple struct with ref binding + let TupleStruct(mm, ref nn) = TupleStruct(55.0, 56); zzz(); } From c9e51cef122bcdd50e4571649421e5ab7d99faeb Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 18 Jul 2013 12:04:33 +0200 Subject: [PATCH 2/5] debuginfo: Support for function arguments. (WIP) --- src/librustc/middle/trans/debuginfo.rs | 147 ++++++++++++---------- src/test/debug-info/function-arguments.rs | 4 +- 2 files changed, 84 insertions(+), 67 deletions(-) diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 574f7aad119cb..add52254b02be 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -91,14 +91,15 @@ static DW_ATE_unsigned_char: c_uint = 0x08; /// A context object for maintaining all state needed by the debuginfo module. pub struct DebugContext { - crate_file: ~str, - llcontext: ContextRef, - builder: DIBuilderRef, - curr_loc: (uint, uint), - created_files: HashMap<~str, DIFile>, - created_functions: HashMap, - created_blocks: HashMap, - created_types: HashMap + priv crate_file: ~str, + priv llcontext: ContextRef, + priv builder: DIBuilderRef, + priv curr_loc: (uint, uint), + priv created_files: HashMap<~str, DIFile>, + priv created_functions: HashMap, + priv created_blocks: HashMap, + priv created_types: HashMap, + priv argument_index_counters: HashMap, } impl DebugContext { @@ -116,6 +117,7 @@ impl DebugContext { created_functions: HashMap::new(), created_blocks: HashMap::new(), created_types: HashMap::new(), + argument_index_counters: HashMap::new(), }; } } @@ -138,11 +140,14 @@ pub fn create_local_var_metadata(bcx: @mut Block, local: &ast::Local) { let def_map = cx.tcx.def_map; let pattern = local.node.pat; - let context = match bcx.parent { + let scope = match bcx.parent { None => create_function_metadata(bcx.fcx), Some(_) => lexical_block_metadata(bcx) }; + let filename = span_start(cx, local.span).file.name; + let file_metadata = file_metadata(cx, filename); + do pat_util::pat_bindings(def_map, pattern) |_, node_id, span, path_ref| { let ident = ast_util::path_to_ident(path_ref); @@ -151,14 +156,13 @@ pub fn create_local_var_metadata(bcx: @mut Block, local: &ast::Local) { let loc = span_start(cx, span); let ty = node_id_type(bcx, node_id); let type_metadata = type_metadata(cx, ty, span); - let file_metadata = file_metadata(cx, loc.file.name); let var_metadata = do as_c_str(name) |name| { unsafe { llvm::LLVMDIBuilderCreateLocalVariable( DIB(cx), DW_TAG_auto_variable, - context, + scope, name, file_metadata, loc.line as c_uint, @@ -172,9 +176,7 @@ pub fn create_local_var_metadata(bcx: @mut Block, local: &ast::Local) { let llptr = match bcx.fcx.lllocals.find_copy(&node_id) { Some(v) => v, None => { - bcx.tcx().sess.span_bug( - local.span, - fmt!("No entry in lllocals table for %?", local.node.id)); + bcx.tcx().sess.span_bug(span, fmt!("No entry in lllocals table for %?", node_id)); } }; @@ -194,64 +196,77 @@ pub fn create_local_var_metadata(bcx: @mut Block, local: &ast::Local) { /// Creates debug information for the given function argument. /// /// Adds the created metadata nodes directly to the crate's IR. -/// The return value should be ignored if called from outside of the debuginfo module. -pub fn create_argument_metadata(bcx: @mut Block, arg: &ast::arg, span: span) -> Option { - debug!("create_argument_metadata"); - if true { - // XXX create_argument_metadata disabled for now because "node_id_type(bcx, arg.id)" below - // blows up: - // "error: internal compiler error: node_id_to_type: no type for node `arg (id=10)`" - return None; - } - +pub fn create_argument_metadata(bcx: @mut Block, arg: &ast::arg, span: span) { let fcx = bcx.fcx; let cx = fcx.ccx; - let loc = span_start(cx, span); - if "" == loc.file.name { - return None; + if fcx.span.is_none() { + return; } - let ty = node_id_type(bcx, arg.id); - let type_metadata = type_metadata(cx, ty, arg.ty.span); - let file_metadata = file_metadata(cx, loc.file.name); - let context = create_function_metadata(fcx); - - match arg.pat.node { - ast::pat_ident(_, ref path, _) => { - // XXX: This is wrong; it should work for multiple bindings. - let ident = path.idents.last(); - let name: &str = cx.sess.str_of(*ident); - let var_metadata = do name.as_c_str |name| { - unsafe { - llvm::LLVMDIBuilderCreateLocalVariable( - DIB(cx), - DW_TAG_arg_variable as u32, - context, - name, - file_metadata, - loc.line as c_uint, - type_metadata, - false, - 0, - 0) - // XXX need to pass in a real argument number - } - }; + if "" == span_start(cx, span).file.name { + return; + } + + let def_map = cx.tcx.def_map; + let pattern = arg.pat; + + let mut argument_index = match dbg_cx(cx).argument_index_counters.find_copy(&arg.id) { + Some(value) => value, + None => 0 + }; + + let filename = span_start(cx, span).file.name; + let file_metadata = file_metadata(cx, filename); + let scope = create_function_metadata(fcx); + + do pat_util::pat_bindings(def_map, pattern) |_, node_id, span, path_ref| { + + let ty = node_id_type(bcx, node_id); + let type_metadata = type_metadata(cx, ty, codemap::dummy_sp()); + let loc = span_start(cx, span); + let ident = ast_util::path_to_ident(path_ref); + let name: &str = cx.sess.str_of(ident); + debug!("create_argument_metadata: %s", name); - let llptr = fcx.llargs.get_copy(&arg.id); - set_debug_location(cx, lexical_block_metadata(bcx), loc.line, loc.col.to_uint()); + let arg_metadata = do as_c_str(name) |name| { unsafe { - let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd( - DIB(cx), llptr, var_metadata, bcx.llbb); - llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr); + llvm::LLVMDIBuilderCreateLocalVariable( + DIB(cx), + DW_TAG_arg_variable, + scope, + name, + file_metadata, + loc.line as c_uint, + type_metadata, + false, + 0, + argument_index as c_uint) } - return Some(var_metadata); - } - _ => { - return None; + }; + + argument_index += 1; + + let llptr = match bcx.fcx.llargs.find_copy(&node_id) { + Some(v) => v, + None => { + bcx.tcx().sess.span_bug(span, fmt!("No entry in llargs table for %?", node_id)); + } + }; + + set_debug_location(cx, lexical_block_metadata(bcx), loc.line, loc.col.to_uint()); + unsafe { + let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd( + DIB(cx), + llptr, + arg_metadata, + bcx.llbb); + + llvm::LLVMSetInstDebugLocation(trans::build::B(bcx), instr); } } + + dbg_cx(cx).argument_index_counters.insert(arg.id, argument_index); } /// Sets the current debug location at the beginning of the span @@ -272,7 +287,6 @@ pub fn update_source_pos(bcx: @mut Block, span: span) { /// The return value should be ignored if called from outside of the debuginfo module. pub fn create_function_metadata(fcx: &FunctionContext) -> DISubprogram { let cx = fcx.ccx; - let span = fcx.span.get(); let fnitem = cx.tcx.items.get_copy(&fcx.id); let (ident, ret_ty, id) = match fnitem { @@ -318,7 +332,7 @@ pub fn create_function_metadata(fcx: &FunctionContext) -> DISubprogram { _) => { (ident, ty, id) } - _ => fcx.ccx.sess.bug("create_function_metadata: unexpected sort of node") + _ => fcx.ccx.sess.bug(fmt!("create_function_metadata: unexpected sort of node: %?", fnitem)) }; match dbg_cx(cx).created_functions.find(&id) { @@ -326,6 +340,11 @@ pub fn create_function_metadata(fcx: &FunctionContext) -> DISubprogram { None => () } + let span = match fcx.span { + Some(value) => value, + None => codemap::dummy_sp() + }; + debug!("create_function_metadata: %s, %s", cx.sess.str_of(ident), cx.sess.codemap.span_to_str(span)); diff --git a/src/test/debug-info/function-arguments.rs b/src/test/debug-info/function-arguments.rs index 225dfedfec721..5a410ef6462ca 100644 --- a/src/test/debug-info/function-arguments.rs +++ b/src/test/debug-info/function-arguments.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// xfail-test - // compile-flags:-Z extra-debug-info // debugger:break zzz // debugger:run @@ -34,7 +32,7 @@ fn main() { nested(2000, 3000); fn nested(a: i32, b: i64) -> (i32, i64) { - zzz() + zzz(); (a, b) } } From 02a0f2822e4911ffa3a36f48c0d9afc48f428ece Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 18 Jul 2013 17:12:33 +0200 Subject: [PATCH 3/5] debuginfo: Support for destructured function arguments. --- src/librustc/middle/trans/debuginfo.rs | 12 +- .../debug-info/destructured-fn-argument.rs | 316 ++++++++++++++++++ .../multiple-functions-equal-var-names.rs | 54 +++ src/test/debug-info/multiple-functions.rs | 54 +++ 4 files changed, 429 insertions(+), 7 deletions(-) create mode 100644 src/test/debug-info/destructured-fn-argument.rs create mode 100644 src/test/debug-info/multiple-functions-equal-var-names.rs create mode 100644 src/test/debug-info/multiple-functions.rs diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index add52254b02be..9179a1fc9bea6 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -200,18 +200,16 @@ pub fn create_argument_metadata(bcx: @mut Block, arg: &ast::arg, span: span) { let fcx = bcx.fcx; let cx = fcx.ccx; - if fcx.span.is_none() { - return; - } - - if "" == span_start(cx, span).file.name { + if fcx.id == -1 || + fcx.span.is_none() || + "" == span_start(cx, span).file.name { return; } let def_map = cx.tcx.def_map; let pattern = arg.pat; - let mut argument_index = match dbg_cx(cx).argument_index_counters.find_copy(&arg.id) { + let mut argument_index = match dbg_cx(cx).argument_index_counters.find_copy(&fcx.id) { Some(value) => value, None => 0 }; @@ -266,7 +264,7 @@ pub fn create_argument_metadata(bcx: @mut Block, arg: &ast::arg, span: span) { } } - dbg_cx(cx).argument_index_counters.insert(arg.id, argument_index); + dbg_cx(cx).argument_index_counters.insert(fcx.id, argument_index); } /// Sets the current debug location at the beginning of the span diff --git a/src/test/debug-info/destructured-fn-argument.rs b/src/test/debug-info/destructured-fn-argument.rs new file mode 100644 index 0000000000000..fe0d9a486bcfe --- /dev/null +++ b/src/test/debug-info/destructured-fn-argument.rs @@ -0,0 +1,316 @@ +// 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 or the MIT license +// , 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 a +// check:$1 = 1 +// debugger:print b +// check:$2 = false +// debugger:continue + +// debugger:finish +// debugger:print a +// check:$3 = 2 +// debugger:print b +// check:$4 = 3 +// debugger:print c +// check:$5 = 4 +// debugger:continue + +// debugger:finish +// debugger:print a +// check:$6 = 5 +// debugger:print b +// check:$7 = {6, 7} +// debugger:continue + +// debugger:finish +// debugger:print h +// check:$8 = 8 +// debugger:print i +// check:$9 = {a = 9, b = 10} +// debugger:print j +// check:$10 = 11 +// debugger:continue + +// debugger:finish +// debugger:print k +// check:$11 = 12 +// debugger:print l +// check:$12 = 13 +// debugger:continue + +// debugger:finish +// debugger:print m +// check:$13 = 14 +// debugger:print n +// check:$14 = 16 +// debugger:continue + +// debugger:finish +// debugger:print o +// check:$15 = 18 +// debugger:continue + +// debugger:finish +// debugger:print p +// check:$16 = 19 +// debugger:print q +// check:$17 = 20 +// debugger:print r +// check:$18 = {a = 21, b = 22} +// debugger:continue + +// debugger:finish +// debugger:print s +// check:$19 = 24 +// debugger:print t +// check:$20 = 23 +// debugger:continue + +// debugger:finish +// debugger:print u +// check:$21 = 25 +// debugger:print v +// check:$22 = 26 +// debugger:print w +// check:$23 = 27 +// debugger:print x +// check:$24 = 28 +// debugger:print y +// check:$25 = 29 +// debugger:print z +// check:$26 = 30 +// debugger:print ae +// check:$27 = 31 +// debugger:print oe +// check:$28 = 32 +// debugger:print ue +// check:$29 = 33 +// debugger:continue + +// debugger:finish +// debugger:print aa +// check:$30 = {34, 35} +// debugger:continue + +// debugger:finish +// debugger:print bb +// check:$31 = {36, 37} +// debugger:continue + +// debugger:finish +// debugger:print cc +// check:$32 = 38 +// debugger:continue + +// debugger:finish +// debugger:print dd +// check:$33 = {40, 41, 42} +// debugger:continue + +// debugger:finish +// debugger:print *ee +// check:$34 = {43, 44, 45} +// debugger:continue + +// debugger:finish +// debugger:print *ff +// check:$35 = 46 +// debugger:print gg +// check:$36 = {47, 48} +// debugger:continue + +// debugger:finish +// debugger:print *hh +// check:$37 = 50 +// debugger:continue + +// debugger:finish +// debugger:print ii +// check:$38 = 51 +// debugger:continue + +// debugger:finish +// debugger:print *jj +// check:$39 = 52 +// debugger:continue + +// debugger:finish +// debugger:print kk +// check:$40 = 53 +// debugger:print ll +// check:$41 = 54 +// debugger:continue + +// debugger:finish +// debugger:print mm +// check:$42 = 55 +// debugger:print *nn +// check:$43 = 56 +// debugger:continue + +// debugger:finish +// debugger:print oo +// check:$44 = 57 +// debugger:print pp +// check:$45 = 58 +// debugger:print qq +// check:$46 = 59 +// debugger:continue + +// debugger:finish +// debugger:print rr +// check:$47 = 60 +// debugger:print ss +// check:$48 = 61 +// debugger:print tt +// check:$49 = 62 +// debugger:continue + + +struct Struct { + a: i64, + b: i32 +} + +enum Univariant { + Unit(i32) +} + +struct TupleStruct (float, int); + + +fn simple_tuple((a, b): (int, bool)) { + zzz(); +} + +fn nested_tuple((a, (b, c)): (int, (u16, u16))) { + zzz(); +} + +fn destructure_only_first_level((a, b): (int, (u32, u32))) { + zzz(); +} + +fn struct_as_tuple_element((h, i, j): (i16, Struct, i16)) { + zzz(); +} + +fn struct_pattern(Struct { a: k, b: l }: Struct) { + zzz(); +} + +fn ignored_tuple_element((m, _, n): (int, u16, i32)) { + zzz(); +} + +fn ignored_struct_field(Struct { b: o, _ }: Struct) { + zzz(); +} + +fn one_struct_destructured_one_not((Struct { a: p, b: q }, r): (Struct, Struct)) { + zzz(); +} + +fn different_order_of_struct_fields(Struct { b: s, a: t }: Struct ) { + zzz(); +} + +fn complex_nesting(((u, v ), ((w, (x, Struct { a: y, b: z})), Struct { a: ae, b: oe }), ue ): + ((i16, i32), ((i64, (i32, Struct, )), Struct ), u16)) { + zzz(); +} + +fn managed_box(@aa: @(int, int)) { + zzz(); +} + +fn borrowed_pointer(&bb: &(int, int)) { + zzz(); +} + +fn contained_borrowed_pointer((&cc, _): (&int, int)) { + zzz(); +} + +fn unique_pointer(~dd: ~(int, int, int)) { + zzz(); +} + +fn ref_binding(ref ee: (int, int, int)) { + zzz(); +} + +fn ref_binding_in_tuple((ref ff, gg): (int, (int, int))) { + zzz(); +} + +fn ref_binding_in_struct(Struct { b: ref hh, _ }: Struct) { + zzz(); +} + +fn univariant_enum(Unit(ii): Univariant) { + zzz(); +} + +fn univariant_enum_with_ref_binding(Unit(ref jj): Univariant) { + zzz(); +} + +fn tuple_struct(TupleStruct(kk, ll): TupleStruct) { + zzz(); +} + +fn tuple_struct_with_ref_binding(TupleStruct(mm, ref nn): TupleStruct) { + zzz(); +} + +fn multiple_arguments((oo, pp): (int, int), qq : int) { + zzz(); +} + +fn main() { + simple_tuple((1, false)); + nested_tuple((2, (3, 4))); + destructure_only_first_level((5, (6, 7))); + struct_as_tuple_element((8, Struct { a: 9, b: 10 }, 11)); + struct_pattern(Struct { a: 12, b: 13 }); + ignored_tuple_element((14, 15, 16)); + ignored_struct_field(Struct { a: 17, b: 18 }); + one_struct_destructured_one_not((Struct { a: 19, b: 20 }, Struct { a: 21, b: 22 })); + different_order_of_struct_fields(Struct { a: 23, b: 24 }); + complex_nesting(((25, 26), ((27, (28, Struct { a: 29, b: 30})), Struct { a: 31, b: 32 }), 33)); + managed_box(@(34, 35)); + borrowed_pointer(&(36, 37)); + contained_borrowed_pointer((&38, 39)); + unique_pointer(~(40, 41, 42)); + ref_binding((43, 44, 45)); + ref_binding_in_tuple((46, (47, 48))); + ref_binding_in_struct(Struct { a: 49, b: 50 }); + univariant_enum(Unit(51)); + univariant_enum_with_ref_binding(Unit(52)); + tuple_struct(TupleStruct(53.0, 54)); + tuple_struct_with_ref_binding(TupleStruct(55.0, 56)); + multiple_arguments((57, 58), 59); + + fn nested_function(rr: int, (ss, tt): (int, int)) { + zzz(); + } + + nested_function(60, (61, 62)); +} + + +fn zzz() {()} \ No newline at end of file diff --git a/src/test/debug-info/multiple-functions-equal-var-names.rs b/src/test/debug-info/multiple-functions-equal-var-names.rs new file mode 100644 index 0000000000000..5b690b9d067c4 --- /dev/null +++ b/src/test/debug-info/multiple-functions-equal-var-names.rs @@ -0,0 +1,54 @@ +// 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 or the MIT license +// , at your +// 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 +// debugger:finish + +// debugger:print abc +// check:$1 = 10101 +// debugger:continue + +// debugger:finish +// debugger:print abc +// check:$2 = 20202 +// debugger:continue + +// debugger:finish +// debugger:print abc +// check:$3 = 30303 + +fn function_one() { + let abc = 10101; + zzz(); +} + +fn function_two() { + let abc = 20202; + zzz(); +} + + +fn function_three() { + let abc = 30303; + zzz(); +} + + +fn main() { + function_one(); + function_two(); + function_three(); +} + +fn zzz() {()} diff --git a/src/test/debug-info/multiple-functions.rs b/src/test/debug-info/multiple-functions.rs new file mode 100644 index 0000000000000..aaac723f1613e --- /dev/null +++ b/src/test/debug-info/multiple-functions.rs @@ -0,0 +1,54 @@ +// 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 or the MIT license +// , at your +// 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 +// debugger:finish + +// debugger:print a +// check:$1 = 10101 +// debugger:continue + +// debugger:finish +// debugger:print b +// check:$2 = 20202 +// debugger:continue + +// debugger:finish +// debugger:print c +// check:$3 = 30303 + +fn function_one() { + let a = 10101; + zzz(); +} + +fn function_two() { + let b = 20202; + zzz(); +} + + +fn function_three() { + let c = 30303; + zzz(); +} + + +fn main() { + function_one(); + function_two(); + function_three(); +} + +fn zzz() {()} From af7b87f69d9c4633d7e0c7dd77f34c23bbd433d8 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 22 Jul 2013 16:18:53 +0200 Subject: [PATCH 4/5] debuginfo: Minor cleanup now possible with new snapshot. --- src/librustc/middle/trans/debuginfo.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 9179a1fc9bea6..50acb080978bc 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -138,7 +138,7 @@ pub fn finalize(cx: @mut CrateContext) { pub fn create_local_var_metadata(bcx: @mut Block, local: &ast::Local) { let cx = bcx.ccx(); let def_map = cx.tcx.def_map; - let pattern = local.node.pat; + let pattern = local.pat; let scope = match bcx.parent { None => create_function_metadata(bcx.fcx), @@ -157,7 +157,7 @@ pub fn create_local_var_metadata(bcx: @mut Block, local: &ast::Local) { let ty = node_id_type(bcx, node_id); let type_metadata = type_metadata(cx, ty, span); - let var_metadata = do as_c_str(name) |name| { + let var_metadata = do name.as_c_str |name| { unsafe { llvm::LLVMDIBuilderCreateLocalVariable( DIB(cx), @@ -188,7 +188,7 @@ pub fn create_local_var_metadata(bcx: @mut Block, local: &ast::Local) { var_metadata, bcx.llbb); - llvm::LLVMSetInstDebugLocation(trans::build::B(bcx), instr); + llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr); } } } @@ -227,7 +227,7 @@ pub fn create_argument_metadata(bcx: @mut Block, arg: &ast::arg, span: span) { let name: &str = cx.sess.str_of(ident); debug!("create_argument_metadata: %s", name); - let arg_metadata = do as_c_str(name) |name| { + let arg_metadata = do name.as_c_str |name| { unsafe { llvm::LLVMDIBuilderCreateLocalVariable( DIB(cx), @@ -260,7 +260,7 @@ pub fn create_argument_metadata(bcx: @mut Block, arg: &ast::arg, span: span) { arg_metadata, bcx.llbb); - llvm::LLVMSetInstDebugLocation(trans::build::B(bcx), instr); + llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr); } } @@ -623,8 +623,6 @@ fn tuple_metadata(cx: &mut CrateContext, fn enum_metadata(cx: &mut CrateContext, enum_type: ty::t, enum_def_id: ast::def_id, - // _substs is only needed in the other version. Will go away with new snapshot. - _substs: &ty::substs, span: span) -> DIType { @@ -1128,8 +1126,8 @@ fn type_metadata(cx: &mut CrateContext, } } }, - ty::ty_enum(def_id, ref substs) => { - enum_metadata(cx, t, def_id, substs, span) + ty::ty_enum(def_id, _) => { + enum_metadata(cx, t, def_id, span) }, ty::ty_box(ref mt) => { create_pointer_to_box_metadata(cx, t, mt.ty) From d54615528c9d90523865a5bc518b21bb20909ce2 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 25 Jul 2013 19:46:57 +0200 Subject: [PATCH 5/5] debuginfo: Fixed a few things for PR. --- src/librustc/middle/trans/base.rs | 2 +- src/librustc/middle/trans/debuginfo.rs | 47 ++++++++++++------- .../debug-info/destructured-fn-argument.rs | 8 ++-- src/test/debug-info/destructured-local.rs | 22 +++++---- src/test/debug-info/function-arguments.rs | 2 + 5 files changed, 51 insertions(+), 30 deletions(-) diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 437d1a50d185e..8a2766b47e1ad 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1790,7 +1790,7 @@ pub fn copy_args_to_allocas(fcx: @mut FunctionContext, bcx = _match::store_arg(bcx, args[arg_n].pat, llarg); if fcx.ccx.sess.opts.extra_debuginfo && fcx_has_nonzero_span(fcx) { - debuginfo::create_argument_metadata(bcx, &args[arg_n], args[arg_n].ty.span); + debuginfo::create_argument_metadata(bcx, &args[arg_n]); } } diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 50acb080978bc..7333850bf96d4 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -99,7 +99,8 @@ pub struct DebugContext { priv created_functions: HashMap, priv created_blocks: HashMap, priv created_types: HashMap, - priv argument_index_counters: HashMap, + priv last_function_context_id: ast::node_id, + priv argument_counter: uint, } impl DebugContext { @@ -117,7 +118,8 @@ impl DebugContext { created_functions: HashMap::new(), created_blocks: HashMap::new(), created_types: HashMap::new(), - argument_index_counters: HashMap::new(), + last_function_context_id: -1, // magic value :( + argument_counter: 1, }; } } @@ -196,25 +198,35 @@ pub fn create_local_var_metadata(bcx: @mut Block, local: &ast::Local) { /// Creates debug information for the given function argument. /// /// Adds the created metadata nodes directly to the crate's IR. -pub fn create_argument_metadata(bcx: @mut Block, arg: &ast::arg, span: span) { +pub fn create_argument_metadata(bcx: @mut Block, + arg: &ast::arg) { let fcx = bcx.fcx; let cx = fcx.ccx; + let pattern = arg.pat; + let filename = span_start(cx, pattern.span).file.name; + if fcx.id == -1 || fcx.span.is_none() || - "" == span_start(cx, span).file.name { + "" == filename { return; } - let def_map = cx.tcx.def_map; - let pattern = arg.pat; + // Limited the scope within which `debug_context` is live, + // otherwise => borrowing errors + { + let debug_context = dbg_cx(cx); - let mut argument_index = match dbg_cx(cx).argument_index_counters.find_copy(&fcx.id) { - Some(value) => value, - None => 0 - }; + // If this is a new function, reset the counter. llvm::DIBuilder + // wants arguments to be indexed starting from 1. + if fcx.id != debug_context.last_function_context_id { + debug_context.argument_counter = 1; + } + // Keep track of the function we are in + debug_context.last_function_context_id = fcx.id; + } - let filename = span_start(cx, span).file.name; + let def_map = cx.tcx.def_map; let file_metadata = file_metadata(cx, filename); let scope = create_function_metadata(fcx); @@ -227,6 +239,13 @@ pub fn create_argument_metadata(bcx: @mut Block, arg: &ast::arg, span: span) { let name: &str = cx.sess.str_of(ident); debug!("create_argument_metadata: %s", name); + let argument_index = { + let debug_context = dbg_cx(cx); + let argument_index = debug_context.argument_counter; + debug_context.argument_counter += 1; + argument_index as c_uint + }; + let arg_metadata = do name.as_c_str |name| { unsafe { llvm::LLVMDIBuilderCreateLocalVariable( @@ -239,12 +258,10 @@ pub fn create_argument_metadata(bcx: @mut Block, arg: &ast::arg, span: span) { type_metadata, false, 0, - argument_index as c_uint) + argument_index) } }; - argument_index += 1; - let llptr = match bcx.fcx.llargs.find_copy(&node_id) { Some(v) => v, None => { @@ -263,8 +280,6 @@ pub fn create_argument_metadata(bcx: @mut Block, arg: &ast::arg, span: span) { llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr); } } - - dbg_cx(cx).argument_index_counters.insert(fcx.id, argument_index); } /// Sets the current debug location at the beginning of the span diff --git a/src/test/debug-info/destructured-fn-argument.rs b/src/test/debug-info/destructured-fn-argument.rs index fe0d9a486bcfe..05718ab48909f 100644 --- a/src/test/debug-info/destructured-fn-argument.rs +++ b/src/test/debug-info/destructured-fn-argument.rs @@ -8,6 +8,8 @@ // 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 @@ -282,7 +284,7 @@ fn multiple_arguments((oo, pp): (int, int), qq : int) { } fn main() { - simple_tuple((1, false)); + simple_tuple((1, false)); nested_tuple((2, (3, 4))); destructure_only_first_level((5, (6, 7))); struct_as_tuple_element((8, Struct { a: 9, b: 10 }, 11)); @@ -291,8 +293,8 @@ fn main() { ignored_struct_field(Struct { a: 17, b: 18 }); one_struct_destructured_one_not((Struct { a: 19, b: 20 }, Struct { a: 21, b: 22 })); different_order_of_struct_fields(Struct { a: 23, b: 24 }); - complex_nesting(((25, 26), ((27, (28, Struct { a: 29, b: 30})), Struct { a: 31, b: 32 }), 33)); - managed_box(@(34, 35)); + complex_nesting(((25, 26), ((27, (28, Struct { a: 29, b: 30})), Struct { a: 31, b: 32 }), 33)); + managed_box(@(34, 35)); borrowed_pointer(&(36, 37)); contained_borrowed_pointer((&38, 39)); unique_pointer(~(40, 41, 42)); diff --git a/src/test/debug-info/destructured-local.rs b/src/test/debug-info/destructured-local.rs index 6d85b99a79d6c..f8db7981c941b 100644 --- a/src/test/debug-info/destructured-local.rs +++ b/src/test/debug-info/destructured-local.rs @@ -8,6 +8,8 @@ // 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 @@ -125,8 +127,8 @@ struct Struct { - a: i64, - b: i32 + a: i64, + b: i32 } enum Univariant { @@ -137,7 +139,7 @@ struct TupleStruct (float, int); fn main() { - // simple tuple + // simple tuple let (a, b) : (int, bool) = (1, false); // nested tuple @@ -162,14 +164,14 @@ fn main() { let (Struct { a: p, b: q }, r) = (Struct { a: 19, b: 20 }, Struct { a: 21, b: 22 }); // different order of struct fields - let Struct { b: s, a: t } = Struct { a: 23, b: 24 }; + let Struct { b: s, a: t } = Struct { a: 23, b: 24 }; - // complex nesting - let ((u, v), ((w, (x, Struct { a: y, b: z})), Struct { a: ae, b: oe }), ue) = - ((25, 26), ((27, (28, Struct { a: 29, b: 30})), Struct { a: 31, b: 32 }), 33); + // complex nesting + let ((u, v), ((w, (x, Struct { a: y, b: z})), Struct { a: ae, b: oe }), ue) = + ((25, 26), ((27, (28, Struct { a: 29, b: 30})), Struct { a: 31, b: 32 }), 33); - // managed box - let @aa = @(34, 35); + // managed box + let @aa = @(34, 35); // borrowed pointer let &bb = &(36, 37); @@ -192,7 +194,7 @@ fn main() { // univariant enum let Unit(ii) = Unit(51); - // univariant enum with ref binding + // univariant enum with ref binding let Unit(ref jj) = Unit(52); // tuple struct diff --git a/src/test/debug-info/function-arguments.rs b/src/test/debug-info/function-arguments.rs index 5a410ef6462ca..1fe79b8e2a9e9 100644 --- a/src/test/debug-info/function-arguments.rs +++ b/src/test/debug-info/function-arguments.rs @@ -8,6 +8,8 @@ // 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