debuginfo: Composite type reform and enum support. #7710

Closed
wants to merge 26 commits into
from

Projects

None yet

3 participants

@michaelwoerister
Contributor

This pull request includes various improvements:

  • Composite types (structs, tuples, boxes, etc) are now handled more cleanly by debuginfo generation. Most notably, field offsets are now extracted directly from LLVM types, as opposed to trying to reconstruct them. This leads to more stable handling of edge cases (e.g. packed structs or structs implementing drop).
  • debuginfo.rs in general has seen a major cleanup. This includes better formatting, more readable variable and function names, removal of dead code, and better factoring of functionality.
  • Handling of VariantInfo in ty.rs has been improved. That is, the type VariantInfo = @VariantInfo_ typedef has been replaced with explicit uses of @VariantInfo, and the duplicated logic for creating VariantInfo instances in ty::enum_variants() and typeck::check::mod::check_enum_variants() has been unified into a single constructor function. Both function now look nicer too :)
  • Debug info generation for enum types is now mostly supported. This includes:
    • Good support for C-style enums. Both DWARF and gdb know how to handle them.
    • Proper description of tuple- and struct-style enum variants as unions of structs.
    • Proper handling of univariant enums without discriminator field.
    • Unfortunately gdb always prints all possible interpretations of a union, so debug output of enums is verbose and unintuitive. Neither LLVM nor gdb support DWARF's DW_TAG_variant which allows to properly describe tagged unions. Adding support for this to LLVM seems doable. gdb however is another story. In the future we might be able to use gdb's Python scripting support to alleviate this problem. In agreement with @jdm this is not a high priority for now.
  • The debuginfo test suite has been extended with 14 test files including tests for packed structs (with Drop), boxed structs, boxed vecs, vec slices, c-style enums (standalone and embedded), empty enums, tuple- and struct-style enums, and various pointer types to the above.

What is not yet included is DI support for some enum edge-cases represented as described in trans::adt::NullablePointer.

Cheers,
Michael

PS: closes #7819, fixes #7712

@jdm
Contributor
jdm commented Jul 11, 2013

\o/

I'll work my way through this today, hopefully.

@jdm
Contributor
jdm commented Jul 12, 2013

One general naming comment: it seems like some functions now use a get_or_create prefix, while others just use create. Is this reflecting the caching nature of their implementation? That doesn't seem important to distinguish to me, and I think names like block_metadata and file_metadata would be descriptive of their purpose.

@jdm
Contributor
jdm commented Jul 12, 2013

Style nits: I'd like to move away from multi-line unsafe blocks opening on the same line as existing code.

@michaelwoerister
Contributor

Style nits: I'd like to move away from multi-line unsafe blocks opening on the same line as existing code.

You mean something like this:

do member_name.as_c_str |member_name| { unsafe {
    llvm::LLVMDIBuilderCreateMemberType(
        DIB(cx),
        file_metadata,
        ...,
        0,
        member_type_metadata[i])
}}

would turn into the following?

do member_name.as_c_str |member_name| { 
    unsafe {
        llvm::LLVMDIBuilderCreateMemberType(
            DIB(cx),
            file_metadata,
            ...,
            0,
            member_type_metadata[i])
    }
}
@michaelwoerister
Contributor

...and I think names like block_metadata and file_metadata would be descriptive of their purpose.

Yeah, I definitely went for verbosity in the naming style. This was certainly influenced by my recent experiences of having to try to understand this code without much prior knowledge or documentation. My thinking behind this was that one should be able to get some insight into what's going on by just reading part of the code, because often a newcomer (or someone doing a quick fix in some code otherwise not known to them) will not be aware of the internal workings of these functions (such as that LLVM will merge duplicate metadata anyway and it is thus no semantic difference whether caching happens or not).

If you find this exceedingly ugly, we can change it of course. But otherwise I would still vote for some redundancy in the naming if it improves readability (even if it impedes writeability a bit).

