debuginfo: Implement discriminator type metadata re-use.
An optimization for sharing the type metadata of generic enum discriminators between monomorphized instances (fixes issue #12840)
This commit is contained in:
parent
43e8ace76b
commit
c26d25466d
@ -130,6 +130,7 @@ use driver::session::{FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
|
|||||||
use lib::llvm::llvm;
|
use lib::llvm::llvm;
|
||||||
use lib::llvm::{ModuleRef, ContextRef, ValueRef};
|
use lib::llvm::{ModuleRef, ContextRef, ValueRef};
|
||||||
use lib::llvm::debuginfo::*;
|
use lib::llvm::debuginfo::*;
|
||||||
|
use metadata::csearch;
|
||||||
use middle::trans::adt;
|
use middle::trans::adt;
|
||||||
use middle::trans::common::*;
|
use middle::trans::common::*;
|
||||||
use middle::trans::datum::{Datum, Lvalue};
|
use middle::trans::datum::{Datum, Lvalue};
|
||||||
@ -178,6 +179,7 @@ pub struct CrateDebugContext {
|
|||||||
current_debug_location: Cell<DebugLocation>,
|
current_debug_location: Cell<DebugLocation>,
|
||||||
created_files: RefCell<HashMap<~str, DIFile>>,
|
created_files: RefCell<HashMap<~str, DIFile>>,
|
||||||
created_types: RefCell<HashMap<uint, DIType>>,
|
created_types: RefCell<HashMap<uint, DIType>>,
|
||||||
|
created_enum_disr_types: RefCell<HashMap<ast::DefId, DIType>>,
|
||||||
namespace_map: RefCell<HashMap<Vec<ast::Name> , @NamespaceTreeNode>>,
|
namespace_map: RefCell<HashMap<Vec<ast::Name> , @NamespaceTreeNode>>,
|
||||||
// This collection is used to assert that composite types (structs, enums, ...) have their
|
// This collection is used to assert that composite types (structs, enums, ...) have their
|
||||||
// members only set once:
|
// members only set once:
|
||||||
@ -196,6 +198,7 @@ impl CrateDebugContext {
|
|||||||
current_debug_location: Cell::new(UnknownLocation),
|
current_debug_location: Cell::new(UnknownLocation),
|
||||||
created_files: RefCell::new(HashMap::new()),
|
created_files: RefCell::new(HashMap::new()),
|
||||||
created_types: RefCell::new(HashMap::new()),
|
created_types: RefCell::new(HashMap::new()),
|
||||||
|
created_enum_disr_types: RefCell::new(HashMap::new()),
|
||||||
namespace_map: RefCell::new(HashMap::new()),
|
namespace_map: RefCell::new(HashMap::new()),
|
||||||
composite_types_completed: RefCell::new(HashSet::new()),
|
composite_types_completed: RefCell::new(HashSet::new()),
|
||||||
};
|
};
|
||||||
@ -1542,24 +1545,45 @@ fn prepare_enum_metadata(cx: &CrateContext,
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let discriminant_type_metadata = |inttype| {
|
let discriminant_type_metadata = |inttype| {
|
||||||
let discriminant_llvm_type = adt::ll_inttype(cx, inttype);
|
// We can reuse the type of the discriminant for all monomorphized instances of an enum
|
||||||
let (discriminant_size, discriminant_align) = size_and_align_of(cx, discriminant_llvm_type);
|
// because it doesn't depend on any type parameters. The def_id, uniquely identifying the
|
||||||
let discriminant_base_type_metadata = type_metadata(cx, adt::ty_of_inttype(inttype),
|
// enum's polytype acts as key in this cache.
|
||||||
codemap::DUMMY_SP);
|
let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types
|
||||||
enum_name.with_c_str(|enum_name| {
|
.borrow()
|
||||||
unsafe {
|
.find_copy(&enum_def_id);
|
||||||
llvm::LLVMDIBuilderCreateEnumerationType(
|
match cached_discriminant_type_metadata {
|
||||||
DIB(cx),
|
Some(discriminant_type_metadata) => discriminant_type_metadata,
|
||||||
containing_scope,
|
None => {
|
||||||
enum_name,
|
let discriminant_llvm_type = adt::ll_inttype(cx, inttype);
|
||||||
file_metadata,
|
let (discriminant_size, discriminant_align) =
|
||||||
loc.line as c_uint,
|
size_and_align_of(cx, discriminant_llvm_type);
|
||||||
bytes_to_bits(discriminant_size),
|
let discriminant_base_type_metadata = type_metadata(cx,
|
||||||
bytes_to_bits(discriminant_align),
|
adt::ty_of_inttype(inttype),
|
||||||
create_DIArray(DIB(cx), enumerators_metadata.as_slice()),
|
codemap::DUMMY_SP);
|
||||||
discriminant_base_type_metadata)
|
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);
|
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 {
|
enum MemberOffset {
|
||||||
|
Loading…
Reference in New Issue
Block a user