@@ -235,27 +235,20 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_
235235 // not mutated by the current function, this is necessary to support unsized arguments.
236236 if let ArgKind :: Normal ( Some ( val) ) = arg_kind {
237237 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 ;
259252 }
260253 }
261254
@@ -291,6 +284,22 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_
291284 fx. bcx . ins ( ) . jump ( * fx. block_map . get ( START_BLOCK ) . unwrap ( ) , & [ ] ) ;
292285}
293286
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+
294303pub ( crate ) fn codegen_terminator_call < ' tcx > (
295304 fx : & mut FunctionCx < ' _ , ' _ , ' tcx > ,
296305 span : Span ,
@@ -361,28 +370,31 @@ pub(crate) fn codegen_terminator_call<'tcx>(
361370 // Unpack arguments tuple for closures
362371 let mut args = if fn_sig. abi == Abi :: RustCall {
363372 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 ] ) ;
366375
367- let tupled_arguments = match pack_arg. layout ( ) . ty . kind ( ) {
376+ let tupled_arguments = match pack_arg. value . layout ( ) . ty . kind ( ) {
368377 ty:: Tuple ( ref tupled_arguments) => tupled_arguments,
369378 _ => bug ! ( "argument to function with \" rust-call\" ABI is not a tuple" ) ,
370379 } ;
371380
372381 let mut args = Vec :: with_capacity ( 1 + tupled_arguments. len ( ) ) ;
373382 args. push ( self_arg) ;
374383 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+ } ) ;
376388 }
377389 args
378390 } 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 < _ > > ( )
380392 } ;
381393
382394 // Pass the caller location for `#[track_caller]`.
383395 if instance. map ( |inst| inst. def . requires_caller_location ( fx. tcx ) ) . unwrap_or ( false ) {
384396 let caller_location = fx. get_caller_location ( span) ;
385- args. push ( caller_location) ;
397+ args. push ( CallArgument { value : caller_location, is_owned : false } ) ;
386398 }
387399
388400 let args = args;
@@ -404,7 +416,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
404416 ) ;
405417 }
406418
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) ;
408420 let sig = clif_sig_from_fn_abi ( fx. tcx , fx. triple ( ) , & fn_abi) ;
409421 let sig = fx. bcx . import_signature ( sig) ;
410422
@@ -441,7 +453,9 @@ pub(crate) fn codegen_terminator_call<'tcx>(
441453 args. into_iter ( )
442454 . enumerate ( )
443455 . 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+ } )
445459 . flatten ( ) ,
446460 )
447461 . collect :: < Vec < Value > > ( ) ;
@@ -529,15 +543,15 @@ pub(crate) fn codegen_drop<'tcx>(
529543 TypeAndMut { ty, mutbl : crate :: rustc_hir:: Mutability :: Mut } ,
530544 ) ) ,
531545 ) ;
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 ) ;
533547
534548 let mut call_args: Vec < Value > = arg_value. into_iter ( ) . collect :: < Vec < _ > > ( ) ;
535549
536550 if drop_instance. def . requires_caller_location ( fx. tcx ) {
537551 // Pass the caller location for `#[track_caller]`.
538552 let caller_location = fx. get_caller_location ( span) ;
539553 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 ( ) ,
541555 ) ;
542556 }
543557
0 commit comments