That being said, I'm not completely satisfied with the naming in the module either. Maybe your approach with just file_metadata (with neither create_ nor get_or_create_ prefix) plus some good documentation in the form of comments would be the best solution.

@jdm
Contributor
jdm commented Jul 15, 2013
  •    return create_composite_type_metadata(cx, Type::nil(), enum_name, &[], &[], &[], span); 
    

Are the &s necessary here?

@jdm
Contributor
jdm commented Jul 15, 2013

With regards to the stage0 thing, I'm inclined to just hold off merging this until we get a new snapshot that makes it irrelevant.

@jdm
Contributor
jdm commented Jul 15, 2013

There are various instances of code like let variant_name : &str = cx.sess.str_of(variant_info.name);. The rustc style is to put the : immediately after the name.

@jdm jdm commented on an outdated diff Jul 15, 2013
src/librustc/middle/trans/debuginfo.rs
+// The stage0 snapshot does not yet support the fixes from PR #7557, so there are two versions of
+// following function for now
+#[cfg(not(stage0))]
+fn create_enum_metadata(cx: &mut CrateContext,
+ enum_type: ty::t,
+ enum_def_id: ast::def_id,
+ substs: &ty::substs,
+ span: span)
+ -> DIType {
+
+ let enum_name = ty_to_str(cx.tcx, enum_type);
+
+ // For empty enums there is an early exit. Just describe it as an empty struct with the
+ // appropriate type name
+ if ty::type_is_empty(cx.tcx, enum_type) {
+ return create_composite_type_metadata(cx, Type::nil(), enum_name, &[], &[], &[], span);
@jdm
jdm Jul 15, 2013 Contributor

Are the &s necessary here?

@jdm jdm and 1 other commented on an outdated diff Jul 15, 2013
src/librustc/middle/trans/debuginfo.rs
+ 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),
+ discriminant_type_metadata)
+ }};
+
+ let type_rep = adt::represent_type(cx, enum_type);
+
+ match *type_rep {
+ adt::CEnum(*) => {
+ return discriminant_type_metadata;
+ }
+ adt::Univariant(ref struct_def, _destroyed_flag) => {
@jdm
jdm Jul 15, 2013 Contributor

This can just be _

@michaelwoerister
michaelwoerister Jul 16, 2013 Contributor

I'll remove it. However, in these cases I'm never sure which version I like better. It often helps readability to know what is ignored here.

@jdm jdm commented on an outdated diff Jul 15, 2013
src/librustc/middle/trans/debuginfo.rs
+ file_metadata,
+ name,
+ file_metadata,
+ loc.line as c_uint,
+ bytes_to_bits(struct_def.size as uint),
+ bytes_to_bits(struct_def.align as uint),
+ bytes_to_bits(0),
+ 0,
+ variant_type_metadata)
+ }}
+ }.collect();
+
+ let enum_llvm_type = type_of::type_of(cx, enum_type);
+ let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
+
+ return do enum_name.as_c_str |enum_name| { unsafe { llvm::LLVMDIBuilderCreateUnionType(
@jdm
jdm Jul 15, 2013 Contributor

Next line, please.

@jdm jdm commented on an outdated diff Jul 15, 2013
src/librustc/middle/trans/debuginfo.rs
- let loc = span_start(cx, span);
- let file_md = create_file(cx, loc.file.name);
-
- let mut scx = StructContext::new(cx, ty_to_str(cx.tcx, struct_type), file_md, loc.line);
- for fields.iter().advance |field| {
- let field_t = field.mt.ty;
- let ty_md = create_ty(cx, field_t, span);
- let (size, align) = size_and_align_of(cx, field_t);
- scx.add_member(cx.sess.str_of(field.ident), loc.line, size, align, ty_md);
+ let mut arg_names = match variant_info.arg_names {
+ Some(ref names) => do names.map |ident| { cx.sess.str_of(*ident).to_owned() },
+ None => do variant_info.args.map |_| { ~"" }
+ };
+
+ if (discriminant_type_metadata.is_some()) {
@jdm
jdm Jul 15, 2013 Contributor

Unnecessary outer parentheses.

@jdm jdm commented on an outdated diff Jul 15, 2013
src/librustc/middle/trans/debuginfo.rs
+
+ let int_type = ty::mk_int();
+ let nil_pointer_type = ty::mk_nil_ptr(cx.tcx);
+
+ let member_types_metadata = [
+ get_or_create_type_metadata(cx, int_type, span),
+ get_or_create_type_metadata(cx, nil_pointer_type, span),
+ get_or_create_type_metadata(cx, nil_pointer_type, span),
+ get_or_create_type_metadata(cx, nil_pointer_type, span),
+ content_type_metadata
+ ];
+
+ return create_composite_type_metadata(
+ cx,
+ box_llvm_type,
+ "box name",
@jdm
jdm Jul 15, 2013 Contributor

BoxedType, perhaps?

@jdm jdm commented on an outdated diff Jul 15, 2013
src/librustc/middle/trans/debuginfo.rs
+ get_or_create_type_metadata(cx, nil_pointer_type, span),
+ get_or_create_type_metadata(cx, nil_pointer_type, span),
+ content_type_metadata
+ ];
+
+ return create_composite_type_metadata(
+ cx,
+ box_llvm_type,
+ "box name",
+ member_llvm_types,
+ member_names,
+ member_types_metadata,
+ span);
+
+ // Unfortunately, we cannot assert anything but the correct types here---and not whether the
+ // 'next' and 'prev' pointers are in the order.
@jdm
jdm Jul 15, 2013 Contributor

"are in the correct order."

@jdm jdm commented on an outdated diff Jul 15, 2013
src/librustc/lib/llvm.rs
+ AlignInBits: c_ulonglong,
+ Elements: ValueRef,
+ ClassType: ValueRef) -> ValueRef;
+
+ #[fast_ffi]
+ pub unsafe fn LLVMDIBuilderCreateUnionType(
+ Builder: DIBuilderRef,
+ Scope: ValueRef,
+ Name: *c_char,
+ File: ValueRef,
+ LineNumber: c_uint,
+ SizeInBits: c_ulonglong,
+ AlignInBits: c_ulonglong,
+ Flags: c_uint ,
+ Elements: ValueRef,
+ RunTimeLang : c_uint) -> ValueRef;
@jdm
jdm Jul 15, 2013 Contributor

There are many places in this PR that have a space before the : in type signatures; rustc style is to have the : immediately follow the name.

@jdm jdm commented on an outdated diff Jul 15, 2013
src/librustc/middle/trans/debuginfo.rs
+ get_or_create_type_metadata(cx, nil_pointer_type, span),
+ content_type_metadata
+ ];
+
+ return create_composite_type_metadata(
+ cx,
+ box_llvm_type,
+ "box name",
+ member_llvm_types,
+ member_names,
+ member_types_metadata,
+ span);
+
+ // Unfortunately, we cannot assert anything but the correct types here---and not whether the
+ // 'next' and 'prev' pointers are in the order.
+ fn box_layout_is_as_expected(cx: &CrateContext,
@jdm
jdm Jul 15, 2013 Contributor

s/as_expected/correct/

@jdm jdm commented on an outdated diff Jul 15, 2013
src/librustc/middle/trans/debuginfo.rs
- box_scx.add_member(
- "refcnt",
+fn create_fixed_vec_metadata(cx: &mut CrateContext,
+ element_type: ty::t,
+ len: uint,
+ span: span)
+ -> DIType {
+ let element_type_metadata = get_or_create_type_metadata(cx, element_type, span);
+ let element_llvm_type = type_of::type_of(cx, element_type);
+ let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type);
+
+ let subrange = unsafe { llvm::LLVMDIBuilderGetOrCreateSubrange(
@jdm
jdm Jul 15, 2013 Contributor

Function call on next line.

@jdm jdm commented on an outdated diff Jul 15, 2013
src/librustc/middle/trans/debuginfo.rs
- let (vp, vpsize, vpalign) = voidptr(cx);
- box_scx.add_member("tydesc", 0, vpsize, vpalign, vp);
- box_scx.add_member("prev", 0, vpsize, vpalign, vp);
- box_scx.add_member("next", 0, vpsize, vpalign, vp);
- let size = 2 * sys::size_of::<int>();
- let align = sys::min_align_of::<int>();
- box_scx.add_member("boxed", 0, size, align, vec_md);
- let mdval = box_scx.finalize();
- return mdval;
+ let subscripts = create_DIArray(DIB(cx), [subrange]);
+ return unsafe { llvm::LLVMDIBuilderCreateArrayType(
@jdm
jdm Jul 15, 2013 Contributor

Function call on next line. I'll stop pointing these out now; please do a search for "{ llvm::" and fix any that show up.

@jdm jdm commented on an outdated diff Jul 15, 2013
src/librustc/middle/trans/debuginfo.rs
- let loc = span_start(cx, span);
- let file_md = create_file(cx, loc.file.name);
- let elem_ty_md = create_ty(cx, elem_t, span);
- let uint_type = create_basic_type(cx, ty::mk_uint(), span);
- let elem_ptr = create_pointer_type(cx, elem_t, span, elem_ty_md);
+ let element_type_metadata = get_or_create_type_metadata(cx, element_type, span);
+ let element_llvm_type = type_of::type_of(cx, element_type);
+ let (element_size, element_align) = size_and_align_of(cx, element_llvm_type);
+
+ let vec_llvm_type = Type::vec(cx.sess.targ_cfg.arch, &element_llvm_type);
+ let vec_type_name = &"vec";
@jdm
jdm Jul 15, 2013 Contributor

This doesn't seem like a useful temporary. Just pass the string as an argument.

@jdm jdm commented on an outdated diff Jul 15, 2013
src/librustc/middle/trans/debuginfo.rs
- let mut scx = StructContext::new(cx, ty_to_str(cx.tcx, vec_t), file_md, 0);
- let (_, ptr_size, ptr_align) = voidptr(cx);
- scx.add_member("vec", 0, ptr_size, ptr_align, elem_ptr);
- scx.add_member("length", 0, sys::size_of::<uint>(), sys::min_align_of::<uint>(), uint_type);
- return scx.finalize();
+ // fill alloc elements
@jdm
jdm Jul 15, 2013 Contributor

Make these line up with the line below?

@jdm jdm commented on an outdated diff Jul 15, 2013
src/librustc/middle/trans/debuginfo.rs
+ debug!("create_vec_slice_metadata: %?", ty::get(vec_type));
+
+ let slice_llvm_type = type_of::type_of(cx, vec_type);
+ let slice_type_name = ty_to_str(cx.tcx, vec_type);
+
+ let member_llvm_types = slice_llvm_type.field_types();
+ let member_names = &[~"data_ptr", ~"size_in_bytes"];
+
+ assert!(slice_layout_is_as_expected(cx, member_llvm_types, element_type));
+
+ let data_ptr_type = ty::mk_ptr(cx.tcx, ty::mt { ty: element_type, mutbl: ast::m_const });
+
+ let member_type_metadata = &[
+ get_or_create_type_metadata(cx, data_ptr_type, span),
+ get_or_create_type_metadata(cx, ty::mk_uint(), span)
+ ];
@jdm
jdm Jul 15, 2013 Contributor

Unindent.

@jdm jdm commented on an outdated diff Jul 15, 2013
src/librustc/middle/trans/debuginfo.rs
+ vec_type: ty::t,
+ element_type: ty::t,
+ span: span)
+ -> DICompositeType {
+
+ debug!("create_vec_slice_metadata: %?", ty::get(vec_type));
+
+ let slice_llvm_type = type_of::type_of(cx, vec_type);
+ let slice_type_name = ty_to_str(cx.tcx, vec_type);
+
+ let member_llvm_types = slice_llvm_type.field_types();
+ let member_names = &[~"data_ptr", ~"size_in_bytes"];
+
+ assert!(slice_layout_is_as_expected(cx, member_llvm_types, element_type));
+
+ let data_ptr_type = ty::mk_ptr(cx.tcx, ty::mt { ty: element_type, mutbl: ast::m_const });
@jdm
jdm Jul 15, 2013 Contributor

Make this m_imm instead, m_const should be going away.

@jdm jdm commented on an outdated diff Jul 15, 2013
src/librustc/middle/trans/debuginfo.rs
+
+ let member_type_metadata = &[
+ get_or_create_type_metadata(cx, data_ptr_type, span),
+ get_or_create_type_metadata(cx, ty::mk_uint(), span)
+ ];
+
+ return create_composite_type_metadata(
+ cx,
+ slice_llvm_type,
+ slice_type_name,
+ member_llvm_types,
+ member_names,
+ member_type_metadata,
+ span);
+
+ fn slice_layout_is_as_expected(cx: &mut CrateContext,
@jdm
jdm Jul 15, 2013 Contributor

slice_layout_is_correct

@jdm jdm commented on an outdated diff Jul 15, 2013
src/librustc/middle/ty.rs
- @VariantInfo_{
- args: arg_tys,
- ctor_ty: ctor_ty,
- name: variant.node.name,
- id: ast_util::local_def(variant.node.id),
- disr_val: disr_val,
- vis: variant.node.vis
- }
+ let mut discriminant = match last_discriminant {
+ Some(val) => val + 1,
+ None => INITIAL_DISCRIMINANT_VALUE
+ };
+
+ match variant.node.disr_expr {
+ Some(e) => match const_eval::eval_const_expr_partial(cx, e) {
+ Ok(const_eval::const_int(val)) => { discriminant = val as int; }
@jdm
jdm Jul 15, 2013 Contributor

Ok(const_eval::const_int(val)) => discriminant = val as int,

@jdm jdm commented on an outdated diff Jul 15, 2013
src/librustc/middle/ty.rs
+ vis: ast_variant.node.vis
+ };
+ },
+ ast::struct_variant_kind(ref struct_def) => {
+
+ let fields : &[@struct_field] = struct_def.fields;
+
+ assert!(fields.len() > 0);
+
+ let arg_tys = ty_fn_args(ctor_ty).map(|a| *a);
+ let arg_names = do fields.map |field| {
+ match field.node.kind {
+ named_field(ident, _visibility) => ident,
+ unnamed_field => cx.sess.bug(
+ "enum_variants: all fields in struct must have a name")
+ }};
@jdm
jdm Jul 15, 2013 Contributor

Split these up, please.

@jdm jdm commented on an outdated diff Jul 15, 2013
src/librustc/middle/ty.rs
+ name: ast_variant.node.name,
+ id: ast_util::local_def(ast_variant.node.id),
+ disr_val: discriminant,
+ vis: ast_variant.node.vis
+ };
+ },
+ ast::struct_variant_kind(ref struct_def) => {
+
+ let fields : &[@struct_field] = struct_def.fields;
+
+ assert!(fields.len() > 0);
+
+ let arg_tys = ty_fn_args(ctor_ty).map(|a| *a);
+ let arg_names = do fields.map |field| {
+ match field.node.kind {
+ named_field(ident, _visibility) => ident,
@jdm
jdm Jul 15, 2013 Contributor

_ instead of _visibility

@jdm jdm commented on an outdated diff Jul 15, 2013
src/librustc/middle/ty.rs
do enum_variants(cx, id).iter().transform |variant_info| {
let substd_args = variant_info.args.iter()
.transform(|aty| subst(cx, substs, *aty)).collect();
let substd_ctor_ty = subst(cx, substs, variant_info.ctor_ty);
- @VariantInfo_{args: substd_args, ctor_ty: substd_ctor_ty,
+ @VariantInfo{args: substd_args, ctor_ty: substd_ctor_ty,
@jdm
jdm Jul 15, 2013 Contributor

Add a space here before the {.

@jdm jdm and 1 other commented on an outdated diff Jul 15, 2013
src/librustc/middle/ty.rs
- args: arg_tys,
- ctor_ty: ctor_ty,
- name: variant.node.name,
- id: ast_util::local_def(variant.node.id),
- disr_val: disr_val,
- vis: variant.node.vis
- }
+ let mut discriminant = match last_discriminant {
+ Some(val) => val + 1,
+ None => INITIAL_DISCRIMINANT_VALUE
+ };
+
+ match variant.node.disr_expr {
+ Some(e) => match const_eval::eval_const_expr_partial(cx, e) {
+ Ok(const_eval::const_int(val)) => { discriminant = val as int; }
+ _ => {}
@jdm
jdm Jul 15, 2013 Contributor

Previously we would ICE here, but now we'll silently use the previous discriminant.

@michaelwoerister
michaelwoerister Jul 16, 2013 Contributor

Yeah, this is kind of a problematic case. I too had it triggering an ICE here but that would break a compile-fail test case because the error message was duplicated (once for this method and another time in typeck::check::mod::check_enum_variants()).
But this was before I moved discriminant calculation out of VariantInfo::from_ast_variant()---I'll try to put the ICE back in and see if it passes the test.

The problem here is that the order between this method and type checking is not fixed. Most of the time the enum will be type checked before this method is called for it but in some rare cases (see #6362 and #7527) this method is called before the type check. Which in turn produces an ICE instead of an compilation error. Maybe this should be cleaned up anyway (by always running the type checking before).

@jdm
jdm Jul 16, 2013 Contributor

You could make it a span_err instead, perhaps? That would allow compile-fail tests to do their magic.

@jdm jdm commented on an outdated diff Jul 15, 2013
src/librustc/middle/typeck/check/mod.rs
- ccx.tcx, local_def(v.node.id)).map(|cf|
- ty::node_id_to_type(ccx.tcx, cf.id.node)))
- }
+ match v.node.disr_expr {
+ Some(e) => {
+ debug!("disr expr, checking %s", pprust::expr_to_str(e, ccx.tcx.sess.intr()));
+
+ let declty = ty::mk_int();
+ let fcx = blank_fn_ctxt(ccx, rty, e.id);
+ check_const_with_ty(fcx, e.span, e, declty);
+ // check_expr (from check_const pass) doesn't guarantee
+ // that the expression is in an form that eval_const_expr can
+ // handle, so we may still get an internal compiler error
+
+ match const_eval::eval_const_expr_partial(ccx.tcx, e) {
+ Ok(const_eval::const_int(val)) => { current_disr_val = val as int; }
@jdm
jdm Jul 15, 2013 Contributor

Ok(const_eval::const_int(val)) => current_disr_val = val as int,

@jdm jdm commented on the diff Jul 15, 2013
src/test/debug-info/box.rs
@@ -8,20 +8,18 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// xfail-test
@jdm
jdm Jul 15, 2013 Contributor

This probably needs xfail-win32 like all the others.

@jdm jdm commented on the diff Jul 16, 2013
src/test/debug-info/boxed-vec.rs
+// 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 managed->val.fill
+// check:$1 = 24
+// debugger:print *((uint64_t[3]*)(managed->val.elements))
@jdm
jdm Jul 16, 2013 Contributor

This is another good reason to create some rust pretty-printers for gdb in the future. We should file an issue about it.

@jdm jdm commented on the diff Jul 16, 2013
src/test/debug-info/boxed-struct.rs
@@ -0,0 +1,57 @@
+// 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.
+
@jdm
jdm Jul 16, 2013 Contributor

xfail-win32. Please make sure all subsequent new test files have this as well.

@jdm jdm commented on the diff Jul 16, 2013
src/test/debug-info/struct-with-destructor.rs
@@ -8,8 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// xfail-test
@jdm
jdm Jul 16, 2013 Contributor

xfail-win32

@jdm jdm commented on the diff Jul 16, 2013
src/test/debug-info/vec.rs
@@ -8,28 +8,18 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// xfail-test
@jdm
jdm Jul 16, 2013 Contributor

xfail-win32

@jdm
Contributor
jdm commented Jul 16, 2013

Wow. This is a fantastic pull request, and I love how thorough your tests are. I stand by my earlier request with regards to the naming; I believe that whether a metadata function caches or not is of no interest to a user of the method, and documenting its behaviour via comments will be enough. With regard to my request to move unsafe blocks to their own lines, your snippet illustrates my desire correctly.

@michaelwoerister
Contributor

Thanks for taking such a close look at it. These code reviews are incredibly useful.

I'll add commit fixing all the style issues and also handle the memory layout changes from here: #7816

@michaelwoerister
Contributor

OK, unique vecs should be supported properly again. I hope rebasing did not mess up the pull request.

@michaelwoerister
Contributor

Added fix for issue #7712 and did some manual merging required by more current mozilla/master.

@jdm
Contributor
jdm commented Jul 18, 2013

Ok, rebase this (sorry :/) and I'll r+ it. I'm not hearing any motion on the snapshot process, since there's a mystery usage regression people don't want to include.

michaelwoerister added some commits Jun 26, 2013
@michaelwoerister michaelwoerister debuginfo: Began refactoring of composite type handling. 976d7a5
@michaelwoerister michaelwoerister debuginfo: Renamed *reference-to-* test cases to *borrowed-* 1b20831
@michaelwoerister michaelwoerister debuginfo: Removed some misleading comments from test cases. 7a31a3e
@michaelwoerister michaelwoerister debuginfo: Refactored vec slice code to use the new infrastructure. A…
…dded test cases for vec slices.
36ea756
@michaelwoerister michaelwoerister debuginfo: Refactoring of composite type info generation done.
There is no more StructContext now. Better support for boxed vectors in there too.
f424e93
@michaelwoerister michaelwoerister debuginfo: Replaced vec::mapi with iterator version. 6230ec1
@michaelwoerister michaelwoerister debuginfo: Added test cases for packed structs (/w drop) 99ebb81
@michaelwoerister michaelwoerister debuginfo: Added support for c-style enums. 739f3ee
@michaelwoerister michaelwoerister debuginfo: Support for tuple-style enums (WIP) f389bd8
@michaelwoerister michaelwoerister debuginfo: Better support for univariant tuple-style enums. 7cf0aac
@michaelwoerister michaelwoerister debuginfo: Added support for struct-style enums. 3b06df4
@michaelwoerister michaelwoerister debuginfo: Fixes related to changed memory layout of unique allocations 77a00cc
@michaelwoerister michaelwoerister Cleanup of ty::VariantInfo and related functions. 12d87d3
@michaelwoerister michaelwoerister debuginfo: Major code cleanup in debuginfo.rs a33d1b8
@michaelwoerister michaelwoerister debuginfo: Extended test suite with various tests for enums. 70e5c08
@michaelwoerister michaelwoerister debuginfo: DI generation for enums uses adt::represent_type() now. e0108a4
@michaelwoerister michaelwoerister debuginfo: Fixed unique pointers to data containing managed pointers. 7af2e6e
@michaelwoerister michaelwoerister debuginfo: Added support for Option<T>-like enums. eed2d0e
@michaelwoerister michaelwoerister debuginfo: Implemented trait_method branch in create_function_metadat…
…a().
72cf2ee
@michaelwoerister michaelwoerister debuginfo: Cleaned up style issues for pull request. b2aeb4b
@michaelwoerister michaelwoerister debuginfo: Adapted DI generation to new memory layout of unique vecs. e9baeab
@michaelwoerister michaelwoerister debuginfo: Added some documenting comments to debuginfo.rs a1c5c79
@michaelwoerister michaelwoerister debuginfo: Fixed issue 7712. d8c27c3
@michaelwoerister michaelwoerister debuginfo: Fixed some merge fallout. 6aa43c7
@michaelwoerister
Contributor

Rebased :)

@michaelwoerister
Contributor

Sorry about that. Compilation seems to break on mac because some new C functions from RustWrapper.cpp cannot be found by the linker. I added their names to rustllvm.def.in in michaelwoerister@b52eb4a. I hope this fixes the issue. Please re-approve.

@michaelwoerister
Contributor

Commit michaelwoerister@a1303cc should make the test cases pass on 32 bit machines. The tests removed were no particularly good idea in the first place.

@jdm
jdm commented on a1303cc Jul 20, 2013

r+

Contributor
bors replied Jul 20, 2013

saw approval from jdm
at michaelwoerister@a1303cc

Contributor
bors replied Jul 20, 2013

merging michaelwoerister/rust/WP4 = a1303cc into auto

Contributor
bors replied Jul 20, 2013

michaelwoerister/rust/WP4 = a1303cc merged ok, testing candidate = 8aae6ed

Contributor
bors replied Jul 20, 2013

fast-forwarding master to auto = 8aae6ed

@jdm
Contributor
jdm commented Jul 20, 2013

That makes sense.

@bors bors added a commit that referenced this pull request Jul 20, 2013
@bors bors auto merge of #7710 : michaelwoerister/rust/WP4, r=jdm
This pull request includes various improvements:

+ Composite types (structs, tuples, boxes, etc) are now handled more cleanly by debuginfo generation. Most notably, field offsets are now extracted directly from LLVM types, as opposed to trying to reconstruct them. This leads to more stable handling of edge cases (e.g. packed structs or structs implementing drop).

+ `debuginfo.rs` in general has seen a major cleanup. This includes better formatting, more readable variable and function names, removal of dead code, and better factoring of functionality.

+ Handling of `VariantInfo` in `ty.rs` has been improved. That is, the `type VariantInfo = @VariantInfo_` typedef has been replaced with explicit uses of @VariantInfo, and the duplicated logic for creating VariantInfo instances in `ty::enum_variants()` and `typeck::check::mod::check_enum_variants()` has been unified into a single constructor function. Both function now look nicer too :)

+ Debug info generation for enum types is now mostly supported. This includes:
  + Good support for C-style enums. Both DWARF and `gdb` know how to handle them.
  + Proper description of tuple- and struct-style enum variants as unions of structs.
  + Proper handling of univariant enums without discriminator field.
  + Unfortunately `gdb` always prints all possible interpretations of a union, so debug output of enums is verbose and unintuitive. Neither `LLVM` nor `gdb` support DWARF's `DW_TAG_variant` which allows to properly describe tagged unions. Adding support for this to `LLVM` seems doable. `gdb` however is another story. In the future we might be able to use `gdb`'s Python scripting support to alleviate this problem. In agreement with @jdm this is not a high priority for now.

+ The debuginfo test suite has been extended with 14 test files including tests for packed structs (with Drop), boxed structs, boxed vecs, vec slices, c-style enums (standalone and embedded), empty enums, tuple- and struct-style enums, and various pointer types to the above.

~~What is not yet included is DI support for some enum edge-cases represented as described in `trans::adt::NullablePointer`.~~

Cheers,
Michael

PS: closes #7819,  fixes #7712
8aae6ed
@bors bors closed this Jul 20, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment