@@ -23,7 +23,7 @@ use builder::Builder;
2323use common:: { self , CrateContext , Funclet } ;
2424use debuginfo:: { self , declare_local, VariableAccess , VariableKind , FunctionDebugContext } ;
2525use monomorphize:: Instance ;
26- use abi:: FnType ;
26+ use abi:: { ArgAttribute , FnType } ;
2727use type_of;
2828
2929use syntax_pos:: { DUMMY_SP , NO_EXPANSION , BytePos , Span } ;
@@ -378,6 +378,10 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
378378 None
379379 } ;
380380
381+ let deref_op = unsafe {
382+ [ llvm:: LLVMRustDIBuilderCreateOpDeref ( ) ]
383+ } ;
384+
381385 mir. args_iter ( ) . enumerate ( ) . map ( |( arg_index, local) | {
382386 let arg_decl = & mir. local_decls [ local] ;
383387 let arg_ty = mircx. monomorphize ( & arg_decl. ty ) ;
@@ -432,10 +436,9 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
432436
433437 let arg = & mircx. fn_ty . args [ idx] ;
434438 idx += 1 ;
435- let llval = if arg. is_indirect ( ) && bcx . sess ( ) . opts . debuginfo != FullDebugInfo {
439+ let llval = if arg. is_indirect ( ) {
436440 // Don't copy an indirect argument to an alloca, the caller
437- // already put it in a temporary alloca and gave it up, unless
438- // we emit extra-debug-info, which requires local allocas :(.
441+ // already put it in a temporary alloca and gave it up
439442 // FIXME: lifetimes
440443 if arg. pad . is_some ( ) {
441444 llarg_idx += 1 ;
@@ -444,8 +447,7 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
444447 llarg_idx += 1 ;
445448 llarg
446449 } else if !lvalue_locals. contains ( local. index ( ) ) &&
447- !arg. is_indirect ( ) && arg. cast . is_none ( ) &&
448- arg_scope. is_none ( ) {
450+ arg. cast . is_none ( ) && arg_scope. is_none ( ) {
449451 if arg. is_ignore ( ) {
450452 return LocalRef :: new_operand ( bcx. ccx , arg_ty) ;
451453 }
@@ -510,13 +512,26 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
510512 arg_scope. map ( |scope| {
511513 // Is this a regular argument?
512514 if arg_index > 0 || mir. upvar_decls . is_empty ( ) {
515+ // The Rust ABI passes indirect variables using a pointer and a manual copy, so we
516+ // need to insert a deref here, but the C ABI uses a pointer and a copy using the
517+ // byval attribute, for which LLVM does the deref itself, so we must not add it.
518+ let variable_access = if arg. is_indirect ( ) &&
519+ !arg. attrs . contains ( ArgAttribute :: ByVal ) {
520+ VariableAccess :: IndirectVariable {
521+ alloca : llval,
522+ address_operations : & deref_op,
523+ }
524+ } else {
525+ VariableAccess :: DirectVariable { alloca : llval }
526+ } ;
527+
513528 declare_local (
514529 bcx,
515530 & mircx. debug_context ,
516531 arg_decl. name . unwrap_or ( keywords:: Invalid . name ( ) ) ,
517532 arg_ty,
518533 scope,
519- VariableAccess :: DirectVariable { alloca : llval } ,
534+ variable_access ,
520535 VariableKind :: ArgumentVariable ( arg_index + 1 ) ,
521536 DUMMY_SP
522537 ) ;
0 commit comments