@@ -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:: { self , DataTypeKind , Session } ;
16
- use ty:: { self , Ty , TyCtxt , TypeFoldable , ReprOptions , ReprFlags } ;
15
+ use session:: Session ;
16
+ use ty:: { self , item_path , Ty , TyCtxt , TypeFoldable , ReprOptions , ReprFlags , Visibility } ;
17
17
18
- use syntax:: ast:: { self , FloatTy , IntTy , UintTy } ;
18
+ use syntax:: ast:: { FloatTy , IntTy , UintTy } ;
19
19
use syntax:: attr;
20
20
use syntax_pos:: DUMMY_SP ;
21
21
@@ -1719,15 +1719,14 @@ impl<'a, 'tcx> Layout {
1719
1719
pub fn record_layout_for_printing ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
1720
1720
ty : Ty < ' tcx > ,
1721
1721
param_env : ty:: ParamEnv < ' tcx > ,
1722
- layout : & Layout ) {
1722
+ layout : & ' tcx Layout ) {
1723
1723
// If we are running with `-Zprint-type-sizes`, record layouts for
1724
1724
// dumping later. Ignore layouts that are done with non-empty
1725
1725
// environments or non-monomorphic layouts, as the user only wants
1726
1726
// to see the stuff resulting from the final trans session.
1727
1727
if
1728
1728
!tcx. sess . opts . debugging_opts . print_type_sizes ||
1729
- ty. has_param_types ( ) ||
1730
- ty. has_self_ty ( ) ||
1729
+ !ty. is_normalized_for_trans ( ) ||
1731
1730
!param_env. caller_bounds . is_empty ( )
1732
1731
{
1733
1732
return ;
@@ -1739,197 +1738,142 @@ impl<'a, 'tcx> Layout {
1739
1738
fn record_layout_for_printing_outlined ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
1740
1739
ty : Ty < ' tcx > ,
1741
1740
param_env : ty:: ParamEnv < ' tcx > ,
1742
- layout : & Layout ) {
1743
- // (delay format until we actually need it)
1744
- let record = |kind, opt_discr_size, variants| {
1745
- let type_desc = format ! ( "{:?}" , ty) ;
1746
- let overall_size = layout. size ( tcx) ;
1747
- let align = layout. align ( tcx) ;
1748
- tcx. sess . code_stats . borrow_mut ( ) . record_type_size ( kind,
1749
- type_desc,
1750
- align,
1751
- overall_size,
1752
- opt_discr_size,
1753
- variants) ;
1754
- } ;
1741
+ layout : & ' tcx Layout ) {
1755
1742
1756
- let ( adt_def, substs) = match ty. sty {
1757
- ty:: TyAdt ( ref adt_def, substs) => {
1758
- debug ! ( "print-type-size t: `{:?}` process adt" , ty) ;
1759
- ( adt_def, substs)
1760
- }
1743
+ use session:: print_type_info:: { Type , TypeKind , Field , Case } ;
1761
1744
1762
- ty:: TyClosure ( ..) => {
1763
- debug ! ( "print-type-size t: `{:?}` record closure" , ty) ;
1764
- record ( DataTypeKind :: Closure , None , vec ! [ ] ) ;
1765
- return ;
1766
- }
1745
+ // Caller should have filtered out all non-monomorphic types, so we
1746
+ // we don't need to worry about finding a generic Vec<T> or Vec<U::Item>
1747
+ match ty. sty {
1748
+ // Concrete types we should consider processing
1749
+ ty:: TyBool |
1750
+ ty:: TyChar |
1751
+ ty:: TyInt ( ..) |
1752
+ ty:: TyUint ( ..) |
1753
+ ty:: TyFloat ( ..) |
1754
+ ty:: TyAdt ( ..) |
1755
+ ty:: TyRawPtr ( ..) |
1756
+ ty:: TyRef ( ..) |
1757
+ ty:: TyNever |
1758
+ ty:: TyTuple ( ..) => { }
1767
1759
1760
+ // Anonymous or generic types we should avoid
1768
1761
_ => {
1762
+ // TODO: `-> impl Trait` means closures can technically end up
1763
+ // in public signatures, so we might want to actually record them?
1769
1764
debug ! ( "print-type-size t: `{:?}` skip non-nominal" , ty) ;
1770
1765
return ;
1771
1766
}
1772
1767
} ;
1773
1768
1774
- let adt_kind = adt_def. adt_kind ( ) ;
1775
-
1776
- let build_field_info = |( field_name, field_ty) : ( ast:: Name , Ty < ' tcx > ) , offset : & Size | {
1777
- let layout = field_ty. layout ( tcx, param_env) ;
1778
- match layout {
1779
- Err ( _) => bug ! ( "no layout found for field {} type: `{:?}`" , field_name, field_ty) ,
1780
- Ok ( field_layout) => {
1781
- session:: FieldInfo {
1782
- name : field_name. to_string ( ) ,
1783
- offset : offset. bytes ( ) ,
1784
- size : field_layout. size ( tcx) . bytes ( ) ,
1785
- align : field_layout. align ( tcx) . abi ( ) ,
1786
- }
1787
- }
1788
- }
1769
+ let cx = LayoutCx :: new ( tcx, param_env) ;
1770
+
1771
+ let layout = TyLayout {
1772
+ ty,
1773
+ layout : layout,
1774
+ variant_index : None
1789
1775
} ;
1790
1776
1791
- let build_primitive_info = |name : ast:: Name , value : & Primitive | {
1792
- session:: VariantInfo {
1793
- name : Some ( name. to_string ( ) ) ,
1794
- kind : session:: SizeKind :: Exact ,
1795
- align : value. align ( tcx) . abi ( ) ,
1796
- size : value. size ( tcx) . bytes ( ) ,
1797
- fields : vec ! [ ] ,
1777
+ // Common code for structs and unions
1778
+ let fields = || {
1779
+ let field_count = layout. field_count ( ) ;
1780
+ let mut fields = Vec :: with_capacity ( field_count) ;
1781
+
1782
+ for i in 0 ..field_count {
1783
+ let offset = layout. field_offset ( cx, i) . bytes ( ) ;
1784
+ let field_ty = layout. field_type ( cx, i) ;
1785
+ let type_name = item_path:: with_forced_impl_filename_line ( ||{
1786
+ field_ty. to_string ( )
1787
+ } ) ;
1788
+ let ( name, public) = layout. field_info ( cx, i) ;
1789
+
1790
+ let field = Field {
1791
+ name,
1792
+ offset,
1793
+ type_name,
1794
+ public,
1795
+ } ;
1796
+
1797
+ fields. push ( field) ;
1798
1798
}
1799
+
1800
+ fields
1799
1801
} ;
1800
1802
1801
- enum Fields < ' a > {
1802
- WithDiscrim ( & ' a Struct ) ,
1803
- NoDiscrim ( & ' a Struct ) ,
1804
- }
1803
+ let kind = match * layout {
1804
+ // Basic primitive, nothing interesting to do
1805
+ Layout :: Scalar { value : Primitive :: Int ( ..) , .. } => {
1806
+ TypeKind :: PrimitiveInt
1807
+ }
1808
+ Layout :: Scalar { value : Primitive :: F32 , .. } |
1809
+ Layout :: Scalar { value : Primitive :: F64 , .. } => {
1810
+ TypeKind :: PrimitiveFloat
1811
+ }
1805
1812
1806
- let build_variant_info = |n : Option < ast:: Name > ,
1807
- flds : & [ ( ast:: Name , Ty < ' tcx > ) ] ,
1808
- layout : Fields | {
1809
- let ( s, field_offsets) = match layout {
1810
- Fields :: WithDiscrim ( s) => ( s, & s. offsets [ 1 ..] ) ,
1811
- Fields :: NoDiscrim ( s) => ( s, & s. offsets [ 0 ..] ) ,
1812
- } ;
1813
- let field_info: Vec < _ > =
1814
- flds. iter ( )
1815
- . zip ( field_offsets. iter ( ) )
1816
- . map ( |( & field_name_ty, offset) | build_field_info ( field_name_ty, offset) )
1817
- . collect ( ) ;
1818
-
1819
- session:: VariantInfo {
1820
- name : n. map ( |n|n. to_string ( ) ) ,
1821
- kind : if s. sized {
1822
- session:: SizeKind :: Exact
1823
- } else {
1824
- session:: SizeKind :: Min
1825
- } ,
1826
- align : s. align . abi ( ) ,
1827
- size : s. min_size . bytes ( ) ,
1828
- fields : field_info,
1813
+ // Thin pointers; don't record these
1814
+ Layout :: Scalar { value : Primitive :: Pointer , .. } |
1815
+ Layout :: RawNullablePointer { .. } => {
1816
+ // TODO: do we maybe want to actually type RawNullablePointer?
1817
+ // Option<Box>/Option<Rc> aren't quite the same as Option<&>...
1818
+ return ;
1829
1819
}
1830
- } ;
1831
1820
1832
- match * layout {
1833
- Layout :: StructWrappedNullablePointer { nonnull : ref variant_layout,
1834
- nndiscr,
1835
- discrfield : _,
1836
- discrfield_source : _ } => {
1837
- debug ! ( "print-type-size t: `{:?}` adt struct-wrapped nullable nndiscr {} is {:?}" ,
1838
- ty, nndiscr, variant_layout) ;
1839
- let variant_def = & adt_def. variants [ nndiscr as usize ] ;
1840
- let fields: Vec < _ > =
1841
- variant_def. fields . iter ( )
1842
- . map ( |field_def| ( field_def. name , field_def. ty ( tcx, substs) ) )
1843
- . collect ( ) ;
1844
- record ( adt_kind. into ( ) ,
1845
- None ,
1846
- vec ! [ build_variant_info( Some ( variant_def. name) ,
1847
- & fields,
1848
- Fields :: NoDiscrim ( variant_layout) ) ] ) ;
1849
- }
1850
- Layout :: RawNullablePointer { nndiscr, value } => {
1851
- debug ! ( "print-type-size t: `{:?}` adt raw nullable nndiscr {} is {:?}" ,
1852
- ty, nndiscr, value) ;
1853
- let variant_def = & adt_def. variants [ nndiscr as usize ] ;
1854
- record ( adt_kind. into ( ) , None ,
1855
- vec ! [ build_primitive_info( variant_def. name, & value) ] ) ;
1856
- }
1857
- Layout :: Univariant { variant : ref variant_layout, non_zero : _ } => {
1858
- let variant_names = || {
1859
- adt_def. variants . iter ( ) . map ( |v|format ! ( "{}" , v. name) ) . collect :: < Vec < _ > > ( )
1860
- } ;
1861
- debug ! ( "print-type-size t: `{:?}` adt univariant {:?} variants: {:?}" ,
1862
- ty, variant_layout, variant_names( ) ) ;
1863
- assert ! ( adt_def. variants. len( ) <= 1 ,
1864
- "univariant with variants {:?}" , variant_names( ) ) ;
1865
- if adt_def. variants . len ( ) == 1 {
1866
- let variant_def = & adt_def. variants [ 0 ] ;
1867
- let fields: Vec < _ > =
1868
- variant_def. fields . iter ( )
1869
- . map ( |f| ( f. name , f. ty ( tcx, substs) ) )
1870
- . collect ( ) ;
1871
- record ( adt_kind. into ( ) ,
1872
- None ,
1873
- vec ! [ build_variant_info( Some ( variant_def. name) ,
1874
- & fields,
1875
- Fields :: NoDiscrim ( variant_layout) ) ] ) ;
1876
- } else {
1877
- // (This case arises for *empty* enums; so give it
1878
- // zero variants.)
1879
- record ( adt_kind. into ( ) , None , vec ! [ ] ) ;
1821
+ // Structs
1822
+ Layout :: Vector { .. } |
1823
+ Layout :: FatPointer { .. } |
1824
+ Layout :: Univariant { .. } => {
1825
+ TypeKind :: Struct { fields : fields ( ) }
1826
+ }
1827
+
1828
+ // Union
1829
+ Layout :: UntaggedUnion { .. } => {
1830
+ TypeKind :: Union { fields : fields ( ) }
1831
+ }
1832
+
1833
+
1834
+ // C-like Enums
1835
+ Layout :: CEnum { discr, signed, .. } => {
1836
+ let base_type = item_path:: with_forced_impl_filename_line ( ||{
1837
+ discr. to_ty ( & tcx, signed) . to_string ( )
1838
+ } ) ;
1839
+
1840
+ let def = if let ty:: TyAdt ( def, ..) = ty. sty { def } else { unreachable ! ( ) } ;
1841
+
1842
+ let mut cases = Vec :: with_capacity ( def. variants . len ( ) ) ;
1843
+ for ( discr, variant) in def. discriminants ( tcx) . zip ( def. variants . iter ( ) ) {
1844
+ // TODO: i128?
1845
+ let value = discr. to_u128_unchecked ( ) as i64 ;
1846
+ let name = variant. name . to_string ( ) ;
1847
+ let case = Case { name, value } ;
1848
+ cases. push ( case) ;
1880
1849
}
1850
+
1851
+ TypeKind :: Enum { base_type, cases }
1881
1852
}
1882
1853
1883
- Layout :: General { ref variants, discr, .. } => {
1884
- debug ! ( "print-type-size t: `{:?}` adt general variants def {} layouts {} {:?}" ,
1885
- ty, adt_def. variants. len( ) , variants. len( ) , variants) ;
1886
- let variant_infos: Vec < _ > =
1887
- adt_def. variants . iter ( )
1888
- . zip ( variants. iter ( ) )
1889
- . map ( |( variant_def, variant_layout) | {
1890
- let fields: Vec < _ > =
1891
- variant_def. fields
1892
- . iter ( )
1893
- . map ( |f| ( f. name , f. ty ( tcx, substs) ) )
1894
- . collect ( ) ;
1895
- build_variant_info ( Some ( variant_def. name ) ,
1896
- & fields,
1897
- Fields :: WithDiscrim ( variant_layout) )
1898
- } )
1899
- . collect ( ) ;
1900
- record ( adt_kind. into ( ) , Some ( discr. size ( ) ) , variant_infos) ;
1901
- }
1902
-
1903
- Layout :: UntaggedUnion { ref variants } => {
1904
- debug ! ( "print-type-size t: `{:?}` adt union variants {:?}" ,
1905
- ty, variants) ;
1906
- // layout does not currently store info about each
1907
- // variant...
1908
- record ( adt_kind. into ( ) , None , Vec :: new ( ) ) ;
1909
- }
1910
-
1911
- Layout :: CEnum { discr, .. } => {
1912
- debug ! ( "print-type-size t: `{:?}` adt c-like enum" , ty) ;
1913
- let variant_infos: Vec < _ > =
1914
- adt_def. variants . iter ( )
1915
- . map ( |variant_def| {
1916
- build_primitive_info ( variant_def. name ,
1917
- & Primitive :: Int ( discr) )
1918
- } )
1919
- . collect ( ) ;
1920
- record ( adt_kind. into ( ) , Some ( discr. size ( ) ) , variant_infos) ;
1921
- }
1922
-
1923
- // other cases provide little interesting (i.e. adjustable
1924
- // via representation tweaks) size info beyond total size.
1925
- Layout :: Scalar { .. } |
1926
- Layout :: Vector { .. } |
1927
- Layout :: Array { .. } |
1928
- Layout :: FatPointer { .. } => {
1929
- debug ! ( "print-type-size t: `{:?}` adt other" , ty) ;
1930
- record ( adt_kind. into ( ) , None , Vec :: new ( ) )
1854
+ // Don't expose details of tagged unions yet, as we
1855
+ // reserve the right to do pretty extreme optimizations, and don't
1856
+ // want to settle on an abstraction yet.
1857
+ Layout :: General { .. } |
1858
+ StructWrappedNullablePointer { .. } => {
1859
+ TypeKind :: Opaque
1931
1860
}
1932
- }
1861
+
1862
+ Layout :: Array { .. } => {
1863
+ bug ! ( "Arrays shouldn't ever make it here" )
1864
+ }
1865
+ } ;
1866
+
1867
+ let size = layout. size ( tcx) . bytes ( ) ;
1868
+ let align = layout. align ( tcx) . abi ( ) ;
1869
+ let name = item_path:: with_forced_impl_filename_line ( ||{
1870
+ ty. to_string ( )
1871
+ } ) ;
1872
+ let public = true ; // TODO
1873
+
1874
+ tcx. sess . code_stats . borrow_mut ( ) . insert ( Type {
1875
+ name, size, align, public, kind
1876
+ } ) ;
1933
1877
}
1934
1878
}
1935
1879
@@ -2264,6 +2208,91 @@ impl<'a, 'tcx> TyLayout<'tcx> {
2264
2208
}
2265
2209
}
2266
2210
2211
+ /// Gets the field name, and whether the field is `pub`, for use in print-type-info.
2212
+ ///
2213
+ /// Fields of builtins have synthesized names that are valid C idents.
2214
+ /// e.g. tuple.0 becomes tuple.item0
2215
+ ///
2216
+ /// Note: some of these results aren't ever used by print-type-info, because these types
2217
+ /// have a natural C ABI (i.e. TyArray).
2218
+ fn field_info < C : LayoutTyper < ' tcx > > ( & self , cx : C , i : usize ) -> ( String , bool ) {
2219
+ let tcx = cx. tcx ( ) ;
2220
+
2221
+ let ptr_field_info = |pointee : Ty < ' tcx > | {
2222
+ assert ! ( i < 2 ) ;
2223
+ match tcx. struct_tail ( pointee) . sty {
2224
+ ty:: TySlice ( ..) |
2225
+ ty:: TyStr => {
2226
+ if i == 0 {
2227
+ ( "ptr" . to_string ( ) , false )
2228
+ } else {
2229
+ ( "len" . to_string ( ) , false )
2230
+ }
2231
+ }
2232
+ ty:: TyDynamic ( ..) => {
2233
+ if i == 0 {
2234
+ ( "data" . to_string ( ) , false )
2235
+ } else {
2236
+ ( "vtable" . to_string ( ) , false )
2237
+ }
2238
+ }
2239
+ _ => bug ! ( "TyLayout::field_info({:?}): not applicable" , self )
2240
+ }
2241
+ } ;
2242
+
2243
+ match self . ty . sty {
2244
+ ty:: TyBool |
2245
+ ty:: TyChar |
2246
+ ty:: TyInt ( _) |
2247
+ ty:: TyUint ( _) |
2248
+ ty:: TyFloat ( _) |
2249
+ ty:: TyFnPtr ( _) |
2250
+ ty:: TyNever |
2251
+ ty:: TyFnDef ( ..) |
2252
+ ty:: TyDynamic ( ..) |
2253
+ ty:: TySlice ( ..) |
2254
+ ty:: TyStr => {
2255
+ bug ! ( "TyLayout::field_info({:?}): not applicable" , self )
2256
+ }
2257
+
2258
+ // Potentially-fat pointers.
2259
+ ty:: TyRef ( _, ty:: TypeAndMut { ty : pointee, .. } ) |
2260
+ ty:: TyRawPtr ( ty:: TypeAndMut { ty : pointee, .. } ) => {
2261
+ ptr_field_info ( pointee)
2262
+ }
2263
+ ty:: TyAdt ( def, _) if def. is_box ( ) => {
2264
+ ptr_field_info ( self . ty . boxed_ty ( ) )
2265
+ }
2266
+
2267
+ // Arrays and slices.
2268
+ ty:: TyArray ( ..) => ( format ! ( "idx{}" , i) , false ) ,
2269
+
2270
+ // Closures.
2271
+ ty:: TyClosure ( ..) => ( format ! ( "capture{}" , i) , false ) ,
2272
+
2273
+ // Tuples
2274
+ ty:: TyTuple ( ..) => ( format ! ( "item{}" , i) , true ) ,
2275
+
2276
+ // SIMD vectors
2277
+ ty:: TyAdt ( def, ..) if def. repr . simd ( ) => {
2278
+ ( format ! ( "idx{}" , i) , true )
2279
+ }
2280
+
2281
+ // ADTs.
2282
+ ty:: TyAdt ( def, ..) => {
2283
+ let field = & def. variants [ self . variant_index . unwrap_or ( 0 ) ] . fields [ i] ;
2284
+ let public = if let Visibility :: Public = field. vis { true } else { false } ;
2285
+ let name = field. name . to_string ( ) ;
2286
+ ( name, public)
2287
+ }
2288
+
2289
+ ty:: TyProjection ( _) | ty:: TyAnon ( ..) | ty:: TyParam ( _) |
2290
+ ty:: TyInfer ( _) | ty:: TyError => {
2291
+ bug ! ( "TyLayout::field_type: unexpected type `{}`" , self . ty)
2292
+ }
2293
+ }
2294
+ }
2295
+
2267
2296
pub fn field < C : LayoutTyper < ' tcx > > ( & self ,
2268
2297
cx : C ,
2269
2298
i : usize )
0 commit comments