return ptr_metadata;
}
+//=-------------------------------------------------------------------------------------------------
+// Common facilities for record-like types (structs, enums, tuples)
+//=-------------------------------------------------------------------------------------------------
+
+enum MemberOffset {
+ FixedMemberOffset { bytes: uint },
+ // For ComputedMemberOffset, the offset is read from the llvm type definition
+ ComputedMemberOffset
+}
+
+// Description of a type member, which can either be a regular field (as in structs or tuples) or
+// an enum variant
+struct MemberDescription {
+ name: String,
+ llvm_type: Type,
+ type_metadata: DIType,
+ offset: MemberOffset,
+}
+
+// A factory for MemberDescriptions. It produces a list of member descriptions for some record-like
+// type. MemberDescriptionFactories are used to defer the creation of type member descriptions in
+// order to break cycles arising from recursive type definitions.
enum MemberDescriptionFactory {
- StructMD(StructMemberDescriptionFactory),
- TupleMD(TupleMemberDescriptionFactory),
- GeneralMD(GeneralMemberDescriptionFactory),
- EnumVariantMD(EnumVariantMemberDescriptionFactory)
+ StructMDF(StructMemberDescriptionFactory),
+ TupleMDF(TupleMemberDescriptionFactory),
+ EnumMDF(EnumMemberDescriptionFactory),
+ VariantMDF(VariantMemberDescriptionFactory)
}
impl MemberDescriptionFactory {
- fn create_member_descriptions(&self, cx: &CrateContext)
- -> Vec<MemberDescription> {
+ fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription> {
match *self {
- StructMD(ref this) => {
+ StructMDF(ref this) => {
this.create_member_descriptions(cx)
}
- TupleMD(ref this) => {
+ TupleMDF(ref this) => {
this.create_member_descriptions(cx)
}
- GeneralMD(ref this) => {
+ EnumMDF(ref this) => {
this.create_member_descriptions(cx)
}
- EnumVariantMD(ref this) => {
+ VariantMDF(ref this) => {
this.create_member_descriptions(cx)
}
}
}
}
+// A description of some recursive type. It can either be already finished (as with FinalMetadata)
+// or it is not yet finished, but contains all information needed to generate the missing parts of
+// the description. See the documentation section on Recursive Types at the top of this file for
+// more information.
+enum RecursiveTypeDescription {
+ UnfinishedMetadata {
+ cache_id: uint,
+ metadata_stub: DICompositeType,
+ llvm_type: Type,
+ file_metadata: DIFile,
+ member_description_factory: MemberDescriptionFactory,
+ },
+ FinalMetadata(DICompositeType)
+}
+
+impl RecursiveTypeDescription {
+ // Finishes up the description of the type in question (mostly by providing description of the
+ // fields of the given type) and returns the final type metadata.
+ fn finalize(&self, cx: &CrateContext) -> DICompositeType {
+ match *self {
+ FinalMetadata(metadata) => metadata,
+ UnfinishedMetadata {
+ cache_id,
+ metadata_stub,
+ llvm_type,
+ file_metadata,
+ ref member_description_factory
+ } => {
+ // Insert the stub into the cache in order to allow recursive references ...
+ debug_context(cx).created_types.borrow_mut()
+ .insert(cache_id, metadata_stub);
+
+ // ... then create the member descriptions ...
+ let member_descriptions = member_description_factory.create_member_descriptions(cx);
+
+ // ... and attach them to the stub to complete it.
+ set_members_of_composite_type(cx,
+ metadata_stub,
+ llvm_type,
+ member_descriptions.as_slice(),
+ file_metadata,
+ codemap::DUMMY_SP);
+ return metadata_stub;
+ }
+ }
+ }
+}
+
+
+//=-------------------------------------------------------------------------------------------------
+// Structs
+//=-------------------------------------------------------------------------------------------------
+
+// Creates MemberDescriptions for the fields of a struct
struct StructMemberDescriptionFactory {
fields: Vec<ty::field>,
is_simd: bool,
}
let field_size = if self.is_simd {
- machine::llsize_of_alloc(cx, type_of::type_of(cx, self.fields.get(0).mt.ty))
+ machine::llsize_of_alloc(cx, type_of::type_of(cx, self.fields.get(0).mt.ty)) as uint
} else {
0xdeadbeef
};
let offset = if self.is_simd {
assert!(field_size != 0xdeadbeef);
- FixedMemberOffset { bytes: i as u64 * field_size }
+ FixedMemberOffset { bytes: i * field_size }
} else {
ComputedMemberOffset
};
metadata_stub: struct_metadata_stub,
llvm_type: struct_llvm_type,
file_metadata: file_metadata,
- member_description_factory: StructMD(StructMemberDescriptionFactory {
+ member_description_factory: StructMDF(StructMemberDescriptionFactory {
fields: fields,
is_simd: ty::type_is_simd(cx.tcx(), struct_type),
span: span,
}
}
-enum RecursiveTypeDescription {
- UnfinishedMetadata {
- cache_id: uint,
- metadata_stub: DICompositeType,
- llvm_type: Type,
- file_metadata: DIFile,
- member_description_factory: MemberDescriptionFactory,
- },
- FinalMetadata(DICompositeType)
-}
-
-impl RecursiveTypeDescription {
-
- fn finalize(&self, cx: &CrateContext) -> DICompositeType {
- match *self {
- FinalMetadata(metadata) => metadata,
- UnfinishedMetadata {
- cache_id,
- metadata_stub,
- llvm_type,
- file_metadata,
- ref member_description_factory
- } => {
- // Insert the stub into the cache in order to allow recursive references ...
- debug_context(cx).created_types.borrow_mut()
- .insert(cache_id, metadata_stub);
-
- // ... then create the member descriptions ...
- let member_descriptions = member_description_factory.create_member_descriptions(cx);
- // ... and attach them to the stub to complete it.
- set_members_of_composite_type(cx,
- metadata_stub,
- llvm_type,
- member_descriptions.as_slice(),
- file_metadata,
- codemap::DUMMY_SP);
- return metadata_stub;
- }
- }
- }
-}
+//=-------------------------------------------------------------------------------------------------
+// Tuples
+//=-------------------------------------------------------------------------------------------------
+// Creates MemberDescriptions for the fields of a tuple
struct TupleMemberDescriptionFactory {
component_types: Vec<ty::t> ,
span: Span,
span),
llvm_type: tuple_llvm_type,
file_metadata: file_metadata,
- member_description_factory: TupleMD(TupleMemberDescriptionFactory {
+ member_description_factory: TupleMDF(TupleMemberDescriptionFactory {
component_types: Vec::from_slice(component_types),
span: span,
})
}
}
-struct GeneralMemberDescriptionFactory {
+
+//=-------------------------------------------------------------------------------------------------
+// Enums
+//=-------------------------------------------------------------------------------------------------
+
+// Describes the members of an enum value: An enum is described as a union of structs in DWARF. This
+// MemberDescriptionFactory provides the description for the members of this union; so for every
+// variant of the given enum, this factory will produce one MemberDescription (all with no name and
+// a fixed offset of zero bytes).
+struct EnumMemberDescriptionFactory {
type_rep: Rc<adt::Repr>,
variants: Rc<Vec<Rc<ty::VariantInfo>>>,
- discriminant_type_metadata: ValueRef,
+ discriminant_type_metadata: DIType,
containing_scope: DIScope,
file_metadata: DIFile,
span: Span,
}
-impl GeneralMemberDescriptionFactory {
- fn create_member_descriptions(&self, cx: &CrateContext)
- -> Vec<MemberDescription> {
+impl EnumMemberDescriptionFactory {
+ fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription> {
// Capture type_rep, so we don't have to copy the struct_defs array
let struct_defs = match *self.type_rep {
adt::General(_, ref struct_defs) => struct_defs,
describe_enum_variant(cx,
struct_def,
&**self.variants.get(i),
- Some(self.discriminant_type_metadata),
+ RegularDiscriminant(self.discriminant_type_metadata),
self.containing_scope,
self.file_metadata,
self.span);
}
}
-struct EnumVariantMemberDescriptionFactory {
+// Creates MemberDescriptions for the fields of a single enum variant
+struct VariantMemberDescriptionFactory {
args: Vec<(String, ty::t)> ,
discriminant_type_metadata: Option<DIType>,
span: Span,
}
-impl EnumVariantMemberDescriptionFactory {
- fn create_member_descriptions(&self, cx: &CrateContext)
- -> Vec<MemberDescription> {
+impl VariantMemberDescriptionFactory {
+ fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription> {
self.args.iter().enumerate().map(|(i, &(ref name, ty))| {
MemberDescription {
name: name.to_string(),
}
}
+enum EnumDiscriminantInfo {
+ RegularDiscriminant(DIType),
+ OptimizedDiscriminant(uint),
+ NoDiscriminant
+}
+
+// Returns a tuple of (1) type_metadata_stub of the variant, (2) the llvm_type of the variant, and
+// (3) a MemberDescriptionFactory for producing the descriptions of the fields of the variant. This
+// is a rudimentary version of a full RecursiveTypeDescription.
fn describe_enum_variant(cx: &CrateContext,
struct_def: &adt::Struct,
variant_info: &ty::VariantInfo,
- discriminant_type_metadata: Option<DIType>,
+ discriminant_info: EnumDiscriminantInfo,
containing_scope: DIScope,
file_metadata: DIFile,
span: Span)
};
// If this is not a univariant enum, there is also the (unnamed) discriminant field
- if discriminant_type_metadata.is_some() {
- arg_names.insert(0, "".to_string());
- }
+ match discriminant_info {
+ RegularDiscriminant(_) => arg_names.insert(0, "".to_string()),
+ _ => { /* do nothing */ }
+ };
// Build an array of (field name, field type) pairs to be captured in the factory closure.
let args: Vec<(String, ty::t)> = arg_names.iter()
.collect();
let member_description_factory =
- EnumVariantMD(EnumVariantMemberDescriptionFactory {
+ VariantMDF(VariantMemberDescriptionFactory {
args: args,
- discriminant_type_metadata: discriminant_type_metadata,
+ discriminant_type_metadata: match discriminant_info {
+ RegularDiscriminant(discriminant_type_metadata) => Some(discriminant_type_metadata),
+ _ => None
+ },
span: span,
});
describe_enum_variant(cx,
struct_def,
&**variants.get(0),
- None,
+ NoDiscriminant,
containing_scope,
file_metadata,
span);
metadata_stub: enum_metadata,
llvm_type: enum_llvm_type,
file_metadata: file_metadata,
- member_description_factory: GeneralMD(GeneralMemberDescriptionFactory {
+ member_description_factory: EnumMDF(EnumMemberDescriptionFactory {
type_rep: type_rep.clone(),
variants: variants,
discriminant_type_metadata: discriminant_type_metadata,
adt::RawNullablePointer { nnty, .. } => {
FinalMetadata(type_metadata(cx, nnty, span))
}
- adt::StructWrappedNullablePointer { nonnull: ref struct_def, nndiscr, .. } => {
+ adt::StructWrappedNullablePointer { nonnull: ref struct_def, nndiscr, ptrfield, .. } => {
let (metadata_stub,
variant_llvm_type,
member_description_factory) =
describe_enum_variant(cx,
struct_def,
&**variants.get(nndiscr as uint),
- None,
+ OptimizedDiscriminant(ptrfield),
containing_scope,
file_metadata,
span);
}
}
-enum MemberOffset {
- FixedMemberOffset { bytes: u64 },
- // For ComputedMemberOffset, the offset is read from the llvm type definition
- ComputedMemberOffset
-}
-
-struct MemberDescription {
- name: String,
- llvm_type: Type,
- type_metadata: DIType,
- offset: MemberOffset,
-}
-
/// Creates debug information for a composite type, that is, anything that results in a LLVM struct.
///
/// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.