11//! Argument passing
22
3- use cranelift_codegen:: ir:: { ArgumentExtension , ArgumentPurpose } ;
3+ use cranelift_codegen:: ir:: ArgumentPurpose ;
44use rustc_abi:: { Reg , RegKind } ;
55use rustc_target:: callconv:: {
66 ArgAbi , ArgAttributes , ArgExtension as RustcArgExtension , CastTarget , PassMode ,
@@ -32,16 +32,26 @@ fn reg_to_abi_param(reg: Reg) -> AbiParam {
3232 AbiParam :: new ( clif_ty)
3333}
3434
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 {
3636 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 ( ) ,
4040 }
41- param
4241}
4342
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+
4555 let ( rest_count, rem_bytes) = if cast. rest . unit . size . bytes ( ) == 0 {
4656 ( 0 , 0 )
4757 } else {
@@ -56,33 +66,40 @@ fn cast_target_to_abi_params(cast: &CastTarget) -> SmallVec<[AbiParam; 2]> {
5666 // different types in Cranelift IR. Instead a single array of primitive types is used.
5767
5868 // Create list of fields in the main structure
59- let mut args = cast
69+ let args = cast
6070 . prefix
6171 . iter ( )
6272 . flatten ( )
6373 . 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+ }
6683
6784 // Append final integer
6885 if rem_bytes != 0 {
6986 // Only integers can be really split further.
7087 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+ ) ) ;
7592 }
7693
77- args
94+ res
7895}
7996
8097impl < ' tcx > ArgAbiExt < ' tcx > for ArgAbi < ' tcx , Ty < ' tcx > > {
8198 fn get_abi_param ( & self , tcx : TyCtxt < ' tcx > ) -> SmallVec < [ AbiParam ; 2 ] > {
8299 match self . mode {
83100 PassMode :: Ignore => smallvec ! [ ] ,
84101 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 (
86103 AbiParam :: new( scalar_to_clif_type( tcx, scalar) ) ,
87104 attrs
88105 ) ] ,
@@ -97,34 +114,34 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
97114 let a = scalar_to_clif_type ( tcx, a) ;
98115 let b = scalar_to_clif_type ( tcx, b) ;
99116 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) ,
102119 ]
103120 }
104121 _ => unreachable ! ( "{:?}" , self . layout. backend_repr) ,
105122 } ,
106123 PassMode :: Cast { ref cast, pad_i32 } => {
107124 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 ( )
109126 }
110127 PassMode :: Indirect { attrs, meta_attrs : None , on_stack } => {
111128 if on_stack {
112129 // Abi requires aligning struct size to pointer size
113130 let size = self . layout . size . align_to ( tcx. data_layout . pointer_align . abi ) ;
114131 let size = u32:: try_from ( size. bytes ( ) ) . unwrap ( ) ;
115- smallvec ! [ apply_arg_attrs_to_abi_param (
132+ smallvec ! [ apply_attrs_to_abi_param (
116133 AbiParam :: special( pointer_ty( tcx) , ArgumentPurpose :: StructArgument ( size) , ) ,
117134 attrs
118135 ) ]
119136 } 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) ]
121138 }
122139 }
123140 PassMode :: Indirect { attrs, meta_attrs : Some ( meta_attrs) , on_stack } => {
124141 assert ! ( !on_stack) ;
125142 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) ,
128145 ]
129146 }
130147 }
@@ -133,30 +150,47 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
133150 fn get_abi_return ( & self , tcx : TyCtxt < ' tcx > ) -> ( Option < AbiParam > , Vec < AbiParam > ) {
134151 match self . mode {
135152 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+ ) ,
140161 BackendRepr :: SimdVector { .. } => {
141162 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 ) ] )
143164 }
144165 _ => unreachable ! ( "{:?}" , self . layout. backend_repr) ,
145166 } ,
146- PassMode :: Pair ( _ , _ ) => match self . layout . backend_repr {
167+ PassMode :: Pair ( attrs_a , attrs_b ) => match self . layout . backend_repr {
147168 BackendRepr :: ScalarPair ( a, b) => {
148169 let a = scalar_to_clif_type ( tcx, a) ;
149170 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+ )
151178 }
152179 _ => unreachable ! ( "{:?}" , self . layout. backend_repr) ,
153180 } ,
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 } => {
158186 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+ )
160194 }
161195 PassMode :: Indirect { attrs : _, meta_attrs : Some ( _) , on_stack : _ } => {
162196 unreachable ! ( "unsized return value" )
@@ -172,12 +206,14 @@ pub(super) fn to_casted_value<'tcx>(
172206) -> SmallVec < [ Value ; 2 ] > {
173207 let ( ptr, meta) = arg. force_stack ( fx) ;
174208 assert ! ( meta. is_none( ) ) ;
175- let mut offset = 0 ;
176209 cast_target_to_abi_params ( cast)
177210 . 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+ ) ;
181217 val
182218 } )
183219 . collect ( )
@@ -190,7 +226,7 @@ pub(super) fn from_casted_value<'tcx>(
190226 cast : & CastTarget ,
191227) -> CValue < ' tcx > {
192228 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 ( ) ;
194230 let layout_size = u32:: try_from ( layout. size . bytes ( ) ) . unwrap ( ) ;
195231 let ptr = fx. create_stack_slot (
196232 // 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>(
199235 std:: cmp:: max ( abi_param_size, layout_size) ,
200236 u32:: try_from ( layout. align . abi . bytes ( ) ) . unwrap ( ) ,
201237 ) ;
202- let mut offset = 0 ;
203238 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 (
206241 fx,
207242 block_params_iter. next ( ) . unwrap ( ) ,
208243 MemFlags :: new ( ) ,
209- ) ;
210- offset += i64:: from ( param. value_type . bytes ( ) ) ;
211- val
244+ )
212245 }
213246 assert_eq ! ( block_params_iter. next( ) , None , "Leftover block param" ) ;
214247 CValue :: by_ref ( ptr, layout)
0 commit comments