@@ -23,7 +23,7 @@ use builder::Builder;
23
23
use common:: { self , CrateContext , Funclet } ;
24
24
use debuginfo:: { self , declare_local, VariableAccess , VariableKind , FunctionDebugContext } ;
25
25
use monomorphize:: Instance ;
26
- use abi:: FnType ;
26
+ use abi:: { ArgAttribute , FnType } ;
27
27
use type_of;
28
28
29
29
use syntax_pos:: { DUMMY_SP , NO_EXPANSION , BytePos , Span } ;
@@ -378,6 +378,10 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
378
378
None
379
379
} ;
380
380
381
+ let deref_op = unsafe {
382
+ [ llvm:: LLVMRustDIBuilderCreateOpDeref ( ) ]
383
+ } ;
384
+
381
385
mir. args_iter ( ) . enumerate ( ) . map ( |( arg_index, local) | {
382
386
let arg_decl = & mir. local_decls [ local] ;
383
387
let arg_ty = mircx. monomorphize ( & arg_decl. ty ) ;
@@ -432,10 +436,9 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
432
436
433
437
let arg = & mircx. fn_ty . args [ idx] ;
434
438
idx += 1 ;
435
- let llval = if arg. is_indirect ( ) && bcx . sess ( ) . opts . debuginfo != FullDebugInfo {
439
+ let llval = if arg. is_indirect ( ) {
436
440
// 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
439
442
// FIXME: lifetimes
440
443
if arg. pad . is_some ( ) {
441
444
llarg_idx += 1 ;
@@ -444,8 +447,7 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
444
447
llarg_idx += 1 ;
445
448
llarg
446
449
} 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 ( ) {
449
451
if arg. is_ignore ( ) {
450
452
return LocalRef :: new_operand ( bcx. ccx , arg_ty) ;
451
453
}
@@ -510,13 +512,26 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
510
512
arg_scope. map ( |scope| {
511
513
// Is this a regular argument?
512
514
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
+
513
528
declare_local (
514
529
bcx,
515
530
& mircx. debug_context ,
516
531
arg_decl. name . unwrap_or ( keywords:: Invalid . name ( ) ) ,
517
532
arg_ty,
518
533
scope,
519
- VariableAccess :: DirectVariable { alloca : llval } ,
534
+ variable_access ,
520
535
VariableKind :: ArgumentVariable ( arg_index + 1 ) ,
521
536
DUMMY_SP
522
537
) ;
0 commit comments