From 203f96f71d86cc6a2d95b8337977835ac1a41c36 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 12 Jul 2013 10:16:54 +0200 Subject: [PATCH] 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 cc690f070ccf..574f7aad119c 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 207899fe3b51..6d85b99a79d6 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(); }