1
1
//! Argument passing
2
2
3
- use cranelift_codegen:: ir:: { ArgumentExtension , ArgumentPurpose } ;
3
+ use cranelift_codegen:: ir:: ArgumentPurpose ;
4
4
use rustc_abi:: { Reg , RegKind } ;
5
5
use rustc_target:: callconv:: {
6
6
ArgAbi , ArgAttributes , ArgExtension as RustcArgExtension , CastTarget , PassMode ,
@@ -32,16 +32,26 @@ fn reg_to_abi_param(reg: Reg) -> AbiParam {
32
32
AbiParam :: new ( clif_ty)
33
33
}
34
34
35
- fn apply_arg_attrs_to_abi_param ( mut param : AbiParam , arg_attrs : ArgAttributes ) -> AbiParam {
35
+ fn apply_attrs_to_abi_param ( param : AbiParam , arg_attrs : ArgAttributes ) -> AbiParam {
36
36
match arg_attrs. arg_ext {
37
- RustcArgExtension :: None => { }
38
- RustcArgExtension :: Zext => param. extension = ArgumentExtension :: Uext ,
39
- RustcArgExtension :: Sext => param. extension = ArgumentExtension :: Sext ,
37
+ RustcArgExtension :: None => param ,
38
+ RustcArgExtension :: Zext => param. uext ( ) ,
39
+ RustcArgExtension :: Sext => param. sext ( ) ,
40
40
}
41
- param
42
41
}
43
42
44
- fn cast_target_to_abi_params ( cast : & CastTarget ) -> SmallVec < [ AbiParam ; 2 ] > {
43
+ fn cast_target_to_abi_params ( cast : & CastTarget ) -> SmallVec < [ ( Size , AbiParam ) ; 2 ] > {
44
+ if let Some ( offset_from_start) = cast. rest_offset {
45
+ assert ! ( cast. prefix[ 1 ..] . iter( ) . all( |p| p. is_none( ) ) ) ;
46
+ assert_eq ! ( cast. rest. unit. size, cast. rest. total) ;
47
+ let first = cast. prefix [ 0 ] . unwrap ( ) ;
48
+ let second = cast. rest . unit ;
49
+ return smallvec ! [
50
+ ( Size :: ZERO , reg_to_abi_param( first) ) ,
51
+ ( offset_from_start, reg_to_abi_param( second) )
52
+ ] ;
53
+ }
54
+
45
55
let ( rest_count, rem_bytes) = if cast. rest . unit . size . bytes ( ) == 0 {
46
56
( 0 , 0 )
47
57
} else {
@@ -56,33 +66,40 @@ fn cast_target_to_abi_params(cast: &CastTarget) -> SmallVec<[AbiParam; 2]> {
56
66
// different types in Cranelift IR. Instead a single array of primitive types is used.
57
67
58
68
// Create list of fields in the main structure
59
- let mut args = cast
69
+ let args = cast
60
70
. prefix
61
71
. iter ( )
62
72
. flatten ( )
63
73
. map ( |& reg| reg_to_abi_param ( reg) )
64
- . chain ( ( 0 ..rest_count) . map ( |_| reg_to_abi_param ( cast. rest . unit ) ) )
65
- . collect :: < SmallVec < _ > > ( ) ;
74
+ . chain ( ( 0 ..rest_count) . map ( |_| reg_to_abi_param ( cast. rest . unit ) ) ) ;
75
+
76
+ let mut res = SmallVec :: new ( ) ;
77
+ let mut offset = Size :: ZERO ;
78
+
79
+ for arg in args {
80
+ res. push ( ( offset, arg) ) ;
81
+ offset += Size :: from_bytes ( arg. value_type . bytes ( ) ) ;
82
+ }
66
83
67
84
// Append final integer
68
85
if rem_bytes != 0 {
69
86
// Only integers can be really split further.
70
87
assert_eq ! ( cast. rest. unit. kind, RegKind :: Integer ) ;
71
- args . push ( reg_to_abi_param ( Reg {
72
- kind : RegKind :: Integer ,
73
- size : Size :: from_bytes ( rem_bytes) ,
74
- } ) ) ;
88
+ res . push ( (
89
+ offset ,
90
+ reg_to_abi_param ( Reg { kind : RegKind :: Integer , size : Size :: from_bytes ( rem_bytes) } ) ,
91
+ ) ) ;
75
92
}
76
93
77
- args
94
+ res
78
95
}
79
96
80
97
impl < ' tcx > ArgAbiExt < ' tcx > for ArgAbi < ' tcx , Ty < ' tcx > > {
81
98
fn get_abi_param ( & self , tcx : TyCtxt < ' tcx > ) -> SmallVec < [ AbiParam ; 2 ] > {
82
99
match self . mode {
83
100
PassMode :: Ignore => smallvec ! [ ] ,
84
101
PassMode :: Direct ( attrs) => match self . layout . backend_repr {
85
- BackendRepr :: Scalar ( scalar) => smallvec ! [ apply_arg_attrs_to_abi_param (
102
+ BackendRepr :: Scalar ( scalar) => smallvec ! [ apply_attrs_to_abi_param (
86
103
AbiParam :: new( scalar_to_clif_type( tcx, scalar) ) ,
87
104
attrs
88
105
) ] ,
@@ -97,34 +114,34 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
97
114
let a = scalar_to_clif_type ( tcx, a) ;
98
115
let b = scalar_to_clif_type ( tcx, b) ;
99
116
smallvec ! [
100
- apply_arg_attrs_to_abi_param ( AbiParam :: new( a) , attrs_a) ,
101
- apply_arg_attrs_to_abi_param ( AbiParam :: new( b) , attrs_b) ,
117
+ apply_attrs_to_abi_param ( AbiParam :: new( a) , attrs_a) ,
118
+ apply_attrs_to_abi_param ( AbiParam :: new( b) , attrs_b) ,
102
119
]
103
120
}
104
121
_ => unreachable ! ( "{:?}" , self . layout. backend_repr) ,
105
122
} ,
106
123
PassMode :: Cast { ref cast, pad_i32 } => {
107
124
assert ! ( !pad_i32, "padding support not yet implemented" ) ;
108
- cast_target_to_abi_params ( cast)
125
+ cast_target_to_abi_params ( cast) . into_iter ( ) . map ( | ( _ , param ) | param ) . collect ( )
109
126
}
110
127
PassMode :: Indirect { attrs, meta_attrs : None , on_stack } => {
111
128
if on_stack {
112
129
// Abi requires aligning struct size to pointer size
113
130
let size = self . layout . size . align_to ( tcx. data_layout . pointer_align . abi ) ;
114
131
let size = u32:: try_from ( size. bytes ( ) ) . unwrap ( ) ;
115
- smallvec ! [ apply_arg_attrs_to_abi_param (
132
+ smallvec ! [ apply_attrs_to_abi_param (
116
133
AbiParam :: special( pointer_ty( tcx) , ArgumentPurpose :: StructArgument ( size) , ) ,
117
134
attrs
118
135
) ]
119
136
} else {
120
- smallvec ! [ apply_arg_attrs_to_abi_param ( AbiParam :: new( pointer_ty( tcx) ) , attrs) ]
137
+ smallvec ! [ apply_attrs_to_abi_param ( AbiParam :: new( pointer_ty( tcx) ) , attrs) ]
121
138
}
122
139
}
123
140
PassMode :: Indirect { attrs, meta_attrs : Some ( meta_attrs) , on_stack } => {
124
141
assert ! ( !on_stack) ;
125
142
smallvec ! [
126
- apply_arg_attrs_to_abi_param ( AbiParam :: new( pointer_ty( tcx) ) , attrs) ,
127
- apply_arg_attrs_to_abi_param ( AbiParam :: new( pointer_ty( tcx) ) , meta_attrs) ,
143
+ apply_attrs_to_abi_param ( AbiParam :: new( pointer_ty( tcx) ) , attrs) ,
144
+ apply_attrs_to_abi_param ( AbiParam :: new( pointer_ty( tcx) ) , meta_attrs) ,
128
145
]
129
146
}
130
147
}
@@ -133,30 +150,47 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
133
150
fn get_abi_return ( & self , tcx : TyCtxt < ' tcx > ) -> ( Option < AbiParam > , Vec < AbiParam > ) {
134
151
match self . mode {
135
152
PassMode :: Ignore => ( None , vec ! [ ] ) ,
136
- PassMode :: Direct ( _) => match self . layout . backend_repr {
137
- BackendRepr :: Scalar ( scalar) => {
138
- ( None , vec ! [ AbiParam :: new( scalar_to_clif_type( tcx, scalar) ) ] )
139
- }
153
+ PassMode :: Direct ( attrs) => match self . layout . backend_repr {
154
+ BackendRepr :: Scalar ( scalar) => (
155
+ None ,
156
+ vec ! [ apply_attrs_to_abi_param(
157
+ AbiParam :: new( scalar_to_clif_type( tcx, scalar) ) ,
158
+ attrs,
159
+ ) ] ,
160
+ ) ,
140
161
BackendRepr :: SimdVector { .. } => {
141
162
let vector_ty = crate :: intrinsics:: clif_vector_type ( tcx, self . layout ) ;
142
- ( None , vec ! [ AbiParam :: new( vector_ty) ] )
163
+ ( None , vec ! [ apply_attrs_to_abi_param ( AbiParam :: new( vector_ty) , attrs ) ] )
143
164
}
144
165
_ => unreachable ! ( "{:?}" , self . layout. backend_repr) ,
145
166
} ,
146
- PassMode :: Pair ( _ , _ ) => match self . layout . backend_repr {
167
+ PassMode :: Pair ( attrs_a , attrs_b ) => match self . layout . backend_repr {
147
168
BackendRepr :: ScalarPair ( a, b) => {
148
169
let a = scalar_to_clif_type ( tcx, a) ;
149
170
let b = scalar_to_clif_type ( tcx, b) ;
150
- ( None , vec ! [ AbiParam :: new( a) , AbiParam :: new( b) ] )
171
+ (
172
+ None ,
173
+ vec ! [
174
+ apply_attrs_to_abi_param( AbiParam :: new( a) , attrs_a) ,
175
+ apply_attrs_to_abi_param( AbiParam :: new( b) , attrs_b) ,
176
+ ] ,
177
+ )
151
178
}
152
179
_ => unreachable ! ( "{:?}" , self . layout. backend_repr) ,
153
180
} ,
154
- PassMode :: Cast { ref cast, .. } => {
155
- ( None , cast_target_to_abi_params ( cast) . into_iter ( ) . collect ( ) )
156
- }
157
- PassMode :: Indirect { attrs : _, meta_attrs : None , on_stack } => {
181
+ PassMode :: Cast { ref cast, .. } => (
182
+ None ,
183
+ cast_target_to_abi_params ( cast) . into_iter ( ) . map ( |( _, param) | param) . collect ( ) ,
184
+ ) ,
185
+ PassMode :: Indirect { attrs, meta_attrs : None , on_stack } => {
158
186
assert ! ( !on_stack) ;
159
- ( Some ( AbiParam :: special ( pointer_ty ( tcx) , ArgumentPurpose :: StructReturn ) ) , vec ! [ ] )
187
+ (
188
+ Some ( apply_attrs_to_abi_param (
189
+ AbiParam :: special ( pointer_ty ( tcx) , ArgumentPurpose :: StructReturn ) ,
190
+ attrs,
191
+ ) ) ,
192
+ vec ! [ ] ,
193
+ )
160
194
}
161
195
PassMode :: Indirect { attrs : _, meta_attrs : Some ( _) , on_stack : _ } => {
162
196
unreachable ! ( "unsized return value" )
@@ -172,12 +206,14 @@ pub(super) fn to_casted_value<'tcx>(
172
206
) -> SmallVec < [ Value ; 2 ] > {
173
207
let ( ptr, meta) = arg. force_stack ( fx) ;
174
208
assert ! ( meta. is_none( ) ) ;
175
- let mut offset = 0 ;
176
209
cast_target_to_abi_params ( cast)
177
210
. into_iter ( )
178
- . map ( |param| {
179
- let val = ptr. offset_i64 ( fx, offset) . load ( fx, param. value_type , MemFlags :: new ( ) ) ;
180
- offset += i64:: from ( param. value_type . bytes ( ) ) ;
211
+ . map ( |( offset, param) | {
212
+ let val = ptr. offset_i64 ( fx, offset. bytes ( ) as i64 ) . load (
213
+ fx,
214
+ param. value_type ,
215
+ MemFlags :: new ( ) ,
216
+ ) ;
181
217
val
182
218
} )
183
219
. collect ( )
@@ -190,7 +226,7 @@ pub(super) fn from_casted_value<'tcx>(
190
226
cast : & CastTarget ,
191
227
) -> CValue < ' tcx > {
192
228
let abi_params = cast_target_to_abi_params ( cast) ;
193
- let abi_param_size: u32 = abi_params. iter ( ) . map ( |param| param. value_type . bytes ( ) ) . sum ( ) ;
229
+ let abi_param_size: u32 = abi_params. iter ( ) . map ( |( _ , param) | param. value_type . bytes ( ) ) . sum ( ) ;
194
230
let layout_size = u32:: try_from ( layout. size . bytes ( ) ) . unwrap ( ) ;
195
231
let ptr = fx. create_stack_slot (
196
232
// Stack slot size may be bigger for example `[u8; 3]` which is packed into an `i32`.
@@ -199,16 +235,13 @@ pub(super) fn from_casted_value<'tcx>(
199
235
std:: cmp:: max ( abi_param_size, layout_size) ,
200
236
u32:: try_from ( layout. align . abi . bytes ( ) ) . unwrap ( ) ,
201
237
) ;
202
- let mut offset = 0 ;
203
238
let mut block_params_iter = block_params. iter ( ) . copied ( ) ;
204
- for param in abi_params {
205
- let val = ptr. offset_i64 ( fx, offset) . store (
239
+ for ( offset , _ ) in abi_params {
240
+ ptr. offset_i64 ( fx, offset. bytes ( ) as i64 ) . store (
206
241
fx,
207
242
block_params_iter. next ( ) . unwrap ( ) ,
208
243
MemFlags :: new ( ) ,
209
- ) ;
210
- offset += i64:: from ( param. value_type . bytes ( ) ) ;
211
- val
244
+ )
212
245
}
213
246
assert_eq ! ( block_params_iter. next( ) , None , "Leftover block param" ) ;
214
247
CValue :: by_ref ( ptr, layout)
0 commit comments