@@ -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,26 +763,41 @@ 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
// XXX: Bad copy.
763
773
let hash_id = vtable_id ( ccx, copy origin) ;
764
774
match ccx. vtables . find ( & hash_id) {
765
- Some ( & val) => val,
766
- None => match origin {
767
- typeck:: vtable_static( id, substs, sub_vtables) => {
768
- make_impl_vtable ( ccx, id, substs, sub_vtables)
775
+ Some ( & val) => val,
776
+ None => {
777
+ match origin {
778
+ typeck:: vtable_static( id, substs, sub_vtables) => {
779
+ make_impl_vtable ( ccx, id, self_ty, substs, sub_vtables)
780
+ }
781
+ _ => fail ! ( "get_vtable: expected a static origin" ) ,
782
+ }
769
783
}
770
- _ => fail ! ( "get_vtable: expected a static origin" )
771
- }
772
784
}
773
785
}
774
786
775
- pub fn make_vtable ( ccx : @CrateContext , ptrs : ~[ ValueRef ] ) -> ValueRef {
787
+ /// Helper function to declare and initialize the vtable.
788
+ pub fn make_vtable ( ccx : @CrateContext ,
789
+ tydesc : @mut tydesc_info ,
790
+ ptrs : & [ ValueRef ] )
791
+ -> ValueRef {
776
792
unsafe {
777
793
let _icx = ccx. insn_ctxt ( "impl::make_vtable" ) ;
778
- let tbl = C_struct ( ptrs) ;
794
+
795
+ let mut components = ~[ tydesc. tydesc ] ;
796
+ for ptrs. each |& ptr| {
797
+ components. push ( ptr)
798
+ }
799
+
800
+ let tbl = C_struct ( components) ;
779
801
let vtable = ccx. sess . str_of ( ( ccx. names ) ( "vtable" ) ) ;
780
802
let vt_gvar = do str:: as_c_str ( * vtable) |buf| {
781
803
llvm:: LLVMAddGlobal ( ccx. llmod , val_ty ( tbl) , buf)
@@ -787,11 +809,13 @@ pub fn make_vtable(ccx: @CrateContext, ptrs: ~[ValueRef]) -> ValueRef {
787
809
}
788
810
}
789
811
812
+ /// Generates a dynamic vtable for objects.
790
813
pub fn make_impl_vtable ( ccx : @CrateContext ,
791
814
impl_id : ast:: def_id ,
815
+ self_ty : ty:: t ,
792
816
substs : ~[ ty:: t ] ,
793
817
vtables : typeck:: vtable_res )
794
- -> ValueRef {
818
+ -> ValueRef {
795
819
let _icx = ccx. insn_ctxt ( "impl::make_impl_vtable" ) ;
796
820
let tcx = ccx. tcx ;
797
821
@@ -800,9 +824,13 @@ pub fn make_impl_vtable(ccx: @CrateContext,
800
824
801
825
let has_tps =
802
826
!ty:: lookup_item_type ( ccx. tcx , impl_id) . generics . type_param_defs . is_empty ( ) ;
803
- make_vtable ( ccx, ty:: trait_method_def_ids ( tcx, trt_id) . map ( |method_def_id| {
827
+
828
+ let trait_method_def_ids = ty:: trait_method_def_ids ( tcx, trt_id) ;
829
+ let methods = do trait_method_def_ids. map |method_def_id| {
804
830
let im = ty:: method ( tcx, * method_def_id) ;
805
- let fty = ty:: subst_tps ( tcx, substs, None ,
831
+ let fty = ty:: subst_tps ( tcx,
832
+ substs,
833
+ None ,
806
834
ty:: mk_bare_fn ( tcx, copy im. fty ) ) ;
807
835
if im. generics . has_type_params ( ) || ty:: type_has_self ( fty) {
808
836
debug ! ( "(making impl vtable) method has self or type params: %s" ,
@@ -828,7 +856,13 @@ pub fn make_impl_vtable(ccx: @CrateContext,
828
856
trans_external_path ( ccx, m_id, fty)
829
857
}
830
858
}
831
- } ) )
859
+ } ;
860
+
861
+ // Generate a type descriptor for the vtable.
862
+ let tydesc = get_tydesc ( ccx, self_ty) ;
863
+ glue:: lazily_emit_all_tydesc_glue ( ccx, tydesc) ;
864
+
865
+ make_vtable ( ccx, tydesc, methods)
832
866
}
833
867
834
868
pub fn trans_trait_cast ( bcx : block ,
@@ -850,40 +884,19 @@ pub fn trans_trait_cast(bcx: block,
850
884
let ccx = bcx. ccx ( ) ;
851
885
let v_ty = expr_ty ( bcx, val) ;
852
886
853
- match store {
854
- ty:: RegionTraitStore ( _) | ty:: BoxTraitStore => {
855
- let mut llboxdest = GEPi ( bcx, lldest, [ 0 u, abi:: trt_field_box] ) ;
856
- // Just store the pointer into the pair. (Region/borrowed
857
- // and boxed trait objects are represented as pairs, and
858
- // have no type descriptor field.)
859
- llboxdest = PointerCast ( bcx,
860
- llboxdest,
861
- T_ptr ( type_of ( bcx. ccx ( ) , v_ty) ) ) ;
862
- bcx = expr:: trans_into ( bcx, val, SaveIn ( llboxdest) ) ;
863
- }
864
- ty:: UniqTraitStore => {
865
- // Translate the uniquely-owned value in the
866
- // triple. (Unique trait objects are represented as
867
- // triples.)
868
- let mut llvaldest = GEPi ( bcx, lldest, [ 0 , abi:: trt_field_box] ) ;
869
- llvaldest = PointerCast ( bcx,
870
- llvaldest,
871
- T_ptr ( type_of ( bcx. ccx ( ) , v_ty) ) ) ;
872
- bcx = expr:: trans_into ( bcx, val, SaveIn ( llvaldest) ) ;
873
-
874
- // Get the type descriptor of the wrapped value and store
875
- // it in the triple as well.
876
- let tydesc = get_tydesc ( bcx. ccx ( ) , v_ty) ;
877
- glue:: lazily_emit_all_tydesc_glue ( bcx. ccx ( ) , tydesc) ;
878
- let lltydescdest = GEPi ( bcx, lldest, [ 0 , abi:: trt_field_tydesc] ) ;
879
- Store ( bcx, tydesc. tydesc , lltydescdest) ;
880
- }
881
- }
887
+ let mut llboxdest = GEPi ( bcx, lldest, [ 0 u, abi:: trt_field_box] ) ;
888
+ // Just store the pointer into the pair. (Region/borrowed
889
+ // and boxed trait objects are represented as pairs, and
890
+ // have no type descriptor field.)
891
+ llboxdest = PointerCast ( bcx,
892
+ llboxdest,
893
+ T_ptr ( type_of ( bcx. ccx ( ) , v_ty) ) ) ;
894
+ bcx = expr:: trans_into ( bcx, val, SaveIn ( llboxdest) ) ;
882
895
883
896
// Store the vtable into the pair or triple.
884
897
let orig = /*bad*/ copy ccx. maps . vtable_map . get ( & id) [ 0 ] ;
885
898
let orig = resolve_vtable_in_fn_ctxt ( bcx. fcx , orig) ;
886
- let vtable = get_vtable ( bcx. ccx ( ) , orig) ;
899
+ let vtable = get_vtable ( bcx. ccx ( ) , v_ty , orig) ;
887
900
Store ( bcx, vtable, PointerCast ( bcx,
888
901
GEPi ( bcx, lldest, [ 0 u, abi:: trt_field_vtable] ) ,
889
902
T_ptr ( val_ty ( vtable) ) ) ) ;
0 commit comments