@@ -6464,6 +6464,44 @@ fn trans_fn(cx: @local_ctxt, sp: &span, f: &ast::_fn, llfndecl: ValueRef,
6464
6464
log_fn_time ( cx. ccx , str:: connect_ivec ( cx. path , "::" ) , start, end) ;
6465
6465
}
6466
6466
6467
+ // Update a self-stack structure ([[wrapper_self_pair], self_pair*]) to
6468
+ // [[backwarding_vtbl*, inner_obj_body*], outer_obj*].
6469
+ //
6470
+ // We do this when we're receiving the outer object in a forwarding function
6471
+ // via the llenv argument, and we want the forwarding function to call a
6472
+ // method on a "self" that's inner-obj-shaped, but we also want to hold onto
6473
+ // the outer obj for potential use later by backwarding functions.
6474
+ fn populate_self_stack ( bcx : @block_ctxt ,
6475
+ self_stack : ValueRef , outer_obj : ValueRef ,
6476
+ backwarding_vtbl : ValueRef , inner_obj_body : ValueRef )
6477
+ -> ValueRef {
6478
+
6479
+ // Drop the outer obj into the second slot.
6480
+ let self_pair_ptr = bcx. build . GEP ( self_stack,
6481
+ ~[ C_int ( 0 ) ,
6482
+ C_int ( 1 ) ] ) ;
6483
+ bcx. build . Store ( outer_obj, self_pair_ptr) ;
6484
+
6485
+ // Drop in the backwarding vtbl.
6486
+ let wrapper_pair = bcx. build . GEP ( self_stack,
6487
+ ~[ C_int ( 0 ) ,
6488
+ C_int ( 0 ) ] ) ;
6489
+ let wrapper_vtbl_ptr = bcx. build . GEP ( wrapper_pair,
6490
+ ~[ C_int ( 0 ) ,
6491
+ C_int ( 0 ) ] ) ;
6492
+ let backwarding_vtbl_cast =
6493
+ bcx. build . PointerCast ( backwarding_vtbl, T_ptr ( T_empty_struct ( ) ) ) ;
6494
+ bcx. build . Store ( backwarding_vtbl_cast, wrapper_vtbl_ptr) ;
6495
+
6496
+ // Drop in the inner obj body.
6497
+ let wrapper_body_ptr = bcx. build . GEP ( wrapper_pair,
6498
+ ~[ C_int ( 0 ) ,
6499
+ C_int ( 1 ) ] ) ;
6500
+ bcx. build . Store ( inner_obj_body, wrapper_body_ptr) ;
6501
+
6502
+ ret self_stack;
6503
+ }
6504
+
6467
6505
// process_bkwding_mthd: Create the backwarding function that appears in a
6468
6506
// backwarding vtable slot.
6469
6507
//
@@ -6505,8 +6543,24 @@ fn process_bkwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
6505
6543
let lltop = bcx. llbb ;
6506
6544
6507
6545
// The self-object will arrive in the backwarding function via the llenv
6508
- // argument.
6509
- let llself_obj_ptr = fcx. llenv ;
6546
+ // argument, but we need to jump past the first item in the self-stack to
6547
+ // get to the one we really want.
6548
+
6549
+ // Cast to self-stack's type.
6550
+ let llenv = bcx. build . PointerCast (
6551
+ fcx. llenv ,
6552
+ T_ptr ( T_struct ( ~[ cx. ccx . rust_object_type ,
6553
+ T_ptr ( cx. ccx . rust_object_type ) ] ) ) ) ;
6554
+
6555
+ let llself_obj_ptr = bcx. build . GEP ( llenv,
6556
+ ~[ C_int ( 0 ) ,
6557
+ C_int ( 1 ) ] ) ;
6558
+ llself_obj_ptr = bcx. build . Load ( llself_obj_ptr) ;
6559
+
6560
+ // Cast it back to the type of fcx.llenv, tho, so LLVM won't complain.
6561
+ // TODO: could we just cast this to T_ptr(cx.ccx.rust_object_type)?
6562
+ llself_obj_ptr = bcx. build . PointerCast ( llself_obj_ptr,
6563
+ val_ty ( fcx. llenv ) ) ;
6510
6564
6511
6565
// The 'llretptr' that will arrive in the backwarding function we're
6512
6566
// creating also needs to be the correct type. Cast it to the method's
@@ -6521,7 +6575,7 @@ fn process_bkwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
6521
6575
// at it.
6522
6576
let llouter_obj_vtbl =
6523
6577
bcx. build . GEP ( llself_obj_ptr,
6524
- ~[ C_int ( 0 ) , C_int ( 1 ) ] ) ;
6578
+ ~[ C_int ( 0 ) , C_int ( abi :: obj_field_vtbl ) ] ) ;
6525
6579
llouter_obj_vtbl = bcx. build . Load ( llouter_obj_vtbl) ;
6526
6580
6527
6581
// Get the index of the method we want.
@@ -6627,20 +6681,6 @@ fn process_fwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
6627
6681
// argument.
6628
6682
let llself_obj_ptr = fcx. llenv ;
6629
6683
6630
- // Grab the vtable out of the self-object and replace it with the
6631
- // backwarding vtable. FIXME (issue #702): Not quite ready to turn this
6632
- // behavior on yet.
6633
-
6634
- // let llself_obj_vtbl =
6635
- // bcx.build.GEP(llself_obj_ptr, ~[C_int(0),
6636
- // C_int(abi::obj_field_vtbl)]);
6637
- // let llbv = bcx.build.PointerCast(backwarding_vtbl,
6638
- // T_ptr(T_empty_struct()));
6639
- // bcx.build.Store(llbv, llself_obj_vtbl);
6640
-
6641
- // NB: llself_obj is now a freakish combination of outer object body
6642
- // and backwarding (inner-object) vtable.
6643
-
6644
6684
// The 'llretptr' that will arrive in the forwarding function we're
6645
6685
// creating also needs to be the correct type. Cast it to the method's
6646
6686
// return type, if necessary.
@@ -6710,6 +6750,11 @@ fn process_fwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
6710
6750
~[ C_int ( 0 ) , C_int ( abi:: obj_field_vtbl) ] ) ;
6711
6751
llinner_obj_vtbl = bcx. build . Load ( llinner_obj_vtbl) ;
6712
6752
6753
+ let llinner_obj_body =
6754
+ bcx. build . GEP ( llinner_obj. val ,
6755
+ ~[ C_int ( 0 ) , C_int ( abi:: obj_field_box) ] ) ;
6756
+ llinner_obj_body = bcx. build . Load ( llinner_obj_body) ;
6757
+
6713
6758
// Get the index of the method we want.
6714
6759
let ix: uint = 0 u;
6715
6760
alt ty:: struct ( bcx_tcx ( bcx) , inner_obj_ty) {
@@ -6741,10 +6786,23 @@ fn process_fwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
6741
6786
bcx. build . PointerCast ( llorig_mthd, T_ptr ( T_ptr ( llorig_mthd_ty) ) ) ;
6742
6787
llorig_mthd = bcx. build . Load ( llorig_mthd) ;
6743
6788
6789
+ // Set up the self-stack.
6790
+ let self_stack = alloca ( bcx, T_struct ( ~[ cx. ccx . rust_object_type ,
6791
+ T_ptr ( cx. ccx . rust_object_type ) ] ) ) ;
6792
+ self_stack = populate_self_stack ( bcx,
6793
+ self_stack,
6794
+ llself_obj_ptr,
6795
+ backwarding_vtbl,
6796
+ llinner_obj_body) ;
6797
+
6798
+ // Cast self_stack back to the type of fcx.llenv to make LLVM happy.
6799
+ // TODO: could we just cast this to T_ptr(cx.ccx.rust_object_type)?
6800
+ self_stack = bcx. build . PointerCast ( self_stack,
6801
+ val_ty ( fcx. llenv ) ) ;
6802
+
6744
6803
// Set up the three implicit arguments to the original method we'll need
6745
6804
// to call.
6746
- let self_arg = llself_obj_ptr;
6747
- let llorig_mthd_args: ValueRef [ ] = ~[ llretptr, fcx. lltaskptr , self_arg] ;
6805
+ let llorig_mthd_args: ValueRef [ ] = ~[ llretptr, fcx. lltaskptr , self_stack] ;
6748
6806
6749
6807
// Copy the explicit arguments that are being passed into the forwarding
6750
6808
// function (they're in fcx.llargs) to llorig_mthd_args.
@@ -6759,7 +6817,7 @@ fn process_fwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
6759
6817
a += 1 u;
6760
6818
}
6761
6819
6762
- // And, finally, call the original method.
6820
+ // And, finally, call the original (inner) method.
6763
6821
bcx. build . FastCall ( llorig_mthd, llorig_mthd_args) ;
6764
6822
6765
6823
bcx. build . RetVoid ( ) ;
0 commit comments