@@ -129,11 +129,13 @@ use driver::session;
129129use lib:: llvm:: llvm;
130130use lib:: llvm:: { ModuleRef , ContextRef , ValueRef } ;
131131use lib:: llvm:: debuginfo:: * ;
132+ use middle:: trans:: adt;
133+ use middle:: trans:: base;
134+ use middle:: trans:: build;
132135use middle:: trans:: common:: * ;
133136use middle:: trans:: machine;
134137use middle:: trans:: type_of;
135138use middle:: trans:: type_:: Type ;
136- use middle:: trans:: adt;
137139use middle:: trans;
138140use middle:: ty;
139141use middle:: pat_util;
@@ -453,12 +455,29 @@ pub fn create_self_argument_metadata(bcx: @mut Block,
453455
454456 let address_operations = & [ unsafe { llvm:: LLVMDIBuilderCreateOpDeref ( Type :: i64 ( ) . to_ref ( ) ) } ] ;
455457
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).
456471 let variable_access = if unsafe { llvm:: LLVMIsAAllocaInst ( llptr) } != ptr:: null ( ) {
457472 DirectVariable { alloca : llptr }
458473 } 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 }
462481 } ;
463482
464483 declare_local ( bcx,
0 commit comments