about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMichael Woerister <michaelwoerister@gmail>2013-07-11 12:51:47 +0200
committerMichael Woerister <michaelwoerister@gmail>2013-07-19 07:57:38 +0200
commite0108a47abcd1977670aa2ca0e5e88321cf789bf (patch)
treee70ec40498b682d88b4496cc7588c7a68a74341b /src
parent70e5c08e39564b1ce69aeadb287fc4296ebdf04a (diff)
downloadrust-e0108a47abcd1977670aa2ca0e5e88321cf789bf.tar.gz
rust-e0108a47abcd1977670aa2ca0e5e88321cf789bf.zip
debuginfo: DI generation for enums uses adt::represent_type() now.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/trans/adt.rs2
-rw-r--r--src/librustc/middle/trans/debuginfo.rs156
-rw-r--r--src/test/debug-info/borrowed-enum.rs2
-rw-r--r--src/test/debug-info/managed-enum.rs2
-rw-r--r--src/test/debug-info/struct-in-enum.rs2
-rw-r--r--src/test/debug-info/struct-style-enum.rs2
-rw-r--r--src/test/debug-info/tuple-style-enum.rs2
-rw-r--r--src/test/debug-info/unique-enum.rs2
8 files changed, 163 insertions, 7 deletions
diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs
index 821242d64c9..fd38ec39bb1 100644
--- a/src/librustc/middle/trans/adt.rs
+++ b/src/librustc/middle/trans/adt.rs
@@ -94,7 +94,7 @@ pub enum Repr {
 }
 
 /// For structs, and struct-like parts of anything fancier.
