@@ -129,11 +129,13 @@ use driver::session;
129
129
use lib:: llvm:: llvm;
130
130
use lib:: llvm:: { ModuleRef , ContextRef , ValueRef } ;
131
131
use lib:: llvm:: debuginfo:: * ;
132
+ use middle:: trans:: adt;
133
+ use middle:: trans:: base;
134
+ use middle:: trans:: build;
132
135
use middle:: trans:: common:: * ;
133
136
use middle:: trans:: machine;
134
137
use middle:: trans:: type_of;
135
138
use middle:: trans:: type_:: Type ;
136
- use middle:: trans:: adt;
137
139
use middle:: trans;
138
140
use middle:: ty;
139
141
use middle:: pat_util;
@@ -453,12 +455,29 @@ pub fn create_self_argument_metadata(bcx: @mut Block,
453
455
454
456
let address_operations = & [ unsafe { llvm:: LLVMDIBuilderCreateOpDeref ( Type :: i64 ( ) . to_ref ( ) ) } ] ;
455
457
458
+ // The self argument comes in one of two forms:
459
+ // (1) For `&self`, `~self`, and `@self` it is an alloca containing a pointer to the data. That
460
+ // is the `{&~@}self` pointer is contained by value in the alloca, and `type_of_self` will
461
+ // be `{&~@}Self`
462
+ // (2) For by-value `self`, `llptr` will not be an alloca, but a pointer to the self-value. That
463
+ // is by-value `self` is always implicitly passed by reference (sic!). So we have a couple
464
+ // of problems here:
465
+ // (a) There is no alloca to give to `llvm.dbg.declare` and
466
+ // (b) `type_of_self` is `Self`, but `llptr` is of type `*Self`
467
+ // In order to solve this problem, the else branch below creates a helper alloca which
468
+ // contains a copy of `llptr`. We then describe the `self` parameter by pointing
469
+ // `llvm.dbg.declare` to this helper alloca and tell it that the pointer there needs to be
470
+ // dereferenced once to get to the actual data (similar to non-immediate by-value args).
456
471
let variable_access = if unsafe { llvm:: LLVMIsAAllocaInst ( llptr) } != ptr:: null ( ) {
457
472
DirectVariable { alloca : llptr }
458
473
} else {
459
- // This is not stable and may break with future LLVM versions. llptr should really always
460
- // be an alloca. Anything else is not supported and just works by chance.
461
- IndirectVariable { alloca : llptr, address_operations : address_operations }
474
+ // Create a helper alloca that allows us to track the self-argument properly. The alloca
475
+ // contains a pointer to the self-value.
476
+ let ptr_type = ty:: mk_mut_ptr ( bcx. tcx ( ) , type_of_self) ;
477
+ let helper_alloca = base:: alloc_ty ( bcx, ptr_type, "__self" ) ;
478
+ build:: Store ( bcx, llptr, helper_alloca) ;
479
+
480
+ IndirectVariable { alloca : helper_alloca, address_operations : address_operations }
462
481
} ;
463
482
464
483
declare_local ( bcx,
0 commit comments