-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
struct field reordering and optimization #37429
Changes from 26 commits
cae94e8
8cfbffe
1969aeb
2746903
d754778
c7ec0df
0e61c0e
8e852e9
3d23dc7
adae9bc
e7c3540
1af8e14
cb21cc5
b3c285f
487ef58
5adf694
74f5c61
cf5f80c
c8c3579
052e59c
e9580e2
025456e
cfe1a77
a65cc1e
9966bbd
79c35bb
f22a22b
ff59474
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -881,25 +881,28 @@ impl<'tcx> MemberDescriptionFactory<'tcx> { | |
|
||
// Creates MemberDescriptions for the fields of a struct | ||
struct StructMemberDescriptionFactory<'tcx> { | ||
ty: Ty<'tcx>, | ||
variant: &'tcx ty::VariantDef, | ||
substs: &'tcx Substs<'tcx>, | ||
is_simd: bool, | ||
span: Span, | ||
} | ||
|
||
impl<'tcx> StructMemberDescriptionFactory<'tcx> { | ||
fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>) | ||
-> Vec<MemberDescription> { | ||
let field_size = if self.is_simd { | ||
let fty = monomorphize::field_ty(cx.tcx(), | ||
self.substs, | ||
&self.variant.fields[0]); | ||
Some(machine::llsize_of_alloc( | ||
cx, | ||
type_of::type_of(cx, fty) | ||
) as usize) | ||
} else { | ||
None | ||
let layout = cx.layout_of(self.ty); | ||
|
||
let tmp; | ||
let offsets = match *layout { | ||
layout::Univariant { ref variant, .. } => &variant.offsets, | ||
layout::Vector { element, count } => { | ||
let element_size = element.size(&cx.tcx().data_layout).bytes(); | ||
tmp = (0..count). | ||
map(|i| layout::Size::from_bytes(i*element_size)) | ||
.collect::<Vec<layout::Size>>(); | ||
&tmp | ||
} | ||
_ => bug!("{} is not a struct", self.ty) | ||
}; | ||
|
||
self.variant.fields.iter().enumerate().map(|(i, f)| { | ||
|
@@ -910,11 +913,7 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> { | |
}; | ||
let fty = monomorphize::field_ty(cx.tcx(), self.substs, f); | ||
|
||
let offset = if self.is_simd { | ||
FixedMemberOffset { bytes: i * field_size.unwrap() } | ||
} else { | ||
ComputedMemberOffset | ||
}; | ||
let offset = FixedMemberOffset { bytes: offsets[i].bytes() as usize}; | ||
|
||
MemberDescription { | ||
name: name, | ||
|
@@ -956,9 +955,9 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, | |
struct_metadata_stub, | ||
struct_llvm_type, | ||
StructMDF(StructMemberDescriptionFactory { | ||
ty: struct_type, | ||
variant: variant, | ||
substs: substs, | ||
is_simd: struct_type.is_simd(), | ||
span: span, | ||
}) | ||
) | ||
|
@@ -970,13 +969,21 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, | |
|
||
// Creates MemberDescriptions for the fields of a tuple | ||
struct TupleMemberDescriptionFactory<'tcx> { | ||
ty: Ty<'tcx>, | ||
component_types: Vec<Ty<'tcx>>, | ||
span: Span, | ||
} | ||
|
||
impl<'tcx> TupleMemberDescriptionFactory<'tcx> { | ||
fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>) | ||
-> Vec<MemberDescription> { | ||
let layout = cx.layout_of(self.ty); | ||
let offsets = if let layout::Univariant { ref variant, .. } = *layout { | ||
&variant.offsets | ||
} else { | ||
bug!("{} is not a tuple", self.ty); | ||
}; | ||
|
||
self.component_types | ||
.iter() | ||
.enumerate() | ||
|
@@ -985,7 +992,7 @@ impl<'tcx> TupleMemberDescriptionFactory<'tcx> { | |
name: format!("__{}", i), | ||
llvm_type: type_of::type_of(cx, component_type), | ||
type_metadata: type_metadata(cx, component_type, self.span), | ||
offset: ComputedMemberOffset, | ||
offset: FixedMemberOffset { bytes: offsets[i].bytes() as usize }, | ||
flags: DIFlags::FlagZero, | ||
} | ||
}).collect() | ||
|
@@ -1012,6 +1019,7 @@ fn prepare_tuple_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, | |
NO_SCOPE_METADATA), | ||
tuple_llvm_type, | ||
TupleMDF(TupleMemberDescriptionFactory { | ||
ty: tuple_type, | ||
component_types: component_types.to_vec(), | ||
span: span, | ||
}) | ||
|
@@ -1250,7 +1258,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { | |
}, | ||
layout::StructWrappedNullablePointer { nonnull: ref struct_def, | ||
nndiscr, | ||
ref discrfield, ..} => { | ||
ref discrfield_source, ..} => { | ||
// Create a description of the non-null variant | ||
let (variant_type_metadata, variant_llvm_type, member_description_factory) = | ||
describe_enum_variant(cx, | ||
|
@@ -1273,12 +1281,12 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { | |
// member's name. | ||
let null_variant_index = (1 - nndiscr) as usize; | ||
let null_variant_name = adt.variants[null_variant_index].name; | ||
let discrfield = discrfield.iter() | ||
let discrfield_source = discrfield_source.iter() | ||
.skip(1) | ||
.map(|x| x.to_string()) | ||
.collect::<Vec<_>>().join("$"); | ||
let union_member_name = format!("RUST$ENCODED$ENUM${}${}", | ||
discrfield, | ||
discrfield_source, | ||
null_variant_name); | ||
|
||
// Create the (singleton) list of descriptions of union members. | ||
|
@@ -1300,6 +1308,8 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { | |
|
||
// Creates MemberDescriptions for the fields of a single enum variant. | ||
struct VariantMemberDescriptionFactory<'tcx> { | ||
// Cloned from the layout::Struct describing the variant. | ||
offsets: Vec<layout::Size>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The layouts are interned so you can just use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Still need to address this. |
||
args: Vec<(String, Ty<'tcx>)>, | ||
discriminant_type_metadata: Option<DIType>, | ||
span: Span, | ||
|
@@ -1316,7 +1326,7 @@ impl<'tcx> VariantMemberDescriptionFactory<'tcx> { | |
Some(metadata) if i == 0 => metadata, | ||
_ => type_metadata(cx, ty, self.span) | ||
}, | ||
offset: ComputedMemberOffset, | ||
offset: FixedMemberOffset { bytes: self.offsets[i].bytes() as usize }, | ||
flags: DIFlags::FlagZero | ||
} | ||
}).collect() | ||
|
@@ -1420,6 +1430,7 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, | |
|
||
let member_description_factory = | ||
VariantMDF(VariantMemberDescriptionFactory { | ||
offsets: struct_def.offsets.clone(), | ||
args: args, | ||
discriminant_type_metadata: match discriminant_info { | ||
RegularDiscriminant(discriminant_type_metadata) => { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Q_Q why doesn't this use an offset? cc @michaelwoerister
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it'd need both a type and an offset which it can get from the field path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm leaving this one for now. This is the old behavior, and we have tests against it that fail if it changes.
If I had to bet, it's field indices because the pretty printers access them with "humanlike" expressions or something.