@@ -16,9 +16,11 @@ use context::CodegenCx;
1616
1717use rustc:: ty:: layout:: { self , TyLayout , Size } ;
1818
19- #[ derive( Clone , Copy , PartialEq , Debug ) ]
19+ /// Classification of "eightbyte" components.
20+ // NB: the order of the variants is from general to specific,
21+ // such that `unify(a, b)` is the "smaller" of `a` and `b`.
22+ #[ derive( Clone , Copy , PartialEq , Eq , PartialOrd , Ord , Debug ) ]
2023enum Class {
21- None ,
2224 Int ,
2325 Sse ,
2426 SseUp
@@ -32,29 +34,10 @@ const LARGEST_VECTOR_SIZE: usize = 512;
3234const MAX_EIGHTBYTES : usize = LARGEST_VECTOR_SIZE / 64 ;
3335
3436fn classify_arg < ' a , ' tcx > ( cx : & CodegenCx < ' a , ' tcx > , arg : & ArgType < ' tcx > )
35- -> Result < [ Class ; MAX_EIGHTBYTES ] , Memory > {
36- fn unify ( cls : & mut [ Class ] ,
37- off : Size ,
38- c : Class ) {
39- let i = ( off. bytes ( ) / 8 ) as usize ;
40- let to_write = match ( cls[ i] , c) {
41- ( Class :: None , _) => c,
42- ( _, Class :: None ) => return ,
43-
44- ( Class :: Int , _) |
45- ( _, Class :: Int ) => Class :: Int ,
46-
47- ( Class :: Sse , _) |
48- ( _, Class :: Sse ) => Class :: Sse ,
49-
50- ( Class :: SseUp , Class :: SseUp ) => Class :: SseUp
51- } ;
52- cls[ i] = to_write;
53- }
54-
37+ -> Result < [ Option < Class > ; MAX_EIGHTBYTES ] , Memory > {
5538 fn classify < ' a , ' tcx > ( cx : & CodegenCx < ' a , ' tcx > ,
5639 layout : TyLayout < ' tcx > ,
57- cls : & mut [ Class ] ,
40+ cls : & mut [ Option < Class > ] ,
5841 off : Size )
5942 -> Result < ( ) , Memory > {
6043 if !off. is_abi_aligned ( layout. align ) {
@@ -64,31 +47,20 @@ fn classify_arg<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &ArgType<'tcx>)
6447 return Ok ( ( ) ) ;
6548 }
6649
67- match layout. abi {
68- layout:: Abi :: Uninhabited => { }
50+ let mut c = match layout. abi {
51+ layout:: Abi :: Uninhabited => return Ok ( ( ) ) ,
6952
7053 layout:: Abi :: Scalar ( ref scalar) => {
71- let reg = match scalar. value {
54+ match scalar. value {
7255 layout:: Int ( ..) |
7356 layout:: Pointer => Class :: Int ,
7457 layout:: F32 |
7558 layout:: F64 => Class :: Sse
76- } ;
77- unify ( cls, off, reg) ;
78- }
79-
80- layout:: Abi :: Vector { ref element, count } => {
81- unify ( cls, off, Class :: Sse ) ;
82-
83- // everything after the first one is the upper
84- // half of a register.
85- let stride = element. value . size ( cx) ;
86- for i in 1 ..count {
87- let field_off = off + stride * i;
88- unify ( cls, field_off, Class :: SseUp ) ;
8959 }
9060 }
9161
62+ layout:: Abi :: Vector { .. } => Class :: Sse ,
63+
9264 layout:: Abi :: ScalarPair ( ..) |
9365 layout:: Abi :: Aggregate { .. } => {
9466 match layout. variants {
@@ -97,12 +69,26 @@ fn classify_arg<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &ArgType<'tcx>)
9769 let field_off = off + layout. fields . offset ( i) ;
9870 classify ( cx, layout. field ( cx, i) , cls, field_off) ?;
9971 }
72+ return Ok ( ( ) ) ;
10073 }
10174 layout:: Variants :: Tagged { .. } |
10275 layout:: Variants :: NicheFilling { .. } => return Err ( Memory ) ,
10376 }
10477 }
10578
79+ } ;
80+
81+ // Fill in `cls` for scalars (Int/Sse) and vectors (Sse).
82+ let first = ( off. bytes ( ) / 8 ) as usize ;
83+ let last = ( ( off. bytes ( ) + layout. size . bytes ( ) - 1 ) / 8 ) as usize ;
84+ for cls in & mut cls[ first..=last] {
85+ * cls = Some ( cls. map_or ( c, |old| old. min ( c) ) ) ;
86+
87+ // Everything after the first Sse "eightbyte"
88+ // component is the upper half of a register.
89+ if c == Class :: Sse {
90+ c = Class :: SseUp ;
91+ }
10692 }
10793
10894 Ok ( ( ) )
@@ -113,23 +99,23 @@ fn classify_arg<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &ArgType<'tcx>)
11399 return Err ( Memory ) ;
114100 }
115101
116- let mut cls = [ Class :: None ; MAX_EIGHTBYTES ] ;
102+ let mut cls = [ None ; MAX_EIGHTBYTES ] ;
117103 classify ( cx, arg. layout , & mut cls, Size :: from_bytes ( 0 ) ) ?;
118104 if n > 2 {
119- if cls[ 0 ] != Class :: Sse {
105+ if cls[ 0 ] != Some ( Class :: Sse ) {
120106 return Err ( Memory ) ;
121107 }
122- if cls[ 1 ..n] . iter ( ) . any ( |& c| c != Class :: SseUp ) {
108+ if cls[ 1 ..n] . iter ( ) . any ( |& c| c != Some ( Class :: SseUp ) ) {
123109 return Err ( Memory ) ;
124110 }
125111 } else {
126112 let mut i = 0 ;
127113 while i < n {
128- if cls[ i] == Class :: SseUp {
129- cls[ i] = Class :: Sse ;
130- } else if cls[ i] == Class :: Sse {
114+ if cls[ i] == Some ( Class :: SseUp ) {
115+ cls[ i] = Some ( Class :: Sse ) ;
116+ } else if cls[ i] == Some ( Class :: Sse ) {
131117 i += 1 ;
132- while i != n && cls[ i] == Class :: SseUp { i += 1 ; }
118+ while i != n && cls[ i] == Some ( Class :: SseUp ) { i += 1 ; }
133119 } else {
134120 i += 1 ;
135121 }
@@ -139,14 +125,14 @@ fn classify_arg<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &ArgType<'tcx>)
139125 Ok ( cls)
140126}
141127
142- fn reg_component ( cls : & [ Class ] , i : & mut usize , size : Size ) -> Option < Reg > {
128+ fn reg_component ( cls : & [ Option < Class > ] , i : & mut usize , size : Size ) -> Option < Reg > {
143129 if * i >= cls. len ( ) {
144130 return None ;
145131 }
146132
147133 match cls[ * i] {
148- Class :: None => None ,
149- Class :: Int => {
134+ None => None ,
135+ Some ( Class :: Int ) => {
150136 * i += 1 ;
151137 Some ( match size. bytes ( ) {
152138 1 => Reg :: i8 ( ) ,
@@ -156,8 +142,10 @@ fn reg_component(cls: &[Class], i: &mut usize, size: Size) -> Option<Reg> {
156142 _ => Reg :: i64 ( )
157143 } )
158144 }
159- Class :: Sse => {
160- let vec_len = 1 + cls[ * i+1 ..] . iter ( ) . take_while ( |& & c| c == Class :: SseUp ) . count ( ) ;
145+ Some ( Class :: Sse ) => {
146+ let vec_len = 1 + cls[ * i+1 ..] . iter ( )
147+ . take_while ( |& & c| c == Some ( Class :: SseUp ) )
148+ . count ( ) ;
161149 * i += vec_len;
162150 Some ( if vec_len == 1 {
163151 match size. bytes ( ) {
@@ -171,11 +159,11 @@ fn reg_component(cls: &[Class], i: &mut usize, size: Size) -> Option<Reg> {
171159 }
172160 } )
173161 }
174- c => bug ! ( "reg_component: unhandled class {:?}" , c)
162+ Some ( c ) => bug ! ( "reg_component: unhandled class {:?}" , c)
175163 }
176164}
177165
178- fn cast_target ( cls : & [ Class ] , size : Size ) -> CastTarget {
166+ fn cast_target ( cls : & [ Option < Class > ] , size : Size ) -> CastTarget {
179167 let mut i = 0 ;
180168 let lo = reg_component ( cls, & mut i, size) . unwrap ( ) ;
181169 let offset = Size :: from_bytes ( 8 ) * ( i as u64 ) ;
@@ -203,8 +191,8 @@ pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tc
203191 Ok ( ref cls) if is_arg => {
204192 for & c in cls {
205193 match c {
206- Class :: Int => needed_int += 1 ,
207- Class :: Sse => needed_sse += 1 ,
194+ Some ( Class :: Int ) => needed_int += 1 ,
195+ Some ( Class :: Sse ) => needed_sse += 1 ,
208196 _ => { }
209197 }
210198 }
0 commit comments