@@ -572,22 +572,28 @@ fn T_opaque_vec_ptr() -> TypeRef {
572
572
// Interior vector.
573
573
//
574
574
// TODO: Support user-defined vector sizes.
575
- fn T_ivec ( TypeRef t) -> TypeRef {
576
- ret T_struct ( [ T_int ( ) , // Length ("fill")
577
- T_int ( ) , // Alloc (if zero, it's heapified)
578
- T_array ( t, 16 u) // Body elements
579
- ] ) ;
575
+ fn T_ivec ( ) -> TypeRef {
576
+ ret T_struct ( [ T_int ( ) , // Length ("fill"; if zero, heapified)
577
+ T_int ( ) , // Alloc
578
+ T_array ( T_i8 ( ) , abi:: ivec_default_size) ] ) ; // Body elements
580
579
}
581
580
582
581
// Interior vector on the heap. Cast to this when the allocated length (second
583
582
// element of T_ivec above) is zero.
584
583
fn T_ivec_heap ( TypeRef t) -> TypeRef {
585
- ret T_struct ( [ T_int ( ) , // Length ("fill" )
586
- T_int ( ) , // Alloc (zero in this case)
587
- T_ptr ( T_struct ( [ T_int ( ) , // Real alloc
584
+ ret T_struct ( [ T_int ( ) , // Length (zero )
585
+ T_int ( ) , // Alloc
586
+ T_ptr ( T_struct ( [ T_int ( ) , // Real length
588
587
T_array ( t, 0 u) ] ) ) ] ) ; // Body elements
589
588
}
590
589
590
+ fn T_opaque_ivec_heap ( ) -> TypeRef {
591
+ ret T_struct ( [ T_int ( ) , // Length (zero)
592
+ T_int ( ) , // Alloc
593
+ T_ptr ( T_struct ( [ T_int ( ) , // Real length
594
+ T_array ( T_i8 ( ) , 0 u) ] ) ) ] ) ; // Body elements
595
+ }
596
+
591
597
fn T_str ( ) -> TypeRef {
592
598
ret T_vec ( T_i8 ( ) ) ;
593
599
}
@@ -862,7 +868,7 @@ fn type_of_inner(&@crate_ctxt cx, &span sp, &ty::t t) -> TypeRef {
862
868
}
863
869
case ( ty:: ty_char) { llty = T_char ( ) ; }
864
870
case ( ty:: ty_str) { llty = T_ptr ( T_str ( ) ) ; }
865
- case ( ty:: ty_istr) { llty = T_ivec ( T_i8 ( ) ) ; }
871
+ case ( ty:: ty_istr) { llty = T_ivec ( ) ; }
866
872
case ( ty:: ty_tag ( _, _) ) {
867
873
if ( ty:: type_has_dynamic_size ( cx. tcx , t) ) {
868
874
llty = T_opaque_tag ( cx. tn ) ;
@@ -878,7 +884,7 @@ fn type_of_inner(&@crate_ctxt cx, &span sp, &ty::t t) -> TypeRef {
878
884
llty = T_ptr ( T_vec ( type_of_inner ( cx, sp, mt. ty ) ) ) ;
879
885
}
880
886
case ( ty:: ty_ivec ( ?mt) ) {
881
- llty = T_ivec ( type_of_inner ( cx , sp , mt . ty ) ) ;
887
+ llty = T_ivec ( ) ;
882
888
}
883
889
case ( ty:: ty_ptr ( ?mt) ) {
884
890
llty = T_ptr ( type_of_inner ( cx, sp, mt. ty ) ) ;
@@ -989,6 +995,13 @@ fn type_of_ty_param_count_and_ty(@local_ctxt lcx, &span sp,
989
995
ret type_of( lcx. ccx , sp, tpt. _1 ) ;
990
996
}
991
997
998
+ fn type_of_or_i8 ( & @block_ctxt bcx , ty:: t typ ) -> TypeRef {
999
+ if ( ty:: type_has_dynamic_size ( bcx. fcx . lcx . ccx . tcx , typ) ) {
1000
+ ret T_i8 ( ) ;
1001
+ }
1002
+ ret type_of( bcx. fcx . lcx . ccx , bcx. sp , typ) ;
1003
+ }
1004
+
992
1005
993
1006
// Name sanitation. LLVM will happily accept identifiers with weird names, but
994
1007
// gas doesn't!
@@ -1058,6 +1071,10 @@ fn C_int(int i) -> ValueRef {
1058
1071
ret C_integral ( T_int ( ) , i as uint , True ) ;
1059
1072
}
1060
1073
1074
+ fn C_uint ( uint i) -> ValueRef {
1075
+ ret C_integral ( T_int ( ) , i, False ) ;
1076
+ }
1077
+
1061
1078
fn C_u8 ( uint i) -> ValueRef {
1062
1079
ret C_integral ( T_i8 ( ) , i, False ) ;
1063
1080
}
@@ -2635,6 +2652,64 @@ fn make_numerical_cmp_glue(&@block_ctxt cx, ValueRef lhs, ValueRef rhs,
2635
2652
r. bcx . build . RetVoid ( ) ;
2636
2653
}
2637
2654
2655
+ // Returns the length of an interior vector and a pointer to its first
2656
+ // element, in that order.
2657
+ fn get_ivec_len_and_data ( & @block_ctxt bcx , ValueRef v, ty:: t unit_ty ) ->
2658
+ tup ( ValueRef , ValueRef , @block_ctxt ) {
2659
+ auto llunitty = type_of_or_i8 ( bcx, unit_ty) ;
2660
+
2661
+ auto stack_len = bcx. build . Load ( bcx. build . GEP ( v,
2662
+ [ C_int ( 0 ) , C_uint ( abi:: ivec_elt_len) ] ) ) ;
2663
+ auto stack_elem = bcx. build . GEP ( v, [ C_int ( 0 ) ,
2664
+ C_uint ( abi:: ivec_elt_elems) ] ) ;
2665
+ stack_elem = bcx. build . PointerCast ( stack_elem, T_ptr ( llunitty) ) ;
2666
+
2667
+ auto on_heap = bcx. build . ICmp ( lib:: llvm:: LLVMIntEQ , stack_len, C_int ( 0 ) ) ;
2668
+
2669
+ auto on_heap_cx = new_sub_block_ctxt ( bcx, "on_heap" ) ;
2670
+ auto next_cx = new_sub_block_ctxt ( bcx, "next" ) ;
2671
+ bcx. build . CondBr ( on_heap, on_heap_cx. llbb , next_cx. llbb ) ;
2672
+
2673
+ auto heap_stub = on_heap_cx. build . PointerCast ( v,
2674
+ T_ptr ( T_ivec_heap ( llunitty) ) ) ;
2675
+ auto heap_ptr = on_heap_cx. build . Load ( on_heap_cx. build . GEP (
2676
+ heap_stub, [ C_int ( 0 ) , C_uint ( abi:: ivec_heap_stub_elt_ptr) ] ) ) ;
2677
+
2678
+ // Check whether the heap pointer is null. If it is, the vector length is
2679
+ // truly zero.
2680
+ auto llstubty = T_ivec_heap ( llunitty) ;
2681
+ auto llheapptrty = struct_elt ( llstubty, abi:: ivec_heap_stub_elt_ptr) ;
2682
+ auto heap_ptr_is_null = on_heap_cx. build . ICmp ( lib:: llvm:: LLVMIntEQ ,
2683
+ heap_ptr, C_null ( T_ptr ( llheapptrty) ) ) ;
2684
+
2685
+ auto zero_len_cx = new_sub_block_ctxt ( bcx, "zero_len" ) ;
2686
+ auto nonzero_len_cx = new_sub_block_ctxt ( bcx, "nonzero_len" ) ;
2687
+ on_heap_cx. build . CondBr ( heap_ptr_is_null, zero_len_cx. llbb ,
2688
+ nonzero_len_cx. llbb ) ;
2689
+
2690
+ // Technically this context is unnecessary, but it makes this function
2691
+ // clearer.
2692
+ auto zero_len = C_int ( 0 ) ;
2693
+ auto zero_elem = C_null ( T_ptr ( llunitty) ) ;
2694
+ zero_len_cx. build . Br ( next_cx. llbb ) ;
2695
+
2696
+ // If we're here, then we actually have a heapified vector.
2697
+ auto heap_len = nonzero_len_cx. build . Load ( nonzero_len_cx. build . GEP (
2698
+ heap_ptr, [ C_int ( 0 ) , C_uint ( abi:: ivec_heap_elt_len) ] ) ) ;
2699
+ auto heap_elem = nonzero_len_cx. build . GEP ( heap_ptr,
2700
+ [ C_int ( 0 ) , C_uint ( abi:: ivec_heap_elt_elems) , C_int ( 0 ) ] ) ;
2701
+ nonzero_len_cx. build . Br ( next_cx. llbb ) ;
2702
+
2703
+ // Now we can figure out the length of `v` and get a pointer to its first
2704
+ // element.
2705
+ auto len = next_cx. build . Phi ( T_int ( ) , [ stack_len, zero_len, heap_len] ,
2706
+ [ bcx. llbb , zero_len_cx. llbb , nonzero_len_cx. llbb ] ) ;
2707
+ auto elem = next_cx. build . Phi ( T_ptr ( llunitty) ,
2708
+ [ stack_elem, zero_elem, heap_elem] ,
2709
+ [ bcx. llbb , zero_len_cx. llbb , nonzero_len_cx. llbb ] ) ;
2710
+ ret tup( len, elem, next_cx) ;
2711
+ }
2712
+
2638
2713
type val_pair_fn = fn ( & @block_ctxt cx , ValueRef dst, ValueRef src) -> result ;
2639
2714
2640
2715
type val_and_ty_fn = fn ( & @block_ctxt cx , ValueRef v, ty:: t t) -> result ;
@@ -2666,7 +2741,6 @@ fn iter_structural_ty_full(&@block_ctxt cx,
2666
2741
& ty:: t t,
2667
2742
& val_pair_and_ty_fn f)
2668
2743
-> result {
2669
- let result r = res ( cx, C_nil ( ) ) ;
2670
2744
2671
2745
fn iter_boxpp ( @block_ctxt cx ,
2672
2746
ValueRef box_a_cell ,
@@ -2687,6 +2761,45 @@ fn iter_structural_ty_full(&@block_ctxt cx,
2687
2761
ret res ( next_cx, C_nil ( ) ) ;
2688
2762
}
2689
2763
2764
+ fn iter_ivec ( @block_ctxt bcx ,
2765
+ ValueRef av,
2766
+ ValueRef bv,
2767
+ ty:: t unit_ty ,
2768
+ & val_pair_and_ty_fn f) -> result {
2769
+ // FIXME: "unimplemented rebinding existing function" workaround
2770
+ fn adapter ( & @block_ctxt bcx , ValueRef av, ValueRef bv, ty:: t unit_ty ,
2771
+ val_pair_and_ty_fn f) -> result {
2772
+ ret f( bcx, av, bv, unit_ty) ;
2773
+ }
2774
+
2775
+ auto llunitty = type_of_or_i8 ( bcx, unit_ty) ;
2776
+
2777
+ auto rslt = size_of ( bcx, unit_ty) ;
2778
+ auto unit_sz = rslt. val ;
2779
+ bcx = rslt. bcx ;
2780
+
2781
+ auto a_len_and_data = get_ivec_len_and_data ( bcx, av, unit_ty) ;
2782
+ auto a_len = a_len_and_data. _0 ;
2783
+ auto a_elem = a_len_and_data. _1 ;
2784
+ bcx = a_len_and_data. _2 ;
2785
+
2786
+ auto b_len_and_data = get_ivec_len_and_data ( bcx, bv, unit_ty) ;
2787
+ auto b_len = b_len_and_data. _0 ;
2788
+ auto b_elem = b_len_and_data. _1 ;
2789
+ bcx = b_len_and_data. _2 ;
2790
+
2791
+ // Calculate the last pointer address we want to handle.
2792
+ auto len = umin ( bcx, a_len, b_len) ;
2793
+ auto b_elem_i8 = bcx. build . PointerCast ( b_elem, T_ptr ( T_i8 ( ) ) ) ;
2794
+ auto b_end_i8 = bcx. build . GEP ( b_elem_i8, [ len] ) ;
2795
+ auto b_end = bcx. build . PointerCast ( b_end_i8, T_ptr ( llunitty) ) ;
2796
+
2797
+ // Now perform the iteration.
2798
+ auto vpf = bind adapter ( _, _, _, unit_ty, f) ;
2799
+ ret iter_sequence_raw ( bcx, a_elem, b_elem, b_end, unit_sz, vpf) ;
2800
+ }
2801
+
2802
+ let result r = res ( cx, C_nil ( ) ) ;
2690
2803
alt ( ty:: struct ( cx. fcx . lcx . ccx . tcx , t) ) {
2691
2804
case ( ty:: ty_tup ( ?args) ) {
2692
2805
let int i = 0 ;
@@ -2831,6 +2944,13 @@ fn iter_structural_ty_full(&@block_ctxt cx,
2831
2944
C_int ( abi:: obj_field_box) ] ) ;
2832
2945
ret iter_boxpp( cx, box_cell_a, box_cell_b, f) ;
2833
2946
}
2947
+ case ( ty:: ty_ivec( ?unit_tm) ) {
2948
+ ret iter_ivec( cx, av, bv, unit_tm. ty, f) ;
2949
+ }
2950
+ case ( ty:: ty_istr) {
2951
+ auto unit_ty = ty:: mk_mach( cx. fcx. lcx. ccx. tcx, common:: ty_u8) ;
2952
+ ret iter_ivec( cx, av, bv, unit_ty, f) ;
2953
+ }
2834
2954
case ( _) {
2835
2955
cx. fcx. lcx. ccx. sess. unimpl( "type in iter_structural_ty_full" ) ;
2836
2956
}
@@ -5475,6 +5595,93 @@ fn trans_vec(&@block_ctxt cx, &vec[@ast::expr] args,
5475
5595
ret res( bcx, vec_val) ;
5476
5596
}
5477
5597
5598
+ fn trans_ivec( @block_ctxt bcx, & vec[ @ast:: expr] args, & ast:: ann ann)
5599
+ -> result {
5600
+ auto typ = node_ann_type( bcx. fcx. lcx. ccx, ann) ;
5601
+ auto unit_ty;
5602
+ alt ( ty:: struct ( bcx. fcx. lcx. ccx. tcx, typ) ) {
5603
+ case ( ty:: ty_ivec( ?mt) ) { unit_ty = mt. ty; }
5604
+ case ( _) { bcx. fcx. lcx. ccx. sess. bug( "non-ivec type in trans_ivec" ) ; }
5605
+ }
5606
+
5607
+ auto rslt = size_of( bcx, unit_ty) ;
5608
+ auto unit_sz = rslt. val;
5609
+ bcx = rslt. bcx;
5610
+ rslt = align_of( bcx, unit_ty) ;
5611
+ auto unit_align = rslt. val;
5612
+ bcx = rslt. bcx;
5613
+
5614
+ auto llunitty = type_of_or_i8( bcx, unit_ty) ;
5615
+ auto llvecptr = alloca( bcx, T_ivec ( ) ) ;
5616
+ auto lllen = bcx. build. Mul ( C_uint ( vec:: len( args) ) , unit_sz) ;
5617
+
5618
+ // Allocate the vector pieces and store length and allocated length.
5619
+ auto llfirsteltptr;
5620
+ if ( vec:: len( args) > 0 u && vec:: len( args) < abi:: ivec_default_size) {
5621
+ // Interior case.
5622
+ bcx. build. Store ( lllen, bcx. build. GEP ( llvecptr,
5623
+ [ C_int( 0 ) , C_uint ( abi : : ivec_elt_len) ] ) ) ;
5624
+ bcx. build. Store ( C_uint ( abi:: ivec_elt_alen) , bcx. build. GEP ( llvecptr,
5625
+ [ C_int ( 0 ) , C_uint ( abi:: ivec_elt_alen) ] ) ) ;
5626
+ llfirsteltptr = bcx. build. GEP ( llvecptr,
5627
+ [ C_int ( 0 ) , C_uint ( abi:: ivec_elt_elems) ] ) ;
5628
+ } else {
5629
+ // Heap case.
5630
+ auto llstubty = T_ivec_heap ( llunitty) ;
5631
+ auto llstubptr = bcx. build. PointerCast ( llvecptr, T_ptr ( llstubty) ) ;
5632
+
5633
+ bcx. build. Store ( C_int ( 0 ) , bcx. build. GEP ( llstubptr,
5634
+ [ C_int ( 0 ) , C_uint ( abi:: ivec_heap_stub_elt_zero) ] ) ) ;
5635
+ bcx. build. Store ( C_uint ( abi:: ivec_elt_alen) , bcx. build. GEP ( llstubptr,
5636
+ [ C_int ( 0 ) , C_uint ( abi:: ivec_heap_stub_elt_alen) ] ) ) ;
5637
+
5638
+ auto llheapty = struct_elt( llstubty, abi:: ivec_heap_stub_elt_ptr) ;
5639
+
5640
+ if ( vec:: len( args) == 0 u) {
5641
+ // Null heap pointer indicates a zero-length vector.
5642
+ bcx. build. Store ( C_null ( T_ptr ( llheapty) ) , bcx. build. GEP ( llstubptr,
5643
+ [ C_int ( 0 ) , C_uint ( abi:: ivec_heap_stub_elt_ptr) ] ) ) ;
5644
+ llfirsteltptr = C_null ( T_ptr ( llunitty) ) ;
5645
+ } else {
5646
+ auto llheapsz = bcx. build. Add ( llsize_of( llheapty) , lllen) ;
5647
+ rslt = trans_raw_malloc( bcx, llheapty, llheapsz) ;
5648
+ bcx = rslt. bcx;
5649
+ auto llheapptr = rslt. val;
5650
+
5651
+ bcx. build. Store ( llheapptr, bcx. build. GEP ( llstubptr,
5652
+ [ C_int ( 0 ) , C_uint ( abi:: ivec_heap_stub_elt_ptr) ] ) ) ;
5653
+ bcx. build. Store ( lllen, bcx. build. GEP ( llheapptr,
5654
+ [ C_int ( 0 ) , C_uint ( abi:: ivec_heap_elt_len) ] ) ) ;
5655
+ llfirsteltptr = bcx. build. GEP ( llheapptr,
5656
+ [ C_int ( 0 ) , C_uint ( abi:: ivec_heap_elt_elems) ] ) ;
5657
+ }
5658
+ }
5659
+
5660
+ llfirsteltptr = bcx. build. PointerCast ( llfirsteltptr, T_ptr ( llunitty) ) ;
5661
+
5662
+ // Store the individual elements.
5663
+ auto i = 0 u;
5664
+ for ( @ast:: expr e in args) {
5665
+ rslt = trans_expr ( bcx, e) ;
5666
+ bcx = rslt. bcx ;
5667
+ auto llsrc = rslt. val ;
5668
+
5669
+ auto lleltptr;
5670
+ if ( ty:: type_has_dynamic_size ( bcx. fcx . lcx . ccx . tcx , unit_ty) ) {
5671
+ lleltptr = bcx. build . GEP ( llfirsteltptr,
5672
+ [ bcx. build . Mul ( C_uint ( i) , unit_align) ] ) ;
5673
+ } else {
5674
+ lleltptr = bcx. build . GEP ( llfirsteltptr, [ C_uint ( i) ] ) ;
5675
+ }
5676
+
5677
+ bcx = copy_val ( bcx, INIT , lleltptr, llsrc, unit_ty) . bcx ;
5678
+
5679
+ i += 1 u;
5680
+ }
5681
+
5682
+ ret res( bcx, llvecptr) ;
5683
+ }
5684
+
5478
5685
fn trans_rec ( & @block_ctxt cx , & vec[ ast:: field ] fields ,
5479
5686
& option:: t[ @ast:: expr] base , & ast:: ann ann) -> result {
5480
5687
@@ -5649,10 +5856,14 @@ fn trans_expr_out(&@block_ctxt cx, &@ast::expr e, out_method output)
5649
5856
ret trans_cast( cx, e, ann) ;
5650
5857
}
5651
5858
5652
- case ( ast:: expr_vec( ?args, _, _ , ?ann) ) {
5859
+ case ( ast:: expr_vec( ?args, _, ast :: sk_rc , ?ann) ) {
5653
5860
ret trans_vec( cx, args, ann) ;
5654
5861
}
5655
5862
5863
+ case ( ast:: expr_vec( ?args, _, ast:: sk_unique, ?ann) ) {
5864
+ ret trans_ivec( cx, args, ann) ;
5865
+ }
5866
+
5656
5867
case ( ast:: expr_tup( ?args, ?ann) ) {
5657
5868
ret trans_tup( cx, args, ann) ;
5658
5869
}
0 commit comments