From 70e5ca2ab49ca31485780f6fa981c5164b2cc848 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 15 Nov 2016 17:48:07 +0100 Subject: [PATCH] Revisions from review comments, squashed. Biggest change: Revised print-type-sizes output to include breakdown of layout. Includes info about field sizes (and alignment + padding when padding is injected; the injected padding is derived from the offsets computed by layout module). Output format is illustrated in commit that has the ui tests. Note: there exists (at least) one case of variant w/o name: empty enums. Namely, empty enums use anonymous univariant repr. So for such cases, print the number of the variant instead of the name. ---- Also, eddyb suggested of reading from `layout_cache` post-trans. (For casual readers: the compiler source often uses the word "cache" for tables that are in fact not periodically purged, and thus are useful as the basis for data like this.) Some types that were previously not printed are now included in the output. (See e.g. the tests `print_type_sizes/generics.rs` and `print_type_sizes/variants.rs`) ---- Other review feedback: switch to an exhaustive match when filtering in just structural types. switch to hashset for layout info and move sort into print method. ---- Driveby change: Factored session::code_stats into its own module ---- incorporate njn feedback re output formatting. --- src/librustc/session/code_stats.rs | 173 ++++++++++++++++ src/librustc/session/mod.rs | 72 +------ src/librustc/ty/layout.rs | 7 + src/librustc_driver/driver.rs | 6 - src/librustc_mir/transform/mod.rs | 1 - .../transform/print_type_sizes.rs | 152 -------------- src/librustc_trans/adt.rs | 1 + src/librustc_trans/base.rs | 193 +++++++++++++++++- 8 files changed, 377 insertions(+), 228 deletions(-) create mode 100644 src/librustc/session/code_stats.rs delete mode 100644 src/librustc_mir/transform/print_type_sizes.rs diff --git a/src/librustc/session/code_stats.rs b/src/librustc/session/code_stats.rs new file mode 100644 index 00000000000..8308c54d70b --- /dev/null +++ b/src/librustc/session/code_stats.rs @@ -0,0 +1,173 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ty::AdtKind; +use ty::layout::{Align, Size}; + +use rustc_data_structures::fx::{FxHashSet}; + +use std::cmp::{self, Ordering}; + +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub struct VariantInfo { + pub name: Option, + pub kind: SizeKind, + pub size: u64, + pub align: u64, + pub fields: Vec, +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +pub enum SizeKind { Exact, Min } + +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub struct FieldInfo { + pub name: String, + pub offset: u64, + pub size: u64, + pub align: u64, +} + +impl From for DataTypeKind { + fn from(kind: AdtKind) -> Self { + match kind { + AdtKind::Struct => DataTypeKind::Struct, + AdtKind::Enum => DataTypeKind::Enum, + AdtKind::Union => DataTypeKind::Union, + } + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +pub enum DataTypeKind { + Struct, + Union, + Enum, + Closure, +} + +#[derive(PartialEq, Eq, Hash, Debug)] +pub struct TypeSizeInfo { + pub kind: DataTypeKind, + pub type_description: String, + pub align: u64, + pub overall_size: u64, + pub opt_discr_size: Option, + pub variants: Vec, +} + +#[derive(PartialEq, Eq, Debug)] +pub struct CodeStats { + type_sizes: FxHashSet, +} + +impl CodeStats { + pub fn new() -> Self { CodeStats { type_sizes: FxHashSet() } } + + pub fn record_type_size(&mut self, + kind: DataTypeKind, + type_desc: S, + align: Align, + overall_size: Size, + opt_discr_size: Option, + variants: Vec) { + let info = TypeSizeInfo { + kind: kind, + type_description: type_desc.to_string(), + align: align.abi(), + overall_size: overall_size.bytes(), + opt_discr_size: opt_discr_size.map(|s| s.bytes()), + variants: variants, + }; + self.type_sizes.insert(info); + } + + pub fn print_type_sizes(&self) { + let mut sorted: Vec<_> = self.type_sizes.iter().collect(); + + // Primary sort: large-to-small. + // Secondary sort: description (dictionary order) + sorted.sort_by(|info1, info2| { + // (reversing cmp order to get large-to-small ordering) + match info2.overall_size.cmp(&info1.overall_size) { + Ordering::Equal => info1.type_description.cmp(&info2.type_description), + other => other, + } + }); + + for info in &sorted { + 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); + discr_size + } else { + 0 + }; + + // We start this at discr_size (rather than 0) because + // things like C-enums do not have variants but we still + // want the max_variant_size at the end of the loop below + // to reflect the presence of the discriminant. + let mut max_variant_size = discr_size; + + let struct_like = match info.kind { + DataTypeKind::Struct | DataTypeKind::Closure => true, + DataTypeKind::Enum | DataTypeKind::Union => false, + }; + for (i, variant_info) in info.variants.iter().enumerate() { + let VariantInfo { ref name, kind: _, align: _, size, ref fields } = *variant_info; + let indent = if !struct_like { + let name = match name.as_ref() { + Some(name) => format!("{}", name), + None => format!("{}", i), + }; + println!("print-type-size {}variant `{}`: {} bytes", + indent, name, size - discr_size); + " " + } else { + assert!(i < 1); + " " + }; + max_variant_size = cmp::max(max_variant_size, size); + + let mut min_offset = discr_size; + for field in fields { + let FieldInfo { ref name, offset, size, align } = *field; + + // Include field alignment in output only if it caused padding injection + if min_offset != offset { + let pad = offset - min_offset; + println!("print-type-size {}padding: {} bytes", + indent, pad); + println!("print-type-size {}field `.{}`: {} bytes, alignment: {} bytes", + indent, name, size, align); + } else { + println!("print-type-size {}field `.{}`: {} bytes", + indent, name, size); + } + + min_offset = offset + 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); + } + } + } +} diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 128e4d878a8..3d8cfd19961 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +pub use self::code_stats::{CodeStats, DataTypeKind, FieldInfo}; +pub use self::code_stats::{SizeKind, TypeSizeInfo, VariantInfo}; + use dep_graph::DepGraph; use hir::def_id::{CrateNum, DefIndex}; use hir::svh::Svh; @@ -49,6 +52,7 @@ use std::fmt; use std::time::Duration; use libc::c_int; +mod code_stats; pub mod config; pub mod filesearch; pub mod search_paths; @@ -118,74 +122,6 @@ pub struct Session { next_node_id: Cell, } -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum VariantSize { - Exact(u64), - Min(u64), -} - -#[derive(PartialEq, Eq, Debug)] -pub struct TypeSizeInfo { - pub type_description: String, - pub overall_size: u64, - pub variant_sizes: Option>, -} - -#[derive(PartialEq, Eq, Debug)] -pub struct CodeStats { - pub type_sizes: Vec, -} - -impl CodeStats { - fn new() -> Self { - CodeStats { type_sizes: Vec::new() } - } - - pub fn record_type_size(&mut self, - type_desc: S, - overall_size: u64, - variant_sizes: Vec) { - let sizes = if variant_sizes.len() == 0 { None } else { Some(variant_sizes) }; - let info = TypeSizeInfo { - type_description: type_desc.to_string(), - overall_size: overall_size, - variant_sizes: sizes, - }; - if !self.type_sizes.contains(&info) { - self.type_sizes.push(info); - } - } - - pub fn sort_by_type_description(&mut self) { - self.type_sizes.sort_by(|info1, info2| { - info1.type_description.cmp(&info2.type_description) - }); - } - - pub fn sort_by_overall_size(&mut self) { - self.type_sizes.sort_by(|info1, info2| { - // (reversing cmp order to get large-to-small ordering) - info2.overall_size.cmp(&info1.overall_size) - }); - } - - pub fn print_type_sizes(&self) { - for info in &self.type_sizes { - println!("print-type-size t: `{}` overall bytes: {}", - info.type_description, info.overall_size); - if let Some(ref variant_sizes) = info.variant_sizes { - for (i, variant_size) in variant_sizes.iter().enumerate() { - let (kind, s) = match *variant_size { - VariantSize::Exact(s) => { ("exact", s) } - VariantSize::Min(s) => { (" min", s) } - }; - println!("print-type-size variant[{}] {} bytes: {}", i, kind, s); - } - } - } - } -} - pub struct PerfStats { // The accumulated time needed for computing the SVH of the crate pub svh_time: Cell, diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 5ee1c3678d6..bc3c5d6ed4e 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -559,11 +559,14 @@ impl<'a, 'gcx, 'tcx> Struct { self.offsets.push(offset); + debug!("Struct::extend offset: {:?} field: {:?} {:?}", offset, field, field.size(dl)); offset = offset.checked_add(field.size(dl), dl) .map_or(Err(LayoutError::SizeOverflow(scapegoat)), Ok)?; } + debug!("Struct::extend min_size: {:?}", offset); + self.min_size = offset; Ok(()) @@ -707,12 +710,16 @@ impl<'a, 'gcx, 'tcx> Union { index, scapegoat); } + debug!("Union::extend field: {:?} {:?}", field, field.size(dl)); + if !self.packed { self.align = self.align.max(field.align(dl)); } self.min_size = cmp::max(self.min_size, field.size(dl)); } + debug!("Union::extend min-size: {:?}", self.min_size); + Ok(()) } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index a91525c6b2d..9a4ecef0c0e 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -216,9 +216,6 @@ pub fn compile_input(sess: &Session, }; if sess.opts.debugging_opts.print_type_sizes { - // (these are stable sorts) - sess.code_stats.borrow_mut().sort_by_type_description(); - sess.code_stats.borrow_mut().sort_by_overall_size(); sess.code_stats.borrow().print_type_sizes(); } @@ -1015,9 +1012,6 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, time(time_passes, "MIR optimisations", || { let mut passes = ::rustc::mir::transform::Passes::new(); passes.push_hook(box mir::transform::dump_mir::DumpMir); - if tcx.sess.opts.debugging_opts.print_type_sizes { - passes.push_pass(box mir::transform::print_type_sizes::GatherTypeSizesMir::new()); - } passes.push_pass(box mir::transform::no_landing_pads::NoLandingPads); passes.push_pass(box mir::transform::simplify::SimplifyCfg::new("no-landing-pads")); diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index eed4763c17d..ae255f70fb7 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -13,7 +13,6 @@ pub mod simplify; pub mod erase_regions; pub mod no_landing_pads; pub mod type_check; -pub mod print_type_sizes; pub mod add_call_guards; pub mod promote_consts; pub mod qualify_consts; diff --git a/src/librustc_mir/transform/print_type_sizes.rs b/src/librustc_mir/transform/print_type_sizes.rs deleted file mode 100644 index 617a5ac78df..00000000000 --- a/src/librustc_mir/transform/print_type_sizes.rs +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! This pass implements instrumentation to gather the layout of every type. - -use rustc::session::{VariantSize}; -use rustc::traits::{Reveal}; -use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::fold::{TypeFoldable}; -use rustc::ty::layout::{Layout}; -use rustc::mir::{Mir}; -use rustc::mir::transform::{MirPass, MirPassHook, MirSource, Pass}; -use rustc::mir::visit::Visitor; - -use std::collections::HashSet; - -pub struct GatherTypeSizesMir { - _hidden: (), -} - -impl GatherTypeSizesMir { - pub fn new() -> Self { - GatherTypeSizesMir { _hidden: () } - } -} - -impl Pass for GatherTypeSizesMir { -} - -impl<'tcx> MirPassHook<'tcx> for GatherTypeSizesMir { - fn on_mir_pass<'a>(&mut self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - src: MirSource, - mir: &Mir<'tcx>, - _pass: &Pass, - _is_after: bool) { - debug!("on_mir_pass: {}", tcx.node_path_str(src.item_id())); - self.go(tcx, mir); - } -} - -impl<'tcx> MirPass<'tcx> for GatherTypeSizesMir { - fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - src: MirSource, mir: &mut Mir<'tcx>) { - debug!("run_pass: {}", tcx.node_path_str(src.item_id())); - self.go(tcx, mir); - } -} - -impl GatherTypeSizesMir { - fn go<'a, 'tcx>(&mut self, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - mir: &Mir<'tcx>) { - if tcx.sess.err_count() > 0 { - // compiling a broken program can obviously result in a - // broken MIR, so do not bother trying to process it. - return; - } - - let mut visitor = TypeVisitor { - tcx: tcx, - seen: HashSet::new(), - }; - visitor.visit_mir(mir); - } -} - -struct TypeVisitor<'a, 'tcx: 'a> { - tcx: TyCtxt<'a, 'tcx, 'tcx>, - seen: HashSet>, -} - -impl<'a, 'tcx: 'a> Visitor<'tcx> for TypeVisitor<'a, 'tcx> { - fn visit_ty(&mut self, ty: &Ty<'tcx>) { - debug!("TypeVisitor::visit_ty ty=`{:?}`", ty); - - match ty.sty { - ty::TyAdt(..) | - ty::TyClosure(..) => {} // fall through - _ => { - debug!("print-type-size t: `{:?}` skip non-nominal", ty); - return; - } - } - - if ty.has_param_types() { - debug!("print-type-size t: `{:?}` skip has param types", ty); - return; - } - if ty.has_projection_types() { - debug!("print-type-size t: `{:?}` skip has projections", ty); - return; - } - - if self.seen.contains(ty) { - return; - } - self.seen.insert(ty); - - let reveal = Reveal::All; - // let reveal = Reveal::NotSpecializable; - - self.tcx.infer_ctxt(None, None, reveal).enter(|infcx| { - match ty.layout(&infcx) { - Ok(layout) => { - let type_desc = format!("{:?}", ty); - let overall_size = layout.size(&Default::default()); - - let variant_sizes: Vec<_> = match *layout { - Layout::General { ref variants, .. } => { - variants.iter() - .map(|v| if v.sized { - VariantSize::Exact(v.min_size.bytes()) - } else { - VariantSize::Min(v.min_size.bytes()) - }) - .collect() - } - - Layout::UntaggedUnion { variants: _ } => { - /* layout does not currently store info about each variant... */ - Vec::new() - } - - // RawNullablePointer/StructWrappedNullablePointer - // don't provide any interesting size info - // beyond what we already reported for their - // total size. - _ => { - Vec::new() - } - }; - - self.tcx.sess.code_stats.borrow_mut() - .record_type_size(type_desc, - overall_size.bytes(), - variant_sizes); - } - Err(err) => { - self.tcx.sess.warn(&format!("print-type-size t: `{:?}` err: {:?}", ty, err)); - } - } - }); - } -} diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs index c3340281d07..e091ba07d4f 100644 --- a/src/librustc_trans/adt.rs +++ b/src/librustc_trans/adt.rs @@ -247,6 +247,7 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // of the size. let size = size.bytes(); let align = align.abi(); + assert!(align <= std::u32::MAX as u64); let discr_ty = Type::from_integer(cx, discr); let discr_size = discr.size().bytes(); let padded_discr_size = roundup(discr_size, align as u32); diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 4353c7bd586..d697a5bafb7 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -47,7 +47,7 @@ use rustc::hir::map as hir_map; use rustc::util::common::time; use session::config::{self, NoDebugInfo}; use rustc_incremental::IncrementalHashesMap; -use session::Session; +use session::{self, DataTypeKind, Session}; use abi::{self, Abi, FnType}; use adt; use attributes; @@ -93,6 +93,7 @@ use std::i32; use syntax_pos::{Span, DUMMY_SP}; use syntax::attr; use rustc::hir; +use rustc::ty::layout::{self, Layout}; use syntax::ast; thread_local! { @@ -1741,6 +1742,10 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .collect()) }); + if tcx.sess.opts.debugging_opts.print_type_sizes { + gather_type_sizes(tcx); + } + if sess.target.target.options.is_like_msvc && sess.crate_types.borrow().iter().any(|ct| *ct == config::CrateTypeRlib) { create_imps(&crate_context_list); @@ -1771,6 +1776,192 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } +fn gather_type_sizes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { + let layout_cache = tcx.layout_cache.borrow(); + for (ty, layout) in layout_cache.iter() { + + // (delay format until we actually need it) + let record = |kind, opt_discr_size, variants| { + let type_desc = format!("{:?}", ty); + let overall_size = layout.size(&tcx.data_layout); + let align = layout.align(&tcx.data_layout); + tcx.sess.code_stats.borrow_mut().record_type_size(kind, + type_desc, + align, + overall_size, + opt_discr_size, + variants); + }; + + let (adt_def, substs) = match ty.sty { + ty::TyAdt(ref adt_def, substs) => { + debug!("print-type-size t: `{:?}` process adt", ty); + (adt_def, substs) + } + + ty::TyClosure(..) => { + debug!("print-type-size t: `{:?}` record closure", ty); + record(DataTypeKind::Closure, None, vec![]); + continue; + } + + _ => { + debug!("print-type-size t: `{:?}` skip non-nominal", ty); + continue; + } + }; + + let adt_kind = adt_def.adt_kind(); + + let build_field_info = |(field_name, field_ty): (ast::Name, Ty), offset: &layout::Size| { + match layout_cache.get(&field_ty) { + None => bug!("no layout found for field {} type: `{:?}`", field_name, field_ty), + Some(field_layout) => { + session::FieldInfo { + name: field_name.to_string(), + offset: offset.bytes(), + size: field_layout.size(&tcx.data_layout).bytes(), + align: field_layout.align(&tcx.data_layout).abi(), + } + } + } + }; + + let build_primitive_info = |name: ast::Name, value: &layout::Primitive| { + session::VariantInfo { + name: Some(name.to_string()), + kind: session::SizeKind::Exact, + align: value.align(&tcx.data_layout).abi(), + size: value.size(&tcx.data_layout).bytes(), + fields: vec![], + } + }; + + enum Fields<'a> { + WithDiscrim(&'a layout::Struct), + NoDiscrim(&'a layout::Struct), + } + + let build_variant_info = |n: Option, flds: &[(ast::Name, Ty)], layout: Fields| { + let (s, field_offsets) = match layout { + Fields::WithDiscrim(s) => (s, &s.offsets[1..]), + Fields::NoDiscrim(s) => (s, &s.offsets[0..]), + }; + let field_info: Vec<_> = flds.iter() + .zip(field_offsets.iter()) + .map(|(&field_name_ty, offset)| build_field_info(field_name_ty, offset)) + .collect(); + + session::VariantInfo { + name: n.map(|n|n.to_string()), + kind: if s.sized { + session::SizeKind::Exact + } else { + session::SizeKind::Min + }, + align: s.align.abi(), + size: s.min_size.bytes(), + fields: field_info, + } + }; + + match **layout { + Layout::StructWrappedNullablePointer { nonnull: ref variant_layout, + nndiscr, + discrfield: _ } => { + debug!("print-type-size t: `{:?}` adt struct-wrapped nullable nndiscr {} is {:?}", + ty, nndiscr, variant_layout); + let variant_def = &adt_def.variants[nndiscr as usize]; + let fields: Vec<_> = variant_def.fields.iter() + .map(|field_def| (field_def.name, field_def.ty(tcx, substs))) + .collect(); + record(adt_kind.into(), + None, + vec![build_variant_info(Some(variant_def.name), + &fields, + Fields::NoDiscrim(variant_layout))]); + } + Layout::RawNullablePointer { nndiscr, value } => { + debug!("print-type-size t: `{:?}` adt raw nullable nndiscr {} is {:?}", + ty, nndiscr, value); + let variant_def = &adt_def.variants[nndiscr as usize]; + record(adt_kind.into(), None, + vec![build_primitive_info(variant_def.name, &value)]); + } + Layout::Univariant { variant: ref variant_layout, non_zero: _ } => { + let variant_names = || { + adt_def.variants.iter().map(|v|format!("{}", v.name)).collect::>() + }; + debug!("print-type-size t: `{:?}` adt univariant {:?} variants: {:?}", + ty, variant_layout, variant_names()); + assert!(adt_def.variants.len() <= 1, + "univariant with variants {:?}", variant_names()); + if adt_def.variants.len() == 1 { + let variant_def = &adt_def.variants[0]; + let fields: Vec<_> = variant_def.fields.iter() + .map(|field_def| (field_def.name, field_def.ty(tcx, substs))) + .collect(); + record(adt_kind.into(), + None, + vec![build_variant_info(Some(variant_def.name), + &fields, + Fields::NoDiscrim(variant_layout))]); + } else { + // (This case arises for *empty* enums; so give it + // zero variants.) + record(adt_kind.into(), None, vec![]); + } + } + + Layout::General { ref variants, discr, .. } => { + debug!("print-type-size t: `{:?}` adt general variants def {} layouts {} {:?}", + ty, adt_def.variants.len(), variants.len(), variants); + let variant_infos: Vec<_> = adt_def.variants.iter() + .zip(variants.iter()) + .map(|(variant_def, variant_layout)| { + let fields: Vec<_> = variant_def.fields.iter() + .map(|field_def| (field_def.name, field_def.ty(tcx, substs))) + .collect(); + build_variant_info(Some(variant_def.name), + &fields, + Fields::WithDiscrim(variant_layout)) + }) + .collect(); + record(adt_kind.into(), Some(discr.size()), variant_infos); + } + + Layout::UntaggedUnion { ref variants } => { + debug!("print-type-size t: `{:?}` adt union variants {:?}", + ty, variants); + // layout does not currently store info about each + // variant... + record(adt_kind.into(), None, Vec::new()); + } + + Layout::CEnum { discr, .. } => { + debug!("print-type-size t: `{:?}` adt c-like enum", ty); + let variant_infos: Vec<_> = adt_def.variants.iter() + .map(|variant_def| { + build_primitive_info(variant_def.name, + &layout::Primitive::Int(discr)) + }) + .collect(); + record(adt_kind.into(), Some(discr.size()), variant_infos); + } + + // other cases provide little interesting (i.e. adjustable + // via representation tweaks) size info beyond total size. + Layout::Scalar { .. } | + Layout::Vector { .. } | + Layout::Array { .. } | + Layout::FatPointer { .. } => { + debug!("print-type-size t: `{:?}` adt other", ty); + record(adt_kind.into(), None, Vec::new()) + } + } + } +} + /// For each CGU, identify if we can reuse an existing object file (or /// maybe other context). fn trans_reuse_previous_work_products(tcx: TyCtxt,