@@ -235,27 +235,20 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_
235
235
// not mutated by the current function, this is necessary to support unsized arguments.
236
236
if let ArgKind :: Normal ( Some ( val) ) = arg_kind {
237
237
if let Some ( ( addr, meta) ) = val. try_to_ptr ( ) {
238
- let local_decl = & fx. mir . local_decls [ local] ;
239
- // v this ! is important
240
- let internally_mutable = !val
241
- . layout ( )
242
- . ty
243
- . is_freeze ( fx. tcx . at ( local_decl. source_info . span ) , ParamEnv :: reveal_all ( ) ) ;
244
- if local_decl. mutability == mir:: Mutability :: Not && !internally_mutable {
245
- // We wont mutate this argument, so it is fine to borrow the backing storage
246
- // of this argument, to prevent a copy.
247
-
248
- let place = if let Some ( meta) = meta {
249
- CPlace :: for_ptr_with_extra ( addr, meta, val. layout ( ) )
250
- } else {
251
- CPlace :: for_ptr ( addr, val. layout ( ) )
252
- } ;
253
-
254
- self :: comments:: add_local_place_comments ( fx, place, local) ;
255
-
256
- assert_eq ! ( fx. local_map. push( place) , local) ;
257
- continue ;
258
- }
238
+ // Ownership of the value at the backing storage for an argument is passed to the
239
+ // callee per the ABI, so it is fine to borrow the backing storage of this argument
240
+ // to prevent a copy.
241
+
242
+ let place = if let Some ( meta) = meta {
243
+ CPlace :: for_ptr_with_extra ( addr, meta, val. layout ( ) )
244
+ } else {
245
+ CPlace :: for_ptr ( addr, val. layout ( ) )
246
+ } ;
247
+
248
+ self :: comments:: add_local_place_comments ( fx, place, local) ;
249
+
250
+ assert_eq ! ( fx. local_map. push( place) , local) ;
251
+ continue ;
259
252
}
260
253
}
261
254
@@ -291,6 +284,22 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_
291
284
fx. bcx . ins ( ) . jump ( * fx. block_map . get ( START_BLOCK ) . unwrap ( ) , & [ ] ) ;
292
285
}
293
286
287
+ struct CallArgument < ' tcx > {
288
+ value : CValue < ' tcx > ,
289
+ is_owned : bool ,
290
+ }
291
+
292
+ // FIXME avoid intermediate `CValue` before calling `adjust_arg_for_abi`
293
+ fn codegen_call_argument_operand < ' tcx > (
294
+ fx : & mut FunctionCx < ' _ , ' _ , ' tcx > ,
295
+ operand : & Operand < ' tcx > ,
296
+ ) -> CallArgument < ' tcx > {
297
+ CallArgument {
298
+ value : codegen_operand ( fx, operand) ,
299
+ is_owned : matches ! ( operand, Operand :: Move ( _) ) ,
300
+ }
301
+ }
302
+
294
303
pub ( crate ) fn codegen_terminator_call < ' tcx > (
295
304
fx : & mut FunctionCx < ' _ , ' _ , ' tcx > ,
296
305
span : Span ,
@@ -361,28 +370,31 @@ pub(crate) fn codegen_terminator_call<'tcx>(
361
370
// Unpack arguments tuple for closures
362
371
let mut args = if fn_sig. abi == Abi :: RustCall {
363
372
assert_eq ! ( args. len( ) , 2 , "rust-call abi requires two arguments" ) ;
364
- let self_arg = codegen_operand ( fx, & args[ 0 ] ) ;
365
- let pack_arg = codegen_operand ( fx, & args[ 1 ] ) ;
373
+ let self_arg = codegen_call_argument_operand ( fx, & args[ 0 ] ) ;
374
+ let pack_arg = codegen_call_argument_operand ( fx, & args[ 1 ] ) ;
366
375
367
- let tupled_arguments = match pack_arg. layout ( ) . ty . kind ( ) {
376
+ let tupled_arguments = match pack_arg. value . layout ( ) . ty . kind ( ) {
368
377
ty:: Tuple ( ref tupled_arguments) => tupled_arguments,
369
378
_ => bug ! ( "argument to function with \" rust-call\" ABI is not a tuple" ) ,
370
379
} ;
371
380
372
381
let mut args = Vec :: with_capacity ( 1 + tupled_arguments. len ( ) ) ;
373
382
args. push ( self_arg) ;
374
383
for i in 0 ..tupled_arguments. len ( ) {
375
- args. push ( pack_arg. value_field ( fx, mir:: Field :: new ( i) ) ) ;
384
+ args. push ( CallArgument {
385
+ value : pack_arg. value . value_field ( fx, mir:: Field :: new ( i) ) ,
386
+ is_owned : pack_arg. is_owned ,
387
+ } ) ;
376
388
}
377
389
args
378
390
} else {
379
- args. iter ( ) . map ( |arg| codegen_operand ( fx, arg) ) . collect :: < Vec < _ > > ( )
391
+ args. iter ( ) . map ( |arg| codegen_call_argument_operand ( fx, arg) ) . collect :: < Vec < _ > > ( )
380
392
} ;
381
393
382
394
// Pass the caller location for `#[track_caller]`.
383
395
if instance. map ( |inst| inst. def . requires_caller_location ( fx. tcx ) ) . unwrap_or ( false ) {
384
396
let caller_location = fx. get_caller_location ( span) ;
385
- args. push ( caller_location) ;
397
+ args. push ( CallArgument { value : caller_location, is_owned : false } ) ;
386
398
}
387
399
388
400
let args = args;
@@ -404,7 +416,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
404
416
) ;
405
417
}
406
418
407
- let ( ptr, method) = crate :: vtable:: get_ptr_and_method_ref ( fx, args[ 0 ] , idx) ;
419
+ let ( ptr, method) = crate :: vtable:: get_ptr_and_method_ref ( fx, args[ 0 ] . value , idx) ;
408
420
let sig = clif_sig_from_fn_abi ( fx. tcx , fx. triple ( ) , & fn_abi) ;
409
421
let sig = fx. bcx . import_signature ( sig) ;
410
422
@@ -441,7 +453,9 @@ pub(crate) fn codegen_terminator_call<'tcx>(
441
453
args. into_iter ( )
442
454
. enumerate ( )
443
455
. skip ( if first_arg_override. is_some ( ) { 1 } else { 0 } )
444
- . map ( |( i, arg) | adjust_arg_for_abi ( fx, arg, & fn_abi. args [ i] ) . into_iter ( ) )
456
+ . map ( |( i, arg) | {
457
+ adjust_arg_for_abi ( fx, arg. value , & fn_abi. args [ i] , arg. is_owned ) . into_iter ( )
458
+ } )
445
459
. flatten ( ) ,
446
460
)
447
461
. collect :: < Vec < Value > > ( ) ;
@@ -529,15 +543,15 @@ pub(crate) fn codegen_drop<'tcx>(
529
543
TypeAndMut { ty, mutbl : crate :: rustc_hir:: Mutability :: Mut } ,
530
544
) ) ,
531
545
) ;
532
- let arg_value = adjust_arg_for_abi ( fx, arg_value, & fn_abi. args [ 0 ] ) ;
546
+ let arg_value = adjust_arg_for_abi ( fx, arg_value, & fn_abi. args [ 0 ] , true ) ;
533
547
534
548
let mut call_args: Vec < Value > = arg_value. into_iter ( ) . collect :: < Vec < _ > > ( ) ;
535
549
536
550
if drop_instance. def . requires_caller_location ( fx. tcx ) {
537
551
// Pass the caller location for `#[track_caller]`.
538
552
let caller_location = fx. get_caller_location ( span) ;
539
553
call_args. extend (
540
- adjust_arg_for_abi ( fx, caller_location, & fn_abi. args [ 1 ] ) . into_iter ( ) ,
554
+ adjust_arg_for_abi ( fx, caller_location, & fn_abi. args [ 1 ] , false ) . into_iter ( ) ,
541
555
) ;
542
556
}
543
557
0 commit comments