@@ -12,10 +12,10 @@ pub use self::Integer::*;
1212pub use self :: Layout :: * ;
1313pub use self :: Primitive :: * ;
1414
15- use session:: Session ;
15+ use session:: { self , DataTypeKind , Session } ;
1616use ty:: { self , Ty , TyCtxt , TypeFoldable , ReprOptions , ReprFlags } ;
1717
18- use syntax:: ast:: { FloatTy , IntTy , UintTy } ;
18+ use syntax:: ast:: { self , FloatTy , IntTy , UintTy } ;
1919use syntax:: attr;
2020use syntax_pos:: DUMMY_SP ;
2121
@@ -1690,6 +1690,219 @@ impl<'a, 'tcx> Layout {
16901690 }
16911691 }
16921692 }
1693+
1694+ /// This is invoked by the `layout_raw` query to record the final
1695+ /// layout of each type.
1696+ #[ inline]
1697+ pub fn record_layout_for_printing ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
1698+ ty : Ty < ' tcx > ,
1699+ param_env : ty:: ParamEnv < ' tcx > ,
1700+ layout : & Layout ) {
1701+ // If we are running with `-Zprint-type-sizes`, record layouts for
1702+ // dumping later. Ignore layouts that are done with non-empty
1703+ // environments or non-monomorphic layouts, as the user only wants
1704+ // to see the stuff resulting from the final trans session.
1705+ if
1706+ !tcx. sess . opts . debugging_opts . print_type_sizes ||
1707+ ty. has_param_types ( ) ||
1708+ ty. has_self_ty ( ) ||
1709+ !param_env. caller_bounds . is_empty ( )
1710+ {
1711+ return ;
1712+ }
1713+
1714+ Self :: record_layout_for_printing_outlined ( tcx, ty, param_env, layout)
1715+ }
1716+
1717+ fn record_layout_for_printing_outlined ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
1718+ ty : Ty < ' tcx > ,
1719+ param_env : ty:: ParamEnv < ' tcx > ,
1720+ layout : & Layout ) {
1721+ // (delay format until we actually need it)
1722+ let record = |kind, opt_discr_size, variants| {
1723+ let type_desc = format ! ( "{:?}" , ty) ;
1724+ let overall_size = layout. size ( tcx) ;
1725+ let align = layout. align ( tcx) ;
1726+ tcx. sess . code_stats . borrow_mut ( ) . record_type_size ( kind,
1727+ type_desc,
1728+ align,
1729+ overall_size,
1730+ opt_discr_size,
1731+ variants) ;
1732+ } ;
1733+
1734+ let ( adt_def, substs) = match ty. sty {
1735+ ty:: TyAdt ( ref adt_def, substs) => {
1736+ debug ! ( "print-type-size t: `{:?}` process adt" , ty) ;
1737+ ( adt_def, substs)
1738+ }
1739+
1740+ ty:: TyClosure ( ..) => {
1741+ debug ! ( "print-type-size t: `{:?}` record closure" , ty) ;
1742+ record ( DataTypeKind :: Closure , None , vec ! [ ] ) ;
1743+ return ;
1744+ }
1745+
1746+ _ => {
1747+ debug ! ( "print-type-size t: `{:?}` skip non-nominal" , ty) ;
1748+ return ;
1749+ }
1750+ } ;
1751+
1752+ let adt_kind = adt_def. adt_kind ( ) ;
1753+
1754+ let build_field_info = |( field_name, field_ty) : ( ast:: Name , Ty < ' tcx > ) , offset : & Size | {
1755+ let layout = field_ty. layout ( tcx, param_env) ;
1756+ match layout {
1757+ Err ( _) => bug ! ( "no layout found for field {} type: `{:?}`" , field_name, field_ty) ,
1758+ Ok ( field_layout) => {
1759+ session:: FieldInfo {
1760+ name : field_name. to_string ( ) ,
1761+ offset : offset. bytes ( ) ,
1762+ size : field_layout. size ( tcx) . bytes ( ) ,
1763+ align : field_layout. align ( tcx) . abi ( ) ,
1764+ }
1765+ }
1766+ }
1767+ } ;
1768+
1769+ let build_primitive_info = |name : ast:: Name , value : & Primitive | {
1770+ session:: VariantInfo {
1771+ name : Some ( name. to_string ( ) ) ,
1772+ kind : session:: SizeKind :: Exact ,
1773+ align : value. align ( tcx) . abi ( ) ,
1774+ size : value. size ( tcx) . bytes ( ) ,
1775+ fields : vec ! [ ] ,
1776+ }
1777+ } ;
1778+
1779+ enum Fields < ' a > {
1780+ WithDiscrim ( & ' a Struct ) ,
1781+ NoDiscrim ( & ' a Struct ) ,
1782+ }
1783+
1784+ let build_variant_info = |n : Option < ast:: Name > ,
1785+ flds : & [ ( ast:: Name , Ty < ' tcx > ) ] ,
1786+ layout : Fields | {
1787+ let ( s, field_offsets) = match layout {
1788+ Fields :: WithDiscrim ( s) => ( s, & s. offsets [ 1 ..] ) ,
1789+ Fields :: NoDiscrim ( s) => ( s, & s. offsets [ 0 ..] ) ,
1790+ } ;
1791+ let field_info: Vec < _ > = flds. iter ( )
1792+ . zip ( field_offsets. iter ( ) )
1793+ . map ( |( & field_name_ty, offset) | build_field_info ( field_name_ty, offset) )
1794+ . collect ( ) ;
1795+
1796+ session:: VariantInfo {
1797+ name : n. map ( |n|n. to_string ( ) ) ,
1798+ kind : if s. sized {
1799+ session:: SizeKind :: Exact
1800+ } else {
1801+ session:: SizeKind :: Min
1802+ } ,
1803+ align : s. align . abi ( ) ,
1804+ size : s. min_size . bytes ( ) ,
1805+ fields : field_info,
1806+ }
1807+ } ;
1808+
1809+ match * layout {
1810+ Layout :: StructWrappedNullablePointer { nonnull : ref variant_layout,
1811+ nndiscr,
1812+ discrfield : _,
1813+ discrfield_source : _ } => {
1814+ debug ! ( "print-type-size t: `{:?}` adt struct-wrapped nullable nndiscr {} is {:?}" ,
1815+ ty, nndiscr, variant_layout) ;
1816+ let variant_def = & adt_def. variants [ nndiscr as usize ] ;
1817+ let fields: Vec < _ > = variant_def. fields . iter ( )
1818+ . map ( |field_def| ( field_def. name , field_def. ty ( tcx, substs) ) )
1819+ . collect ( ) ;
1820+ record ( adt_kind. into ( ) ,
1821+ None ,
1822+ vec ! [ build_variant_info( Some ( variant_def. name) ,
1823+ & fields,
1824+ Fields :: NoDiscrim ( variant_layout) ) ] ) ;
1825+ }
1826+ Layout :: RawNullablePointer { nndiscr, value } => {
1827+ debug ! ( "print-type-size t: `{:?}` adt raw nullable nndiscr {} is {:?}" ,
1828+ ty, nndiscr, value) ;
1829+ let variant_def = & adt_def. variants [ nndiscr as usize ] ;
1830+ record ( adt_kind. into ( ) , None ,
1831+ vec ! [ build_primitive_info( variant_def. name, & value) ] ) ;
1832+ }
1833+ Layout :: Univariant { variant : ref variant_layout, non_zero : _ } => {
1834+ let variant_names = || {
1835+ adt_def. variants . iter ( ) . map ( |v|format ! ( "{}" , v. name) ) . collect :: < Vec < _ > > ( )
1836+ } ;
1837+ debug ! ( "print-type-size t: `{:?}` adt univariant {:?} variants: {:?}" ,
1838+ ty, variant_layout, variant_names( ) ) ;
1839+ assert ! ( adt_def. variants. len( ) <= 1 ,
1840+ "univariant with variants {:?}" , variant_names( ) ) ;
1841+ if adt_def. variants . len ( ) == 1 {
1842+ let variant_def = & adt_def. variants [ 0 ] ;
1843+ let fields: Vec < _ > = variant_def. fields . iter ( )
1844+ . map ( |field_def| ( field_def. name , field_def. ty ( tcx, substs) ) )
1845+ . collect ( ) ;
1846+ record ( adt_kind. into ( ) ,
1847+ None ,
1848+ vec ! [ build_variant_info( Some ( variant_def. name) ,
1849+ & fields,
1850+ Fields :: NoDiscrim ( variant_layout) ) ] ) ;
1851+ } else {
1852+ // (This case arises for *empty* enums; so give it
1853+ // zero variants.)
1854+ record ( adt_kind. into ( ) , None , vec ! [ ] ) ;
1855+ }
1856+ }
1857+
1858+ Layout :: General { ref variants, discr, .. } => {
1859+ debug ! ( "print-type-size t: `{:?}` adt general variants def {} layouts {} {:?}" ,
1860+ ty, adt_def. variants. len( ) , variants. len( ) , variants) ;
1861+ let variant_infos: Vec < _ > = adt_def. variants . iter ( )
1862+ . zip ( variants. iter ( ) )
1863+ . map ( |( variant_def, variant_layout) | {
1864+ let fields: Vec < _ > = variant_def. fields . iter ( )
1865+ . map ( |field_def| ( field_def. name , field_def. ty ( tcx, substs) ) )
1866+ . collect ( ) ;
1867+ build_variant_info ( Some ( variant_def. name ) ,
1868+ & fields,
1869+ Fields :: WithDiscrim ( variant_layout) )
1870+ } )
1871+ . collect ( ) ;
1872+ record ( adt_kind. into ( ) , Some ( discr. size ( ) ) , variant_infos) ;
1873+ }
1874+
1875+ Layout :: UntaggedUnion { ref variants } => {
1876+ debug ! ( "print-type-size t: `{:?}` adt union variants {:?}" ,
1877+ ty, variants) ;
1878+ // layout does not currently store info about each
1879+ // variant...
1880+ record ( adt_kind. into ( ) , None , Vec :: new ( ) ) ;
1881+ }
1882+
1883+ Layout :: CEnum { discr, .. } => {
1884+ debug ! ( "print-type-size t: `{:?}` adt c-like enum" , ty) ;
1885+ let variant_infos: Vec < _ > =
1886+ adt_def. variants . iter ( )
1887+ . map ( |variant_def| {
1888+ build_primitive_info ( variant_def. name ,
1889+ & Primitive :: Int ( discr) )
1890+ } )
1891+ . collect ( ) ;
1892+ record ( adt_kind. into ( ) , Some ( discr. size ( ) ) , variant_infos) ;
1893+ }
1894+
1895+ // other cases provide little interesting (i.e. adjustable
1896+ // via representation tweaks) size info beyond total size.
1897+ Layout :: Scalar { .. } |
1898+ Layout :: Vector { .. } |
1899+ Layout :: Array { .. } |
1900+ Layout :: FatPointer { .. } => {
1901+ debug ! ( "print-type-size t: `{:?}` adt other" , ty) ;
1902+ record ( adt_kind. into ( ) , None , Vec :: new ( ) )
1903+ }
1904+ }
1905+ }
16931906}
16941907
16951908/// Type size "skeleton", i.e. the only information determining a type's size.
0 commit comments