From c26d25466d93cefea6cf81ec3f0e64200a7150be Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 27 Mar 2014 15:47:13 +0100 Subject: [PATCH] debuginfo: Implement discriminator type metadata re-use. An optimization for sharing the type metadata of generic enum discriminators between monomorphized instances (fixes issue #12840) --- src/librustc/middle/trans/debuginfo.rs | 68 +++++++++++++++++++------- 1 file changed, 51 insertions(+), 17 deletions(-) diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 6f6484ae1a5..c2828b333ed 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -130,6 +130,7 @@ use driver::session::{FullDebugInfo, LimitedDebugInfo, NoDebugInfo}; use lib::llvm::llvm; use lib::llvm::{ModuleRef, ContextRef, ValueRef}; use lib::llvm::debuginfo::*; +use metadata::csearch; use middle::trans::adt; use middle::trans::common::*; use middle::trans::datum::{Datum, Lvalue}; @@ -178,6 +179,7 @@ pub struct CrateDebugContext { current_debug_location: Cell, created_files: RefCell>, created_types: RefCell>, + created_enum_disr_types: RefCell>, namespace_map: RefCell , @NamespaceTreeNode>>, // This collection is used to assert that composite types (structs, enums, ...) have their // members only set once: @@ -196,6 +198,7 @@ impl CrateDebugContext { current_debug_location: Cell::new(UnknownLocation), created_files: RefCell::new(HashMap::new()), created_types: RefCell::new(HashMap::new()), + created_enum_disr_types: RefCell::new(HashMap::new()), namespace_map: RefCell::new(HashMap::new()), composite_types_completed: RefCell::new(HashSet::new()), }; @@ -1542,24 +1545,45 @@ fn prepare_enum_metadata(cx: &CrateContext, .collect(); let discriminant_type_metadata = |inttype| { - let discriminant_llvm_type = adt::ll_inttype(cx, inttype); - let (discriminant_size, discriminant_align) = size_and_align_of(cx, discriminant_llvm_type); - let discriminant_base_type_metadata = type_metadata(cx, adt::ty_of_inttype(inttype), - codemap::DUMMY_SP); - enum_name.with_c_str(|enum_name| { - unsafe { - llvm::LLVMDIBuilderCreateEnumerationType( - DIB(cx), - containing_scope, - 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.as_slice()), - discriminant_base_type_metadata) + // We can reuse the type of the discriminant for all monomorphized instances of an enum + // because it doesn't depend on any type parameters. The def_id, uniquely identifying the + // enum's polytype acts as key in this cache. + let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types + .borrow() + .find_copy(&enum_def_id); + match cached_discriminant_type_metadata { + Some(discriminant_type_metadata) => discriminant_type_metadata, + None => { + let discriminant_llvm_type = adt::ll_inttype(cx, inttype); + let (discriminant_size, discriminant_align) = + size_and_align_of(cx, discriminant_llvm_type); + let discriminant_base_type_metadata = type_metadata(cx, + adt::ty_of_inttype(inttype), + codemap::DUMMY_SP); + let discriminant_name = get_enum_discriminant_name(cx, enum_def_id); + + let discriminant_type_metadata = discriminant_name.get().with_c_str(|name| { + unsafe { + llvm::LLVMDIBuilderCreateEnumerationType( + DIB(cx), + containing_scope, + name, + file_metadata, + loc.line as c_uint, + bytes_to_bits(discriminant_size), + bytes_to_bits(discriminant_align), + create_DIArray(DIB(cx), enumerators_metadata.as_slice()), + discriminant_base_type_metadata) + } + }); + + debug_context(cx).created_enum_disr_types + .borrow_mut() + .insert(enum_def_id, discriminant_type_metadata); + + discriminant_type_metadata } - }) + } }; let type_rep = adt::represent_type(cx, enum_type); @@ -1648,6 +1672,16 @@ fn prepare_enum_metadata(cx: &CrateContext, } } }; + + fn get_enum_discriminant_name(cx: &CrateContext, def_id: ast::DefId) -> token::InternedString { + let name = if def_id.krate == ast::LOCAL_CRATE { + cx.tcx.map.get_path_elem(def_id.node).name() + } else { + csearch::get_item_path(&cx.tcx, def_id).last().unwrap().name() + }; + + token::get_name(name) + } } enum MemberOffset {