@@ -39,9 +39,13 @@ for non-monomorphized methods only. Other methods will
39
39
be generated once they are invoked with specific type parameters,
40
40
see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`.
41
41
*/
42
- pub fn trans_impl ( ccx : @CrateContext , path : path , name : ast:: ident ,
43
- methods : & [ @ast:: method ] , generics : & ast:: Generics ,
44
- self_ty : Option < ty:: t > , id : ast:: node_id ) {
42
+ pub fn trans_impl ( ccx : @CrateContext ,
43
+ path : path ,
44
+ name : ast:: ident ,
45
+ methods : & [ @ast:: method ] ,
46
+ generics : & ast:: Generics ,
47
+ self_ty : Option < ty:: t > ,
48
+ id : ast:: node_id ) {
45
49
let _icx = ccx. insn_ctxt ( "impl::trans_impl" ) ;
46
50
let tcx = ccx. tcx ;
47
51
@@ -718,7 +722,10 @@ pub fn trans_trait_callee_from_llval(bcx: block,
718
722
// Load the function from the vtable and cast it to the expected type.
719
723
debug ! ( "(translating trait callee) loading method" ) ;
720
724
let llcallee_ty = type_of_fn_from_ty ( ccx, callee_ty) ;
721
- let mptr = Load ( bcx, GEPi ( bcx, llvtable, [ 0 u, n_method] ) ) ;
725
+
726
+ // Plus one in order to skip past the type descriptor.
727
+ let mptr = Load ( bcx, GEPi ( bcx, llvtable, [ 0 u, n_method + 1 ] ) ) ;
728
+
722
729
let mptr = PointerCast ( bcx, mptr, T_ptr ( llcallee_ty) ) ;
723
730
724
731
return Callee {
@@ -756,25 +763,40 @@ pub fn vtable_id(ccx: @CrateContext,
756
763
}
757
764
}
758
765
766
+ /// Creates a returns a dynamic vtable for the given type and vtable origin.
767
+ /// This is used only for objects.
759
768
pub fn get_vtable ( ccx : @CrateContext ,
769
+ self_ty : ty:: t ,
760
770
origin : typeck:: vtable_origin )
761
- -> ValueRef {
771
+ -> ValueRef {
762
772
let hash_id = vtable_id ( ccx, & origin) ;
763
773
match ccx. vtables . find ( & hash_id) {
764
- Some ( & val) => val,
765
- None => match origin {
766
- typeck:: vtable_static( id, substs, sub_vtables) => {
767
- make_impl_vtable ( ccx, id, substs, sub_vtables)
774
+ Some ( & val) => val,
775
+ None => {
776
+ match origin {
777
+ typeck:: vtable_static( id, substs, sub_vtables) => {
778
+ make_impl_vtable ( ccx, id, self_ty, substs, sub_vtables)
779
+ }
780
+ _ => fail ! ( "get_vtable: expected a static origin" ) ,
781
+ }
768
782
}
769
- _ => fail ! ( "get_vtable: expected a static origin" )
770
- }
771
783
}
772
784
}
773
785
774
- pub fn make_vtable ( ccx : @CrateContext , ptrs : ~[ ValueRef ] ) -> ValueRef {
786
+ /// Helper function to declare and initialize the vtable.
787
+ pub fn make_vtable ( ccx : @CrateContext ,
788
+ tydesc : @mut tydesc_info ,
789
+ ptrs : & [ ValueRef ] )
790
+ -> ValueRef {
775
791
unsafe {
776
792
let _icx = ccx. insn_ctxt ( "impl::make_vtable" ) ;
777
- let tbl = C_struct ( ptrs) ;
793
+
794
+ let mut components = ~[ tydesc. tydesc ] ;
795
+ for ptrs. each |& ptr| {
796
+ components. push ( ptr)
797
+ }
798
+
799
+ let tbl = C_struct ( components) ;
778
800
let vtable = ccx. sess . str_of ( ( ccx. names ) ( "vtable" ) ) ;
779
801
let vt_gvar = do str:: as_c_str ( * vtable) |buf| {
780
802
llvm:: LLVMAddGlobal ( ccx. llmod , val_ty ( tbl) , buf)
@@ -786,11 +808,13 @@ pub fn make_vtable(ccx: @CrateContext, ptrs: ~[ValueRef]) -> ValueRef {
786
808
}
787
809
}
788
810
811
+ /// Generates a dynamic vtable for objects.
789
812
pub fn make_impl_vtable ( ccx : @CrateContext ,
790
813
impl_id : ast:: def_id ,
814
+ self_ty : ty:: t ,
791
815
substs : ~[ ty:: t ] ,
792
816
vtables : typeck:: vtable_res )
793
- -> ValueRef {
817
+ -> ValueRef {
794
818
let _icx = ccx. insn_ctxt ( "impl::make_impl_vtable" ) ;
795
819
let tcx = ccx. tcx ;
796
820
@@ -802,9 +826,13 @@ pub fn make_impl_vtable(ccx: @CrateContext,
802
826
803
827
let has_tps =
804
828
!ty:: lookup_item_type ( ccx. tcx , impl_id) . generics . type_param_defs . is_empty ( ) ;
805
- make_vtable ( ccx, ty:: trait_method_def_ids ( tcx, trt_id) . map ( |method_def_id| {
829
+
830
+ let trait_method_def_ids = ty:: trait_method_def_ids ( tcx, trt_id) ;
831
+ let methods = do trait_method_def_ids. map |method_def_id| {
806
832
let im = ty:: method ( tcx, * method_def_id) ;
807
- let fty = ty:: subst_tps ( tcx, substs, None ,
833
+ let fty = ty:: subst_tps ( tcx,
834
+ substs,
835
+ None ,
808
836
ty:: mk_bare_fn ( tcx, copy im. fty ) ) ;
809
837
if im. generics . has_type_params ( ) || ty:: type_has_self ( fty) {
810
838
debug ! ( "(making impl vtable) method has self or type params: %s" ,
@@ -830,7 +858,13 @@ pub fn make_impl_vtable(ccx: @CrateContext,
830
858
trans_external_path ( ccx, m_id, fty)
831
859
}
832
860
}
833
- } ) )
861
+ } ;
862
+
863
+ // Generate a type descriptor for the vtable.
864
+ let tydesc = get_tydesc ( ccx, self_ty) ;
865
+ glue:: lazily_emit_all_tydesc_glue ( ccx, tydesc) ;
866
+
867
+ make_vtable ( ccx, tydesc, methods)
834
868
}
835
869
836
870
pub fn trans_trait_cast ( bcx : block ,
@@ -852,40 +886,19 @@ pub fn trans_trait_cast(bcx: block,
852
886
let ccx = bcx. ccx ( ) ;
853
887
let v_ty = expr_ty ( bcx, val) ;
854
888
855
- match store {
856
- ty:: RegionTraitStore ( _) | ty:: BoxTraitStore => {
857
- let mut llboxdest = GEPi ( bcx, lldest, [ 0 u, abi:: trt_field_box] ) ;
858
- // Just store the pointer into the pair. (Region/borrowed
859
- // and boxed trait objects are represented as pairs, and
860
- // have no type descriptor field.)
861
- llboxdest = PointerCast ( bcx,
862
- llboxdest,
863
- T_ptr ( type_of ( bcx. ccx ( ) , v_ty) ) ) ;
864
- bcx = expr:: trans_into ( bcx, val, SaveIn ( llboxdest) ) ;
865
- }
866
- ty:: UniqTraitStore => {
867
- // Translate the uniquely-owned value in the
868
- // triple. (Unique trait objects are represented as
869
- // triples.)
870
- let mut llvaldest = GEPi ( bcx, lldest, [ 0 , abi:: trt_field_box] ) ;
871
- llvaldest = PointerCast ( bcx,
872
- llvaldest,
873
- T_ptr ( type_of ( bcx. ccx ( ) , v_ty) ) ) ;
874
- bcx = expr:: trans_into ( bcx, val, SaveIn ( llvaldest) ) ;
875
-
876
- // Get the type descriptor of the wrapped value and store
877
- // it in the triple as well.
878
- let tydesc = get_tydesc ( bcx. ccx ( ) , v_ty) ;
879
- glue:: lazily_emit_all_tydesc_glue ( bcx. ccx ( ) , tydesc) ;
880
- let lltydescdest = GEPi ( bcx, lldest, [ 0 , abi:: trt_field_tydesc] ) ;
881
- Store ( bcx, tydesc. tydesc , lltydescdest) ;
882
- }
883
- }
889
+ let mut llboxdest = GEPi ( bcx, lldest, [ 0 u, abi:: trt_field_box] ) ;
890
+ // Just store the pointer into the pair. (Region/borrowed
891
+ // and boxed trait objects are represented as pairs, and
892
+ // have no type descriptor field.)
893
+ llboxdest = PointerCast ( bcx,
894
+ llboxdest,
895
+ T_ptr ( type_of ( bcx. ccx ( ) , v_ty) ) ) ;
896
+ bcx = expr:: trans_into ( bcx, val, SaveIn ( llboxdest) ) ;
884
897
885
898
// Store the vtable into the pair or triple.
886
899
let orig = /*bad*/ copy ccx. maps . vtable_map . get ( & id) [ 0 ] ;
887
900
let orig = resolve_vtable_in_fn_ctxt ( bcx. fcx , orig) ;
888
- let vtable = get_vtable ( bcx. ccx ( ) , orig) ;
901
+ let vtable = get_vtable ( bcx. ccx ( ) , v_ty , orig) ;
889
902
Store ( bcx, vtable, PointerCast ( bcx,
890
903
GEPi ( bcx, lldest, [ 0 u, abi:: trt_field_vtable] ) ,
891
904
T_ptr ( val_ty ( vtable) ) ) ) ;
0 commit comments