@@ -732,6 +732,108 @@ fn dynamic_align_of(@block_ctxt cx, @ty.t t) -> ValueRef {
732
732
}
733
733
}
734
734
735
+ // Replacement for the LLVM 'GEP' instruction when field-indexing into a
736
+ // tuple-like structure (tup, rec, tag) with a static index. This one is
737
+ // driven off ty.struct and knows what to do when it runs into a ty_param
738
+ // stuck in the middle of the thing it's GEP'ing into. Much like size_of and
739
+ // align_of, above.
740
+
741
+ fn GEP_tup_like ( @block_ctxt cx, @ty. t t,
742
+ ValueRef base, vec[ int] ixs) -> ValueRef {
743
+
744
+ check ( ty. type_is_tup_like( t) ) ;
745
+
746
+ // It might be a static-known type. Handle this.
747
+
748
+ if ( ! ty. type_has_dynamic_size( t) ) {
749
+ let vec[ ValueRef ] v = vec( ) ;
750
+ for ( int i in ixs) {
751
+ v += C_int ( i) ;
752
+ }
753
+ ret cx. build. GEP ( base, v) ;
754
+ }
755
+
756
+ // It is a dynamic-containing type that, if we convert directly to an LLVM
757
+ // TypeRef, will be all wrong; there's no proper LLVM type to represent
758
+ // it, and the lowering function will stick in i8* values for each
759
+ // ty_param, which is not right; the ty_params are all of some dynamic
760
+ // size.
761
+ //
762
+ // What we must do instead is sadder. We must look through the indices
763
+ // manually and split the input type into a prefix and a target. We then
764
+ // measure the prefix size, bump the input pointer by that amount, and
765
+ // cast to a pointer-to-target type.
766
+
767
+
768
+ // Given a type, an index vector and an element number N in that vector,
769
+ // calculate index X and the type that results by taking the first X-1
770
+ // elements of the type and splitting the Xth off. Return the prefix as
771
+ // well as the innermost Xth type.
772
+
773
+ fn split_type( @ty. t t, vec[ int] ixs, uint n)
774
+ -> rec( vec[ @ty. t] prefix, @ty. t target) {
775
+
776
+ let uint len = _vec. len[ int] ( ixs) ;
777
+
778
+ // We don't support 0-index or 1-index GEPs. The former is nonsense
779
+ // and the latter would only be meaningful if we supported non-0
780
+ // values for the 0th index (we don't).
781
+
782
+ check ( len > 1 u) ;
783
+
784
+ if ( n == 0 u) {
785
+ // Since we're starting from a value that's a pointer to a
786
+ // *single* structure, the first index (in GEP-ese) should just be
787
+ // 0, to yield the pointee.
788
+ check ( ixs. ( n) == 0 ) ;
789
+ ret split_type( t, ixs, n+1 u) ;
790
+ }
791
+
792
+ check ( n < len) ;
793
+
794
+ let int ix = ixs . ( n ) ;
795
+ let vec[ @ty. t] prefix = vec ( ) ;
796
+ let int i = 0 ;
797
+ while ( i < ix) {
798
+ append[ @ty. t] ( prefix, ty. get_element_type ( t, i as uint ) ) ;
799
+ i +=1 ;
800
+ }
801
+
802
+ auto selected = ty. get_element_type ( t, i as uint ) ;
803
+
804
+ if ( n == len-1 u) {
805
+ // We are at the innermost index.
806
+ ret rec ( prefix=prefix, target=selected) ;
807
+
808
+ } else {
809
+ // Not the innermost index; call self recursively to dig deeper.
810
+ // Once we get an inner result, append it current prefix and
811
+ // return to caller.
812
+ auto inner = split_type ( selected, ixs, n+1 u) ;
813
+ prefix += inner. prefix ;
814
+ ret rec ( prefix=prefix with inner) ;
815
+ }
816
+ }
817
+
818
+ // We make a fake prefix tuple-type here; luckily for measuring sizes
819
+ // the tuple parens are associative so it doesn't matter that we've
820
+ // flattened the incoming structure.
821
+
822
+ auto s = split_type ( t, ixs, 0 u) ;
823
+ auto prefix_ty = ty. plain_ty ( ty. ty_tup ( s. prefix ) ) ;
824
+ auto sz = size_of ( cx, prefix_ty) ;
825
+ auto raw = cx. build . PointerCast ( base, T_ptr ( T_i8 ( ) ) ) ;
826
+ auto bumped = cx. build . GEP ( raw, vec ( sz) ) ;
827
+ alt ( s. target . struct ) {
828
+ case ( ty. ty_param ( _) ) { ret bumped; }
829
+ case ( _) {
830
+ auto ty = T_ptr ( type_of ( cx. fcx . ccx , s. target ) ) ;
831
+ ret cx. build . PointerCast ( bumped, ty) ;
832
+ }
833
+ }
834
+ }
835
+
836
+
735
837
fn trans_malloc_inner ( @block_ctxt cx , TypeRef llptr_ty ) -> result {
736
838
auto llbody_ty = lib. llvm . llvm . LLVMGetElementType ( llptr_ty) ;
737
839
// FIXME: need a table to collect tydesc globals.
@@ -1969,12 +2071,12 @@ impure fn trans_field(@block_ctxt cx, &ast.span sp, @ast.expr base,
1969
2071
alt ( t. struct ) {
1970
2072
case ( ty. ty_tup( ?fields) ) {
1971
2073
let uint ix = ty. field_num( cx. fcx. ccx. sess, sp, field) ;
1972
- auto v = r. bcx. build . GEP ( r. val, vec( C_int ( 0 ) , C_int ( ix as int) ) ) ;
2074
+ auto v = GEP_tup_like ( r. bcx, t , r. val, vec( 0 , ix as int) ) ;
1973
2075
ret lval_mem( r. bcx, v) ;
1974
2076
}
1975
2077
case ( ty. ty_rec( ?fields) ) {
1976
2078
let uint ix = ty. field_idx( cx. fcx. ccx. sess, sp, field, fields) ;
1977
- auto v = r. bcx. build . GEP ( r. val, vec( C_int ( 0 ) , C_int ( ix as int) ) ) ;
2079
+ auto v = GEP_tup_like ( r. bcx, t , r. val, vec( 0 , ix as int) ) ;
1978
2080
ret lval_mem( r. bcx, v) ;
1979
2081
}
1980
2082
case ( ty. ty_obj( ?methods) ) {
0 commit comments