1- #[ cfg( feature = "nightly" ) ]
2- use crate :: { BackendRepr , FieldsShape , Primitive , Size , TyAbiInterface , TyAndLayout , Variants } ;
3-
41mod reg;
52
63pub use reg:: { Reg , RegKind } ;
@@ -35,8 +32,7 @@ impl HomogeneousAggregate {
3532 /// Try to combine two `HomogeneousAggregate`s, e.g. from two fields in
3633 /// the same `struct`. Only succeeds if only one of them has any data,
3734 /// or both units are identical.
38- #[ cfg( feature = "nightly" ) ]
39- fn merge ( self , other : HomogeneousAggregate ) -> Result < HomogeneousAggregate , Heterogeneous > {
35+ pub fn merge ( self , other : HomogeneousAggregate ) -> Result < HomogeneousAggregate , Heterogeneous > {
4036 match ( self , other) {
4137 ( x, HomogeneousAggregate :: NoData ) | ( HomogeneousAggregate :: NoData , x) => Ok ( x) ,
4238
@@ -49,145 +45,3 @@ impl HomogeneousAggregate {
4945 }
5046 }
5147}
52-
53- #[ cfg( feature = "nightly" ) ]
54- impl < ' a , Ty > TyAndLayout < ' a , Ty > {
55- /// Returns `Homogeneous` if this layout is an aggregate containing fields of
56- /// only a single type (e.g., `(u32, u32)`). Such aggregates are often
57- /// special-cased in ABIs.
58- ///
59- /// Note: We generally ignore 1-ZST fields when computing this value (see #56877).
60- ///
61- /// This is public so that it can be used in unit tests, but
62- /// should generally only be relevant to the ABI details of
63- /// specific targets.
64- #[ tracing:: instrument( skip( cx) , level = "debug" ) ]
65- pub fn homogeneous_aggregate < C > ( & self , cx : & C ) -> Result < HomogeneousAggregate , Heterogeneous >
66- where
67- Ty : TyAbiInterface < ' a , C > + Copy ,
68- {
69- match self . backend_repr {
70- // The primitive for this algorithm.
71- BackendRepr :: Scalar ( scalar) => {
72- let kind = match scalar. primitive ( ) {
73- Primitive :: Int ( ..) | Primitive :: Pointer ( _) => RegKind :: Integer ,
74- Primitive :: Float ( _) => RegKind :: Float ,
75- } ;
76- Ok ( HomogeneousAggregate :: Homogeneous ( Reg { kind, size : self . size } ) )
77- }
78-
79- BackendRepr :: SimdVector { element, count : _ } => {
80- assert ! ( !self . is_zst( ) ) ;
81-
82- Ok ( HomogeneousAggregate :: Homogeneous ( Reg {
83- kind : RegKind :: Vector { hint_vector_elem : element. primitive ( ) } ,
84- size : self . size ,
85- } ) )
86- }
87-
88- BackendRepr :: SimdScalableVector { .. } => {
89- unreachable ! ( "`homogeneous_aggregate` should not be called for scalable vectors" )
90- }
91-
92- BackendRepr :: ScalarPair ( ..) | BackendRepr :: Memory { sized : true } => {
93- // Helper for computing `homogeneous_aggregate`, allowing a custom
94- // starting offset (used below for handling variants).
95- let from_fields_at =
96- |layout : Self ,
97- start : Size |
98- -> Result < ( HomogeneousAggregate , Size ) , Heterogeneous > {
99- let is_union = match layout. fields {
100- FieldsShape :: Primitive => {
101- unreachable ! ( "aggregates can't have `FieldsShape::Primitive`" )
102- }
103- FieldsShape :: Array { count, .. } => {
104- assert_eq ! ( start, Size :: ZERO ) ;
105-
106- let result = if count > 0 {
107- layout. field ( cx, 0 ) . homogeneous_aggregate ( cx) ?
108- } else {
109- HomogeneousAggregate :: NoData
110- } ;
111- return Ok ( ( result, layout. size ) ) ;
112- }
113- FieldsShape :: Union ( _) => true ,
114- FieldsShape :: Arbitrary { .. } => false ,
115- } ;
116-
117- let mut result = HomogeneousAggregate :: NoData ;
118- let mut total = start;
119-
120- for i in 0 ..layout. fields . count ( ) {
121- let field = layout. field ( cx, i) ;
122- if field. is_1zst ( ) {
123- // No data here and no impact on layout, can be ignored.
124- // (We might be able to also ignore all aligned ZST but that's less clear.)
125- continue ;
126- }
127-
128- if !is_union && total != layout. fields . offset ( i) {
129- // This field isn't just after the previous one we considered, abort.
130- return Err ( Heterogeneous ) ;
131- }
132-
133- result = result. merge ( field. homogeneous_aggregate ( cx) ?) ?;
134-
135- // Keep track of the offset (without padding).
136- let size = field. size ;
137- if is_union {
138- total = total. max ( size) ;
139- } else {
140- total += size;
141- }
142- }
143-
144- Ok ( ( result, total) )
145- } ;
146-
147- let ( mut result, mut total) = from_fields_at ( * self , Size :: ZERO ) ?;
148-
149- match & self . variants {
150- Variants :: Single { .. } | Variants :: Empty => { }
151- Variants :: Multiple { variants, .. } => {
152- // Treat enum variants like union members.
153- // HACK(eddyb) pretend the `enum` field (discriminant)
154- // is at the start of every variant (otherwise the gap
155- // at the start of all variants would disqualify them).
156- //
157- // NB: for all tagged `enum`s (which include all non-C-like
158- // `enum`s with defined FFI representation), this will
159- // match the homogeneous computation on the equivalent
160- // `struct { tag; union { variant1; ... } }` and/or
161- // `union { struct { tag; variant1; } ... }`
162- // (the offsets of variant fields should be identical
163- // between the two for either to be a homogeneous aggregate).
164- let variant_start = total;
165- for variant_idx in variants. indices ( ) {
166- let ( variant_result, variant_total) =
167- from_fields_at ( self . for_variant ( cx, variant_idx) , variant_start) ?;
168-
169- result = result. merge ( variant_result) ?;
170- total = total. max ( variant_total) ;
171- }
172- }
173- }
174-
175- // There needs to be no padding.
176- if total != self . size {
177- Err ( Heterogeneous )
178- } else {
179- match result {
180- HomogeneousAggregate :: Homogeneous ( _) => {
181- assert_ne ! ( total, Size :: ZERO ) ;
182- }
183- HomogeneousAggregate :: NoData => {
184- assert_eq ! ( total, Size :: ZERO ) ;
185- }
186- }
187- Ok ( result)
188- }
189- }
190- BackendRepr :: Memory { sized : false } => Err ( Heterogeneous ) ,
191- }
192- }
193- }
0 commit comments