+use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::sync::Lock;
use rustc_target::abi::{Align, Size};
-use rustc_data_structures::fx::{FxHashSet};
use std::cmp::{self, Ordering};
-use rustc_data_structures::sync::Lock;
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct VariantInfo {
}
impl CodeStats {
- pub fn record_type_size<S: ToString>(&self,
- kind: DataTypeKind,
- type_desc: S,
- align: Align,
- overall_size: Size,
- packed: bool,
- opt_discr_size: Option<Size>,
- mut variants: Vec<VariantInfo>) {
+ pub fn record_type_size<S: ToString>(
+ &self,
+ kind: DataTypeKind,
+ type_desc: S,
+ align: Align,
+ overall_size: Size,
+ packed: bool,
+ opt_discr_size: Option<Size>,
+ mut variants: Vec<VariantInfo>,
+ ) {
// Sort variants so the largest ones are shown first. A stable sort is
// used here so that source code order is preserved for all variants
// that have the same size.
- variants.sort_by(|info1, info2| {
- info2.size.cmp(&info1.size)
- });
+ variants.sort_by(|info1, info2| info2.size.cmp(&info1.size));
let info = TypeSizeInfo {
kind,
type_description: type_desc.to_string(),
});
for info in &sorted {
- println!("print-type-size type: `{}`: {} bytes, alignment: {} bytes",
- info.type_description, info.overall_size, info.align);
+ println!(
+ "print-type-size type: `{}`: {} bytes, alignment: {} bytes",
+ info.type_description, info.overall_size, info.align
+ );
let indent = " ";
let discr_size = if let Some(discr_size) = info.opt_discr_size {
- println!("print-type-size {}discriminant: {} bytes",
- indent, discr_size);
+ println!("print-type-size {}discriminant: {} bytes", indent, discr_size);
discr_size
} else {
0
Some(name) => name.to_owned(),
None => i.to_string(),
};
- println!("print-type-size {}variant `{}`: {} bytes",
- indent, name, size - discr_size);
+ println!(
+ "print-type-size {}variant `{}`: {} bytes",
+ indent,
+ name,
+ size - discr_size
+ );
" "
} else {
assert!(i < 1);
let mut min_offset = discr_size;
- // We want to print fields by increasing offset.
+ // We want to print fields by increasing offset. We also want
+ // zero-sized fields before non-zero-sized fields, otherwise
+ // the loop below goes wrong; hence the `f.size` in the sort
+ // key.
let mut fields = fields.clone();
- fields.sort_by_key(|f| f.offset);
+ fields.sort_by_key(|f| (f.offset, f.size));
for field in fields.iter() {
let FieldInfo { ref name, offset, size, align } = *field;
if offset > min_offset {
let pad = offset - min_offset;
- println!("print-type-size {}padding: {} bytes",
- indent, pad);
+ println!("print-type-size {}padding: {} bytes", indent, pad);
}
if offset < min_offset {
- // if this happens something is very wrong
- println!("print-type-size {}field `.{}`: {} bytes, \
+ // If this happens it's probably a union.
+ println!(
+ "print-type-size {}field `.{}`: {} bytes, \
offset: {} bytes, \
alignment: {} bytes",
- indent, name, size, offset, align);
+ indent, name, size, offset, align
+ );
} else if info.packed || offset == min_offset {
- println!("print-type-size {}field `.{}`: {} bytes",
- indent, name, size);
+ println!("print-type-size {}field `.{}`: {} bytes", indent, name, size);
} else {
// Include field alignment in output only if it caused padding injection
- println!("print-type-size {}field `.{}`: {} bytes, \
+ println!(
+ "print-type-size {}field `.{}`: {} bytes, \
alignment: {} bytes",
- indent, name, size, align);
+ indent, name, size, align
+ );
}
min_offset = offset + size;
}
}
- assert!(max_variant_size <= info.overall_size,
- "max_variant_size {} !<= {} overall_size",
- max_variant_size, info.overall_size);
+ assert!(
+ max_variant_size <= info.overall_size,
+ "max_variant_size {} !<= {} overall_size",
+ max_variant_size,
+ info.overall_size
+ );
if max_variant_size < info.overall_size {
- println!("print-type-size {}end padding: {} bytes",
- indent, info.overall_size - max_variant_size);
+ println!(
+ "print-type-size {}end padding: {} bytes",
+ indent,
+ info.overall_size - max_variant_size
+ );
}
}
}