@@ -12,10 +12,10 @@ pub use self::Integer::*;
12
12
pub use self :: Layout :: * ;
13
13
pub use self :: Primitive :: * ;
14
14
15
- use session:: Session ;
15
+ use session:: { self , DataTypeKind , Session } ;
16
16
use ty:: { self , Ty , TyCtxt , TypeFoldable , ReprOptions , ReprFlags } ;
17
17
18
- use syntax:: ast:: { FloatTy , IntTy , UintTy } ;
18
+ use syntax:: ast:: { self , FloatTy , IntTy , UintTy } ;
19
19
use syntax:: attr;
20
20
use syntax_pos:: DUMMY_SP ;
21
21
@@ -1690,6 +1690,219 @@ impl<'a, 'tcx> Layout {
1690
1690
}
1691
1691
}
1692
1692
}
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
+ }
1693
1906
}
1694
1907
1695
1908
/// Type size "skeleton", i.e. the only information determining a type's size.
0 commit comments