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};
current_debug_location: Cell<DebugLocation>,
created_files: RefCell<HashMap<~str, DIFile>>,
created_types: RefCell<HashMap<uint, DIType>>,
+ created_enum_disr_types: RefCell<HashMap<ast::DefId, DIType>>,
namespace_map: RefCell<HashMap<Vec<ast::Name> , @NamespaceTreeNode>>,
// This collection is used to assert that composite types (structs, enums, ...) have their
// members only set once:
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()),
};
.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);
}
}
};
+
+ 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 {