-struct Struct {
+pub struct Struct {
     size: u64,
     align: u64,
     packed: bool,
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index 48ab0566178..93a6ab4fcd9 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -50,6 +50,7 @@ use middle::trans::common::*;
 use middle::trans::machine;
 use middle::trans::type_of;
 use middle::trans::type_::Type;
+use middle::trans::adt;
 use middle::trans;
 use middle::ty;
 use util::ppaux::ty_to_str;
@@ -560,6 +561,161 @@ fn create_tuple_metadata(cx: &mut CrateContext,
         span);
 }
 
+// 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);
+    }
+
+    // Prepare some data (llvm type, size, align, ...) about the discriminant. This data will be
+    // needed in all of the following cases.
+    let discriminant_llvm_type = Type::enum_discrim(cx);
+    let (discriminant_size, discriminant_align) = size_and_align_of(cx, discriminant_llvm_type);
+
+    assert!(Type::enum_discrim(cx) == cx.int_type);
+    let discriminant_type_metadata = get_or_create_type_metadata(cx, ty::mk_int(), span);
+
+    let variants : &[@ty::VariantInfo] = *ty::enum_variants(cx.tcx, enum_def_id);
+
+    let enumerators_metadata : ~[DIDescriptor] = variants
+        .iter()
+        .transform(|v| {
+            let name : &str = cx.sess.str_of(v.name);
+            let discriminant_value = v.disr_val as c_ulonglong;
+
+            do name.as_c_str |name| { unsafe {
+                llvm::LLVMDIBuilderCreateEnumerator(
+                    DIB(cx),
+                    name,
+                    discriminant_value)
+            }}
+        })
+        .collect();
+
+    let loc = span_start(cx, span);
+    let file_metadata = get_or_create_file_metadata(cx, loc.file.name);
+
+    let discriminant_type_metadata = do enum_name.as_c_str |enum_name| { unsafe {
+        llvm::LLVMDIBuilderCreateEnumerationType(
+            DIB(cx),
+            file_metadata,
+            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) => {
+            assert!(variants.len() == 1);
+            return create_adt_struct_metadata(cx, struct_def, variants[0], None, span);
+        }
+        adt::General(ref struct_defs) => {
+            let variants_member_metadata : ~[DIDescriptor] = do struct_defs
+                .iter()
+                .enumerate()
+                .transform |(i, struct_def)| {
+                    let variant_type_metadata = create_adt_struct_metadata(
+                        cx,
+                        struct_def,
+                        variants[i],
+                        Some(discriminant_type_metadata),
+                        span);
+
+                    do "".as_c_str |name| { unsafe {
+                        llvm::LLVMDIBuilderCreateMemberType(
+                            DIB(cx),
+                            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(
+                DIB(cx),
+                file_metadata,
+                enum_name,
+                file_metadata,
+                loc.line as c_uint,
+                bytes_to_bits(enum_type_size),
+                bytes_to_bits(enum_type_align),
+                0, // Flags
+                create_DIArray(DIB(cx), variants_member_metadata),
+                0) // RuntimeLang
+            }};
+        }
+        _ => { return ptr::null(); }
+    }
+
+    fn create_adt_struct_metadata(cx: &mut CrateContext,
+                                  struct_def: &adt::Struct,
+                                  variant_info: &ty::VariantInfo,
+                                  discriminant_type_metadata: Option<DIType>,
+                                  span: span)
+                               -> DICompositeType
+    {
+        let arg_llvm_types : ~[Type] = do struct_def.fields.map |&ty| { type_of::type_of(cx, ty) };
+        let arg_metadata : ~[DIType] = do struct_def.fields.iter().enumerate()
+            .transform |(i, &ty)| {
+                match discriminant_type_metadata {
+                    Some(metadata) if i == 0 => metadata,
+                    _                        => get_or_create_type_metadata(cx, ty, span)
+                }
+        }.collect();
+
+        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()) {
+            arg_names.insert(0, ~"");
+        }
+
+        let variant_llvm_type = Type::struct_(arg_llvm_types, struct_def.packed);
+        let variant_name : &str = cx.sess.str_of(variant_info.name);
+
+        return create_composite_type_metadata(
+            cx,
+            variant_llvm_type,
+            variant_name,
+            arg_llvm_types,
+            arg_names,
+            arg_metadata,
+            span);
+    }
+}
+
+#[cfg(stage0)]
 fn create_enum_metadata(cx: &mut CrateContext,
                         enum_type: ty::t,
                         enum_def_id: ast::def_id,
diff --git a/src/test/debug-info/borrowed-enum.rs b/src/test/debug-info/borrowed-enum.rs
index c73cddf0d89..8c9a7799a29 100644
--- a/src/test/debug-info/borrowed-enum.rs
+++ b/src/test/debug-info/borrowed-enum.rs
@@ -22,7 +22,7 @@
 // check:$2 = {{TheB, x = 0, y = 1229782938247303441}, {TheB, 0, 286331153, 286331153}}
 
 // debugger:print *univariant_ref
-// check:$3 = {{4820353753753434}}
+// check:$3 = {4820353753753434}
 
 // 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
diff --git a/src/test/debug-info/managed-enum.rs b/src/test/debug-info/managed-enum.rs
index 794a362e573..1a3600a7d8c 100644
--- a/src/test/debug-info/managed-enum.rs
+++ b/src/test/debug-info/managed-enum.rs
@@ -22,7 +22,7 @@
 // check:$2 = {{TheB, x = 0, y = 1229782938247303441}, {TheB, 0, 286331153, 286331153}}
 
 // debugger:print univariant->val
-// check:$3 = {{-9747455}}
+// check:$3 = {-9747455}
 
 // 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
diff --git a/src/test/debug-info/struct-in-enum.rs b/src/test/debug-info/struct-in-enum.rs
index c8ad621f6f0..6d4a40e193f 100644
--- a/src/test/debug-info/struct-in-enum.rs
+++ b/src/test/debug-info/struct-in-enum.rs
@@ -21,7 +21,7 @@
 // check:$2 = {{Case2, 0, {x = 286331153, y = 286331153, z = 4369}}, {Case2, 0, 1229782938247303441, 4369}}
 
 // debugger:print univariant
-// check:$3 = {{{x = 123, y = 456, z = 789}}}
+// check:$3 = {{x = 123, y = 456, z = 789}}
 
 struct Struct {
 	x: u32,
diff --git a/src/test/debug-info/struct-style-enum.rs b/src/test/debug-info/struct-style-enum.rs
index 2be15e0f80f..972772b07d2 100644
--- a/src/test/debug-info/struct-style-enum.rs
+++ b/src/test/debug-info/struct-style-enum.rs
@@ -24,7 +24,7 @@
 // check:$3 = {{Case3, a = 0, b = 22873, c = 22873, d = 22873, e = 22873}, {Case3, a = 0, b = 1499027801, c = 1499027801}, {Case3, a = 0, b = 6438275382588823897}}
 
 // debugger:print univariant
-// check:$4 = {{a = -1}}
+// check:$4 = {a = -1}
 
 // 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
diff --git a/src/test/debug-info/tuple-style-enum.rs b/src/test/debug-info/tuple-style-enum.rs
index 43b97a9bbfc..66e64a1e20a 100644
--- a/src/test/debug-info/tuple-style-enum.rs
+++ b/src/test/debug-info/tuple-style-enum.rs
@@ -24,7 +24,7 @@
 // check:$3 = {{Case3, 0, 22873, 22873, 22873, 22873}, {Case3, 0, 1499027801, 1499027801}, {Case3, 0, 6438275382588823897}}
 
 // debugger:print univariant
-// check:$4 = {{-1}}
+// check:$4 = {-1}
 
 // 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
diff --git a/src/test/debug-info/unique-enum.rs b/src/test/debug-info/unique-enum.rs
index c231ea5a42b..443f641a858 100644
--- a/src/test/debug-info/unique-enum.rs
+++ b/src/test/debug-info/unique-enum.rs
@@ -22,7 +22,7 @@
 // check:$2 = {{TheB, x = 0, y = 1229782938247303441}, {TheB, 0, 286331153, 286331153}}
 
 // debugger:print *univariant
-// check:$3 = {{123234}}
+// check:$3 = {123234}
 
 // 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