@@ -6534,6 +6534,7 @@ fn trans_fn(cx: @local_ctxt, sp: &span, f: &ast::_fn, llfndecl: ValueRef,
6534
6534
// helper function for create_vtbl.
6535
6535
fn process_fwding_mthd ( cx : @local_ctxt , sp : & span , m : @ty:: method ,
6536
6536
ty_params : & ast:: ty_param [ ] , with_obj_ty : ty:: t ,
6537
+ backwarding_vtbl : option:: t [ ValueRef ] ,
6537
6538
additional_field_tys : & ty:: t [ ] ) -> ValueRef {
6538
6539
6539
6540
@@ -6552,9 +6553,14 @@ fn process_fwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
6552
6553
let mcx: @local_ctxt = @{ path: cx. path + ~[ "method" , m. ident ] with * cx} ;
6553
6554
6554
6555
// Make up a name for the forwarding function.
6555
- let s: str =
6556
- mangle_internal_name_by_path_and_seq ( mcx. ccx , mcx. path ,
6557
- "forwarding_fn" ) ;
6556
+ let fn_name: str ;
6557
+ alt ( backwarding_vtbl) {
6558
+ none. { fn_name = "forwarding_fn" ; }
6559
+ some ( _) { fn_name = "backwarding_fn" ; }
6560
+ }
6561
+
6562
+ let s: str = mangle_internal_name_by_path_and_seq ( mcx. ccx , mcx. path ,
6563
+ fn_name) ;
6558
6564
6559
6565
// Get the forwarding function's type and declare it.
6560
6566
let llforwarding_fn_ty: TypeRef =
@@ -6574,6 +6580,21 @@ fn process_fwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
6574
6580
let llself_obj_ptr = alloca ( bcx, fcx. lcx . ccx . rust_object_type ) ;
6575
6581
bcx. build . Store ( fcx. llenv , llself_obj_ptr) ;
6576
6582
6583
+ // Do backwarding if necessary.
6584
+ alt ( backwarding_vtbl) {
6585
+ none. { /* fall through */ }
6586
+ some ( bv) {
6587
+ // Grab the vtable out of the self-object.
6588
+ let llself_obj_vtbl =
6589
+ bcx. build . GEP ( llself_obj_ptr, ~[ C_int ( 0 ) ,
6590
+ C_int ( abi:: obj_field_vtbl) ] ) ;
6591
+
6592
+ // And replace it with the backwarding vtbl.
6593
+ let llbv = bcx. build . PointerCast ( bv, T_ptr ( T_empty_struct ( ) ) ) ;
6594
+ bcx. build . Store ( llbv, llself_obj_vtbl) ;
6595
+ }
6596
+ }
6597
+
6577
6598
// Grab hold of the outer object so we can pass it into the inner object,
6578
6599
// in case that inner object needs to make any self-calls. (Such calls
6579
6600
// will need to dispatch back through the outer object.)
@@ -6733,22 +6754,21 @@ fn process_normal_mthd(cx: @local_ctxt, m: @ast::method, self_ty: ty::t,
6733
6754
ret llfn;
6734
6755
}
6735
6756
6757
+ // Used only inside create_vtbl and create_backwarding_vtbl to distinguish
6758
+ // different kinds of slots we'll have to create.
6759
+ tag vtbl_mthd {
6760
+ // Normal methods are complete AST nodes, but for forwarding methods,
6761
+ // the only information we'll have about them is their type.
6762
+ normal_mthd( @ast : : method) ;
6763
+ fwding_mthd ( @ty:: method) ;
6764
+ }
6765
+
6736
6766
// Create a vtable for an object being translated. Returns a pointer into
6737
6767
// read-only memory.
6738
6768
fn create_vtbl ( cx : @local_ctxt , sp : & span , self_ty : ty:: t , ob : & ast:: _obj ,
6739
6769
ty_params : & ast:: ty_param [ ] , with_obj_ty : option:: t [ ty:: t ] ,
6740
6770
additional_field_tys : & ty:: t [ ] ) -> ValueRef {
6741
6771
6742
- // Used only inside create_vtbl to distinguish different kinds of slots
6743
- // we'll have to create.
6744
- tag vtbl_mthd {
6745
-
6746
- // Normal methods are complete AST nodes, but for forwarding methods,
6747
- // the only information we'll have about them is their type.
6748
- normal_mthd( @ast : : method) ;
6749
- fwding_mthd ( @ty:: method) ;
6750
- }
6751
-
6752
6772
let dtor = C_null ( T_ptr ( T_i8 ( ) ) ) ;
6753
6773
alt ob. dtor {
6754
6774
some ( d) {
@@ -6760,6 +6780,7 @@ fn create_vtbl(cx: @local_ctxt, sp: &span, self_ty: ty::t, ob: &ast::_obj,
6760
6780
6761
6781
let llmethods: ValueRef [ ] = ~[ dtor] ;
6762
6782
let meths: vtbl_mthd [ ] = ~[ ] ;
6783
+ let backwarding_vtbl: option:: t [ ValueRef ] = none;
6763
6784
6764
6785
alt with_obj_ty {
6765
6786
none. {
@@ -6794,8 +6815,8 @@ fn create_vtbl(cx: @local_ctxt, sp: &span, self_ty: ty::t, ob: &ast::_obj,
6794
6815
}
6795
6816
_ {
6796
6817
// Shouldn't happen.
6797
- cx. ccx . sess . bug ( "create_vtbl(): trying to extend a " +
6798
- " non-object") ;
6818
+ cx. ccx . sess . bug ( "create_vtbl(): trying to extend a \
6819
+ non-object") ;
6799
6820
}
6800
6821
}
6801
6822
@@ -6805,7 +6826,6 @@ fn create_vtbl(cx: @local_ctxt, sp: &span, self_ty: ty::t, ob: &ast::_obj,
6805
6826
addtl_meths : ( @ast:: method ) [ ] ) ->
6806
6827
option:: t [ vtbl_mthd ] {
6807
6828
6808
-
6809
6829
alt m {
6810
6830
fwding_mthd( fm) {
6811
6831
// Since fm is a fwding_mthd, and we're checking to
@@ -6863,7 +6883,7 @@ fn create_vtbl(cx: @local_ctxt, sp: &span, self_ty: ty::t, ob: &ast::_obj,
6863
6883
meths) ;
6864
6884
6865
6885
// Now that we have our list of methods, we can process them in order.
6866
- for m: vtbl_mthd in meths {
6886
+ for m: vtbl_mthd in meths {
6867
6887
alt m {
6868
6888
normal_mthd( nm) {
6869
6889
llmethods += ~[ process_normal_mthd ( cx, nm, self_ty, ty_params) ] ;
@@ -6877,13 +6897,14 @@ fn create_vtbl(cx: @local_ctxt, sp: &span, self_ty: ty::t, ob: &ast::_obj,
6877
6897
// This shouldn't happen; if we're trying to process a
6878
6898
// forwarding method, then we should always have a
6879
6899
// with_obj_ty.
6880
- cx. ccx . sess . bug ( "create_vtbl(): trying to create " +
6881
- " forwarding method without a type " +
6882
- " of object to forward to") ;
6900
+ cx. ccx . sess . bug ( "create_vtbl(): trying to create \
6901
+ forwarding method without a type \
6902
+ of object to forward to") ;
6883
6903
}
6884
6904
some ( t) {
6885
6905
llmethods +=
6886
6906
~[ process_fwding_mthd ( cx, sp, fm, ty_params, t,
6907
+ backwarding_vtbl,
6887
6908
additional_field_tys) ] ;
6888
6909
}
6889
6910
}
@@ -6914,6 +6935,65 @@ fn trans_dtor(cx: @local_ctxt, self_ty: ty::t, ty_params: &ast::ty_param[],
6914
6935
ret llfn;
6915
6936
}
6916
6937
6938
+ fn create_backwarding_vtbl ( cx : @local_ctxt , sp : & span , with_obj_ty : ty:: t ,
6939
+ outer_obj_ty : ty:: t ) -> ValueRef {
6940
+
6941
+ // This vtbl needs to have slots for all of the methods on an inner
6942
+ // object, and it needs to forward them to the corresponding slots on the
6943
+ // outer object. All we know about either one are their types.
6944
+
6945
+ let dtor = C_null ( T_ptr ( T_i8 ( ) ) ) ;
6946
+ let llmethods: ValueRef [ ] = ~[ dtor] ;
6947
+ let meths: vtbl_mthd [ ] = ~[ ] ;
6948
+
6949
+ // Gather up methods on the inner object.
6950
+ alt ty:: struct ( cx. ccx . tcx , with_obj_ty) {
6951
+ ty:: ty_obj ( with_obj_methods) {
6952
+ for m: ty:: method in with_obj_methods {
6953
+ meths += ~[ fwding_mthd ( @m) ] ;
6954
+ }
6955
+ }
6956
+ _ {
6957
+ // Shouldn't happen.
6958
+ cx. ccx . sess . bug ( "create_backwarding_vtbl(): trying to extend a \
6959
+ non-object") ;
6960
+ }
6961
+ }
6962
+
6963
+ // Methods should have already been sorted, so no need to do so again.
6964
+
6965
+ for m: vtbl_mthd in meths {
6966
+ alt m {
6967
+ normal_mthd( nm) {
6968
+ cx. ccx . sess . bug ( "backwarding vtables shouldn't contain \
6969
+ normal methods") ;
6970
+ }
6971
+ fwding_mthd ( fm) {
6972
+ // We pass outer_obj_ty to process_fwding_mthd() because it's
6973
+ // the one being forwarded to.
6974
+ llmethods += ~[ process_fwding_mthd (
6975
+ cx, sp, fm, ~[ ] , outer_obj_ty,
6976
+ none,
6977
+ ~[ ] ) ] ;
6978
+ }
6979
+ }
6980
+ }
6981
+
6982
+ let vtbl = C_struct ( llmethods) ;
6983
+ let vtbl_name =
6984
+ mangle_internal_name_by_path ( cx. ccx ,
6985
+ cx. path + ~[ "backwarding_vtbl" ] ) ;
6986
+ let gvar =
6987
+ llvm:: LLVMAddGlobal ( cx. ccx . llmod , val_ty ( vtbl) , str:: buf ( vtbl_name) ) ;
6988
+ llvm:: LLVMSetInitializer ( gvar, vtbl) ;
6989
+ llvm:: LLVMSetGlobalConstant ( gvar, True ) ;
6990
+ llvm:: LLVMSetLinkage ( gvar,
6991
+ lib:: llvm:: LLVMInternalLinkage as llvm:: Linkage ) ;
6992
+
6993
+ ret gvar;
6994
+
6995
+ }
6996
+
6917
6997
// trans_obj: creates an LLVM function that is the object constructor for the
6918
6998
// object being translated.
6919
6999
fn trans_obj ( cx : @local_ctxt , sp : & span , ob : & ast:: _obj ,
0 commit comments