@@ -16,9 +16,11 @@ use context::CodegenCx;
16
16
17
17
use rustc:: ty:: layout:: { self , TyLayout , Size } ;
18
18
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 ) ]
20
23
enum Class {
21
- None ,
22
24
Int ,
23
25
Sse ,
24
26
SseUp
@@ -32,29 +34,10 @@ const LARGEST_VECTOR_SIZE: usize = 512;
32
34
const MAX_EIGHTBYTES : usize = LARGEST_VECTOR_SIZE / 64 ;
33
35
34
36
fn 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 > {
55
38
fn classify < ' a , ' tcx > ( cx : & CodegenCx < ' a , ' tcx > ,
56
39
layout : TyLayout < ' tcx > ,
57
- cls : & mut [ Class ] ,
40
+ cls : & mut [ Option < Class > ] ,
58
41
off : Size )
59
42
-> Result < ( ) , Memory > {
60
43
if !off. is_abi_aligned ( layout. align ) {
@@ -64,31 +47,20 @@ fn classify_arg<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &ArgType<'tcx>)
64
47
return Ok ( ( ) ) ;
65
48
}
66
49
67
- match layout. abi {
68
- layout:: Abi :: Uninhabited => { }
50
+ let mut c = match layout. abi {
51
+ layout:: Abi :: Uninhabited => return Ok ( ( ) ) ,
69
52
70
53
layout:: Abi :: Scalar ( ref scalar) => {
71
- let reg = match scalar. value {
54
+ match scalar. value {
72
55
layout:: Int ( ..) |
73
56
layout:: Pointer => Class :: Int ,
74
57
layout:: F32 |
75
58
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 ) ;
89
59
}
90
60
}
91
61
62
+ layout:: Abi :: Vector { .. } => Class :: Sse ,
63
+
92
64
layout:: Abi :: ScalarPair ( ..) |
93
65
layout:: Abi :: Aggregate { .. } => {
94
66
match layout. variants {
@@ -97,12 +69,26 @@ fn classify_arg<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &ArgType<'tcx>)
97
69
let field_off = off + layout. fields . offset ( i) ;
98
70
classify ( cx, layout. field ( cx, i) , cls, field_off) ?;
99
71
}
72
+ return Ok ( ( ) ) ;
100
73
}
101
74
layout:: Variants :: Tagged { .. } |
102
75
layout:: Variants :: NicheFilling { .. } => return Err ( Memory ) ,
103
76
}
104
77
}
105
78
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
+ }
106
92
}
107
93
108
94
Ok ( ( ) )
@@ -113,23 +99,23 @@ fn classify_arg<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &ArgType<'tcx>)
113
99
return Err ( Memory ) ;
114
100
}
115
101
116
- let mut cls = [ Class :: None ; MAX_EIGHTBYTES ] ;
102
+ let mut cls = [ None ; MAX_EIGHTBYTES ] ;
117
103
classify ( cx, arg. layout , & mut cls, Size :: from_bytes ( 0 ) ) ?;
118
104
if n > 2 {
119
- if cls[ 0 ] != Class :: Sse {
105
+ if cls[ 0 ] != Some ( Class :: Sse ) {
120
106
return Err ( Memory ) ;
121
107
}
122
- if cls[ 1 ..n] . iter ( ) . any ( |& c| c != Class :: SseUp ) {
108
+ if cls[ 1 ..n] . iter ( ) . any ( |& c| c != Some ( Class :: SseUp ) ) {
123
109
return Err ( Memory ) ;
124
110
}
125
111
} else {
126
112
let mut i = 0 ;
127
113
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 ) {
131
117
i += 1 ;
132
- while i != n && cls[ i] == Class :: SseUp { i += 1 ; }
118
+ while i != n && cls[ i] == Some ( Class :: SseUp ) { i += 1 ; }
133
119
} else {
134
120
i += 1 ;
135
121
}
@@ -139,14 +125,14 @@ fn classify_arg<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &ArgType<'tcx>)
139
125
Ok ( cls)
140
126
}
141
127
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 > {
143
129
if * i >= cls. len ( ) {
144
130
return None ;
145
131
}
146
132
147
133
match cls[ * i] {
148
- Class :: None => None ,
149
- Class :: Int => {
134
+ None => None ,
135
+ Some ( Class :: Int ) => {
150
136
* i += 1 ;
151
137
Some ( match size. bytes ( ) {
152
138
1 => Reg :: i8 ( ) ,
@@ -156,8 +142,10 @@ fn reg_component(cls: &[Class], i: &mut usize, size: Size) -> Option<Reg> {
156
142
_ => Reg :: i64 ( )
157
143
} )
158
144
}
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 ( ) ;
161
149
* i += vec_len;
162
150
Some ( if vec_len == 1 {
163
151
match size. bytes ( ) {
@@ -171,11 +159,11 @@ fn reg_component(cls: &[Class], i: &mut usize, size: Size) -> Option<Reg> {
171
159
}
172
160
} )
173
161
}
174
- c => bug ! ( "reg_component: unhandled class {:?}" , c)
162
+ Some ( c ) => bug ! ( "reg_component: unhandled class {:?}" , c)
175
163
}
176
164
}
177
165
178
- fn cast_target ( cls : & [ Class ] , size : Size ) -> CastTarget {
166
+ fn cast_target ( cls : & [ Option < Class > ] , size : Size ) -> CastTarget {
179
167
let mut i = 0 ;
180
168
let lo = reg_component ( cls, & mut i, size) . unwrap ( ) ;
181
169
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
203
191
Ok ( ref cls) if is_arg => {
204
192
for & c in cls {
205
193
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 ,
208
196
_ => { }
209
197
}
210
198
}
0 commit comments