Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc_target: factor out common fields of non-Single Variants. #59519

Merged
merged 1 commit into from Mar 31, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
57 changes: 34 additions & 23 deletions src/librustc/ty/layout.rs
Expand Up @@ -913,11 +913,13 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
}

return Ok(tcx.intern_layout(LayoutDetails {
variants: Variants::NicheFilling {
dataful_variant: i,
niche_variants,
niche: niche_scalar,
niche_start,
variants: Variants::Multiple {
discr: niche_scalar,
discr_kind: DiscriminantKind::Niche {
dataful_variant: i,
niche_variants,
niche_start,
},
variants: st,
},
fields: FieldPlacement::Arbitrary {
Expand Down Expand Up @@ -1137,8 +1139,9 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
}

tcx.intern_layout(LayoutDetails {
variants: Variants::Tagged {
tag,
variants: Variants::Multiple {
discr: tag,
discr_kind: DiscriminantKind::Tag,
variants: layout_variants,
},
fields: FieldPlacement::Arbitrary {
Expand Down Expand Up @@ -1293,8 +1296,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
}
}

Variants::NicheFilling { .. } |
Variants::Tagged { .. } => {
Variants::Multiple { ref discr, ref discr_kind, .. } => {
debug!("print-type-size `{:#?}` adt general variants def {}",
layout.ty, adt_def.variants.len());
let variant_infos: Vec<_> =
Expand All @@ -1306,8 +1308,8 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
layout.for_variant(self, i))
})
.collect();
record(adt_kind.into(), adt_packed, match layout.variants {
Variants::Tagged { ref tag, .. } => Some(tag.value.size(self)),
record(adt_kind.into(), adt_packed, match discr_kind {
DiscriminantKind::Tag => Some(discr.value.size(self)),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

first occurrence here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole thing needs to be rewritten to pretty-print layouts losslessly (or we can just use {:#?}, heh).

_ => None
}, variant_infos);
}
Expand Down Expand Up @@ -1627,8 +1629,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
})
}

Variants::NicheFilling { ref variants, .. } |
Variants::Tagged { ref variants, .. } => {
Variants::Multiple { ref variants, .. } => {
&variants[variant_index]
}
};
Expand Down Expand Up @@ -1735,8 +1736,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
}

// Discriminant field for enums (where applicable).
Variants::Tagged { tag: ref discr, .. } |
Variants::NicheFilling { niche: ref discr, .. } => {
Variants::Multiple { ref discr, .. } => {
assert_eq!(i, 0);
let layout = LayoutDetails::scalar(cx, discr.clone());
return MaybeResult::from_ok(TyLayout {
Expand Down Expand Up @@ -1881,26 +1881,37 @@ impl<'a> HashStable<StableHashingContext<'a>> for Variants {
Single { index } => {
index.hash_stable(hcx, hasher);
}
Tagged {
ref tag,
Multiple {
ref discr,
ref discr_kind,
ref variants,
} => {
tag.hash_stable(hcx, hasher);
discr.hash_stable(hcx, hasher);
discr_kind.hash_stable(hcx, hasher);
variants.hash_stable(hcx, hasher);
}
NicheFilling {
}
}
}

impl<'a> HashStable<StableHashingContext<'a>> for DiscriminantKind {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
use crate::ty::layout::DiscriminantKind::*;
mem::discriminant(self).hash_stable(hcx, hasher);

match *self {
Tag => {}
Niche {
dataful_variant,
ref niche_variants,
ref niche,
niche_start,
ref variants,
} => {
dataful_variant.hash_stable(hcx, hasher);
niche_variants.start().hash_stable(hcx, hasher);
niche_variants.end().hash_stable(hcx, hasher);
niche.hash_stable(hcx, hasher);
niche_start.hash_stable(hcx, hasher);
variants.hash_stable(hcx, hasher);
}
}
}
Expand Down
68 changes: 48 additions & 20 deletions src/librustc_codegen_llvm/debuginfo/metadata.rs
Expand Up @@ -1235,7 +1235,11 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
}
]
}
layout::Variants::Tagged { ref variants, .. } => {
layout::Variants::Multiple {
discr_kind: layout::DiscriminantKind::Tag,
ref variants,
..
} => {
let discriminant_info = if fallback {
RegularDiscriminant(self.discriminant_type_metadata
.expect(""))
Expand Down Expand Up @@ -1277,12 +1281,14 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
}
}).collect()
}
layout::Variants::NicheFilling {
ref niche_variants,
niche_start,
layout::Variants::Multiple {
discr_kind: layout::DiscriminantKind::Niche {
ref niche_variants,
niche_start,
dataful_variant,
},
ref discr,
ref variants,
dataful_variant,
ref niche,
} => {
if fallback {
let variant = self.layout.for_variant(cx, dataful_variant);
Expand Down Expand Up @@ -1369,7 +1375,11 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
let value = (i.as_u32() as u128)
.wrapping_sub(niche_variants.start().as_u32() as u128)
.wrapping_add(niche_start);
let value = truncate(value, niche.value.size(cx));
let value = truncate(value, discr.value.size(cx));
// NOTE(eddyb) do *NOT* remove this assert, until
// we pass the full 128-bit value to LLVM, otherwise
// truncation will be silent and remain undetected.
assert_eq!(value as u64 as u128, value);
Some(value as u64)
};

Expand Down Expand Up @@ -1586,8 +1596,11 @@ fn prepare_enum_metadata(
let layout = cx.layout_of(enum_type);

match (&layout.abi, &layout.variants) {
(&layout::Abi::Scalar(_), &layout::Variants::Tagged {ref tag, .. }) =>
return FinalMetadata(discriminant_type_metadata(tag.value)),
(&layout::Abi::Scalar(_), &layout::Variants::Multiple {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've seen this code twice now (extracting the discr field if disc_kind is Tag. Pull it out into a method returning Option?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree, these are orthogonal. I didn't want to rewrite too much code, but arguably everything should match on Variants and then match on DiscriminantKind inside the Multiple case.

That way, code common to both niches and tags can be reused. Adding a .tag() method runs counter to that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get that, but the three cases that I saw here all are very "tagged" special and can't share code with the niche part. Or do you see any additional refactorings that can be done here in the future?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah this is the special case for C-like enums. Either way, I don't see a point in catering to this pattern, but I'll leave comments regarding the possibility of refactoring on the other 2 cases.

discr_kind: layout::DiscriminantKind::Tag,
ref discr,
..
}) => return FinalMetadata(discriminant_type_metadata(discr.value)),
_ => {}
}

Expand All @@ -1599,9 +1612,16 @@ fn prepare_enum_metadata(
if use_enum_fallback(cx) {
let discriminant_type_metadata = match layout.variants {
layout::Variants::Single { .. } |
layout::Variants::NicheFilling { .. } => None,
layout::Variants::Tagged { ref tag, .. } => {
Some(discriminant_type_metadata(tag.value))
layout::Variants::Multiple {
discr_kind: layout::DiscriminantKind::Niche { .. },
..
} => None,
layout::Variants::Multiple {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thrice

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is in if use_enum_fallback(cx) and will eventually be removed when we stop supporting LLVM versions that predate the addition of variant debuginfo.

discr_kind: layout::DiscriminantKind::Tag,
ref discr,
..
} => {
Some(discriminant_type_metadata(discr.value))
}
};

Expand Down Expand Up @@ -1636,16 +1656,20 @@ fn prepare_enum_metadata(
);
}

let discriminator_metadata = match &layout.variants {
let discriminator_metadata = match layout.variants {
// A single-variant enum has no discriminant.
&layout::Variants::Single { .. } => None,
layout::Variants::Single { .. } => None,

&layout::Variants::NicheFilling { ref niche, .. } => {
layout::Variants::Multiple {
discr_kind: layout::DiscriminantKind::Niche { .. },
ref discr,
..
} => {
// Find the integer type of the correct size.
let size = niche.value.size(cx);
let align = niche.value.align(cx);
let size = discr.value.size(cx);
let align = discr.value.align(cx);

let discr_type = match niche.value {
let discr_type = match discr.value {
layout::Int(t, _) => t,
layout::Float(layout::FloatTy::F32) => Integer::I32,
layout::Float(layout::FloatTy::F64) => Integer::I64,
Expand All @@ -1668,8 +1692,12 @@ fn prepare_enum_metadata(
}
},

&layout::Variants::Tagged { ref tag, .. } => {
let discr_type = tag.value.to_ty(cx.tcx);
layout::Variants::Multiple {
discr_kind: layout::DiscriminantKind::Tag,
ref discr,
..
} => {
let discr_type = discr.value.to_ty(cx.tcx);
let (size, align) = cx.size_and_align_of(discr_type);

let discr_metadata = basic_type_metadata(cx, discr_type);
Expand Down
8 changes: 7 additions & 1 deletion src/librustc_codegen_llvm/type_of.rs
Expand Up @@ -452,7 +452,13 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {

_ => {
let mut data_variant = match self.variants {
layout::Variants::NicheFilling { dataful_variant, .. } => {
layout::Variants::Multiple {
discr_kind: layout::DiscriminantKind::Niche {
dataful_variant,
..
},
..
} => {
// Only the niche itself is always initialized,
// so only check for a pointer at its offset.
//
Expand Down
36 changes: 20 additions & 16 deletions src/librustc_codegen_ssa/mir/place.rs
Expand Up @@ -216,37 +216,36 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
if self.layout.abi.is_uninhabited() {
return bx.cx().const_undef(cast_to);
}
match self.layout.variants {
let (discr_scalar, discr_kind) = match self.layout.variants {
layout::Variants::Single { index } => {
let discr_val = self.layout.ty.ty_adt_def().map_or(
index.as_u32() as u128,
|def| def.discriminant_for_variant(bx.cx().tcx(), index).val);
return bx.cx().const_uint_big(cast_to, discr_val);
}
layout::Variants::Tagged { .. } |
layout::Variants::NicheFilling { .. } => {},
}
layout::Variants::Multiple { ref discr, ref discr_kind, .. } => {
(discr, discr_kind)
}
};

let discr = self.project_field(bx, 0);
let lldiscr = bx.load_operand(discr).immediate();
match self.layout.variants {
layout::Variants::Single { .. } => bug!(),
layout::Variants::Tagged { ref tag, .. } => {
let signed = match tag.value {
match *discr_kind {
layout::DiscriminantKind::Tag => {
let signed = match discr_scalar.value {
// We use `i1` for bytes that are always `0` or `1`,
// e.g., `#[repr(i8)] enum E { A, B }`, but we can't
// let LLVM interpret the `i1` as signed, because
// then `i1 1` (i.e., E::B) is effectively `i8 -1`.
layout::Int(_, signed) => !tag.is_bool() && signed,
layout::Int(_, signed) => !discr_scalar.is_bool() && signed,
_ => false
};
bx.intcast(lldiscr, cast_to, signed)
}
layout::Variants::NicheFilling {
layout::DiscriminantKind::Niche {
dataful_variant,
ref niche_variants,
niche_start,
..
} => {
let niche_llty = bx.cx().immediate_backend_type(discr.layout);
if niche_variants.start() == niche_variants.end() {
Expand Down Expand Up @@ -291,7 +290,10 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
layout::Variants::Single { index } => {
assert_eq!(index, variant_index);
}
layout::Variants::Tagged { .. } => {
layout::Variants::Multiple {
discr_kind: layout::DiscriminantKind::Tag,
..
} => {
let ptr = self.project_field(bx, 0);
let to = self.layout.ty.ty_adt_def().unwrap()
.discriminant_for_variant(bx.tcx(), variant_index)
Expand All @@ -301,10 +303,12 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
ptr.llval,
ptr.align);
}
layout::Variants::NicheFilling {
dataful_variant,
ref niche_variants,
niche_start,
layout::Variants::Multiple {
discr_kind: layout::DiscriminantKind::Niche {
dataful_variant,
ref niche_variants,
niche_start,
},
..
} => {
if variant_index != dataful_variant {
Expand Down
3 changes: 1 addition & 2 deletions src/librustc_codegen_ssa/mir/rvalue.rs
Expand Up @@ -303,8 +303,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
});
}
}
layout::Variants::Tagged { .. } |
layout::Variants::NicheFilling { .. } => {},
layout::Variants::Multiple { .. } => {},
}
let llval = operand.immediate();

Expand Down