@@ -3499,6 +3499,172 @@ mod ivec {
3499
3499
post_copy_cx. build. Br ( copy_loop_header_cx. llbb) ;
3500
3500
ret res( next_cx, C_nil ( ) ) ;
3501
3501
}
3502
+
3503
+ fn alloc( & @block_ctxt bcx, ty:: t unit_ty, ValueRef llalen) -> ValueRef {
3504
+ auto llunitty = type_of_or_i8( bcx, unit_ty) ;
3505
+ if ( ty:: type_has_dynamic_size( bcx. fcx. lcx. ccx. tcx, unit_ty) ) {
3506
+ auto llarraysz = bcx. build. Add ( llsize_of( T_opaque_ivec ( ) ) ,
3507
+ llalen) ;
3508
+ auto llvecptr = array_alloca( bcx, T_i8 ( ) , llarraysz) ;
3509
+ ret bcx. build. PointerCast ( llvecptr, T_ptr ( T_opaque_ivec ( ) ) ) ;
3510
+ }
3511
+
3512
+ ret alloca( bcx, T_ivec ( llunitty) ) ;
3513
+ }
3514
+
3515
+ fn trans_add( & @block_ctxt cx, ty:: t vec_ty, ValueRef lhs, ValueRef rhs)
3516
+ -> result {
3517
+ auto bcx = cx;
3518
+
3519
+ auto unit_ty = ty:: sequence_element_type( bcx. fcx. lcx. ccx. tcx, vec_ty) ;
3520
+
3521
+ auto rslt = size_of( bcx, unit_ty) ;
3522
+ auto unit_sz = rslt. val;
3523
+
3524
+ auto llalen = bcx. build. Mul ( unit_sz,
3525
+ C_uint ( abi:: ivec_default_length) ) ;
3526
+ auto llvecptr = alloc( bcx, unit_ty, llalen) ;
3527
+ auto llunitty = type_of_or_i8( bcx, unit_ty) ;
3528
+ auto llheappartty = T_ivec_heap_part ( llunitty) ;
3529
+
3530
+ auto lhs_len_and_data = get_len_and_data( bcx, lhs, unit_ty) ;
3531
+ auto lhs_len = lhs_len_and_data. _0;
3532
+ auto lhs_data = lhs_len_and_data. _1;
3533
+ bcx = lhs_len_and_data. _2;
3534
+
3535
+ auto rhs_len_and_data = get_len_and_data( bcx, rhs, unit_ty) ;
3536
+ auto rhs_len = rhs_len_and_data. _0;
3537
+ auto rhs_data = rhs_len_and_data. _1;
3538
+ bcx = rhs_len_and_data. _2;
3539
+
3540
+ auto lllen = bcx. build. Add ( lhs_len, rhs_len) ;
3541
+
3542
+ // We have three cases to handle here:
3543
+ // (1) Length is zero ([] + []).
3544
+ // (2) Copy onto stack.
3545
+ // (3) Allocate on heap and copy there.
3546
+
3547
+ auto len_is_zero = bcx. build. ICmp ( lib:: llvm:: LLVMIntEQ , lllen,
3548
+ C_int ( 0 ) ) ;
3549
+ auto zero_len_cx = new_sub_block_ctxt( bcx, "zero_len") ;
3550
+ auto nonzero_len_cx = new_sub_block_ctxt( bcx, "nonzero_len") ;
3551
+ bcx. build. CondBr ( len_is_zero, zero_len_cx. llbb, nonzero_len_cx. llbb) ;
3552
+
3553
+ // Case (1): Length is zero.
3554
+ auto stub_ptr_zero = zero_len_cx. build. PointerCast ( llvecptr,
3555
+ T_ptr ( T_ivec_heap ( llunitty) ) ) ;
3556
+ zero_len_cx. build. Store ( C_int ( 0 ) , zero_len_cx. build. InBoundsGEP (
3557
+ stub_ptr_zero, [ C_int ( 0 ) , C_uint ( abi:: ivec_heap_stub_elt_zero) ] ) ) ;
3558
+ zero_len_cx. build. Store ( llalen, zero_len_cx. build. InBoundsGEP (
3559
+ stub_ptr_zero, [ C_int ( 0 ) , C_uint ( abi:: ivec_heap_stub_elt_alen) ] ) ) ;
3560
+ zero_len_cx. build. Store ( C_null ( T_ptr ( llheappartty) ) ,
3561
+ zero_len_cx. build. InBoundsGEP ( stub_ptr_zero,
3562
+ [ C_int ( 0 ) , C_uint ( abi:: ivec_heap_stub_elt_ptr) ] ) ) ;
3563
+ auto next_cx = new_sub_block_ctxt( bcx, "next") ;
3564
+ zero_len_cx. build. Br ( next_cx. llbb) ;
3565
+
3566
+ // Determine whether we need to spill to the heap.
3567
+ auto on_stack = nonzero_len_cx. build. ICmp ( lib:: llvm:: LLVMIntULE ,
3568
+ lllen, llalen) ;
3569
+ auto stack_cx = new_sub_block_ctxt( bcx, "stack") ;
3570
+ auto heap_cx = new_sub_block_ctxt( bcx, "heap") ;
3571
+ nonzero_len_cx. build. CondBr ( on_stack, stack_cx. llbb, heap_cx. llbb) ;
3572
+
3573
+ // Case (2): Copy onto stack.
3574
+ stack_cx. build. Store ( lllen, stack_cx. build. InBoundsGEP ( llvecptr,
3575
+ [ C_int ( 0 ) , C_uint ( abi:: ivec_elt_len) ] ) ) ;
3576
+ stack_cx. build. Store ( llalen, stack_cx. build. InBoundsGEP ( llvecptr,
3577
+ [ C_int ( 0 ) , C_uint ( abi:: ivec_elt_alen) ] ) ) ;
3578
+ auto dest_ptr_stack = stack_cx. build. InBoundsGEP ( llvecptr,
3579
+ [ C_int ( 0 ) , C_uint ( abi:: ivec_elt_elems) , C_int ( 0 ) ] ) ;
3580
+ auto copy_cx = new_sub_block_ctxt( bcx, "copy") ;
3581
+ stack_cx. build. Br ( copy_cx. llbb) ;
3582
+
3583
+ // Case (3): Allocate on heap and copy there.
3584
+ auto stub_ptr_heap = heap_cx. build. PointerCast ( llvecptr,
3585
+ T_ptr ( T_ivec_heap ( llunitty) ) ) ;
3586
+ heap_cx. build. Store ( C_int ( 0 ) , heap_cx. build. InBoundsGEP (
3587
+ stub_ptr_heap, [ C_int ( 0 ) , C_uint ( abi:: ivec_heap_stub_elt_zero) ] ) ) ;
3588
+ heap_cx. build. Store ( lllen, heap_cx. build. InBoundsGEP (
3589
+ stub_ptr_heap, [ C_int ( 0 ) , C_uint ( abi:: ivec_heap_stub_elt_alen) ] ) ) ;
3590
+
3591
+ auto heap_sz = heap_cx. build. Add ( llsize_of( llheappartty) , lllen) ;
3592
+
3593
+ rslt = trans_raw_malloc( heap_cx, T_ptr ( llheappartty) , heap_sz) ;
3594
+ auto heap_part = rslt. val;
3595
+ heap_cx = rslt. bcx;
3596
+
3597
+ heap_cx. build. Store ( heap_part, heap_cx. build. InBoundsGEP (
3598
+ stub_ptr_heap, [ C_int ( 0 ) , C_uint ( abi:: ivec_heap_stub_elt_ptr) ] ) ) ;
3599
+ heap_cx. build. Store ( lllen, heap_cx. build. InBoundsGEP ( heap_part,
3600
+ [ C_int ( 0 ) , C_uint ( abi:: ivec_heap_elt_len) ] ) ) ;
3601
+ auto dest_ptr_heap = heap_cx. build. InBoundsGEP ( heap_part,
3602
+ [ C_int ( 0 ) , C_uint ( abi:: ivec_heap_elt_elems) , C_int ( 0 ) ] ) ;
3603
+ heap_cx. build. Br ( copy_cx. llbb) ;
3604
+
3605
+ // Emit the copy loop.
3606
+ auto first_dest_ptr = copy_cx. build. Phi ( T_ptr ( llunitty) ,
3607
+ [ dest_ptr_stack, dest_ptr_heap] , [ stack_cx. llbb, heap_cx. llbb] ) ;
3608
+
3609
+ auto lhs_len_unscaled = copy_cx. build. UDiv ( lhs_len, unit_sz) ;
3610
+ auto lhs_end_ptr = copy_cx. build. InBoundsGEP ( lhs_data,
3611
+ [ lhs_len_unscaled] ) ;
3612
+ auto rhs_len_unscaled = copy_cx. build. UDiv ( rhs_len, unit_sz) ;
3613
+ auto rhs_end_ptr = copy_cx. build. InBoundsGEP ( rhs_data,
3614
+ [ rhs_len_unscaled] ) ;
3615
+
3616
+ auto dest_ptr_ptr = alloca( copy_cx, T_ptr ( llunitty) ) ;
3617
+ copy_cx. build. Store ( first_dest_ptr, dest_ptr_ptr) ;
3618
+ auto lhs_ptr_ptr = alloca( copy_cx, T_ptr ( llunitty) ) ;
3619
+ copy_cx. build. Store ( lhs_data, lhs_ptr_ptr) ;
3620
+ auto rhs_ptr_ptr = alloca( copy_cx, T_ptr ( llunitty) ) ;
3621
+ copy_cx. build. Store ( rhs_data, rhs_ptr_ptr) ;
3622
+
3623
+ auto lhs_copy_cx = new_sub_block_ctxt( bcx, "lhs_copy") ;
3624
+ copy_cx. build. Br ( lhs_copy_cx. llbb) ;
3625
+
3626
+ // Copy in elements from the LHS.
3627
+ auto lhs_ptr = lhs_copy_cx. build. Load ( lhs_ptr_ptr) ;
3628
+ auto not_at_end_lhs = lhs_copy_cx. build. ICmp ( lib:: llvm:: LLVMIntNE ,
3629
+ lhs_ptr, lhs_end_ptr) ;
3630
+ auto lhs_do_copy_cx = new_sub_block_ctxt( bcx, "lhs_do_copy") ;
3631
+ auto rhs_copy_cx = new_sub_block_ctxt( bcx, "rhs_copy") ;
3632
+ lhs_copy_cx. build. CondBr ( not_at_end_lhs, lhs_do_copy_cx. llbb,
3633
+ rhs_copy_cx. llbb) ;
3634
+
3635
+ auto dest_ptr_lhs_copy = lhs_do_copy_cx. build. Load ( dest_ptr_ptr) ;
3636
+ auto lhs_val = load_if_immediate( lhs_do_copy_cx, lhs_ptr, unit_ty) ;
3637
+ rslt = copy_val( lhs_do_copy_cx, INIT , dest_ptr_lhs_copy, lhs_val,
3638
+ unit_ty) ;
3639
+ lhs_do_copy_cx = rslt. bcx;
3640
+ lhs_do_copy_cx. build. Store ( lhs_do_copy_cx. build. InBoundsGEP (
3641
+ dest_ptr_lhs_copy, [ C_int ( 1 ) ] ) , dest_ptr_ptr) ;
3642
+ lhs_do_copy_cx. build. Store ( lhs_do_copy_cx. build. InBoundsGEP (
3643
+ lhs_ptr, [ C_int ( 1 ) ] ) , lhs_ptr_ptr) ;
3644
+ lhs_do_copy_cx. build. Br ( lhs_copy_cx. llbb) ;
3645
+
3646
+ // Copy in elements from the RHS.
3647
+ auto rhs_ptr = rhs_copy_cx. build. Load ( rhs_ptr_ptr) ;
3648
+ auto not_at_end_rhs = rhs_copy_cx. build. ICmp ( lib:: llvm:: LLVMIntNE ,
3649
+ rhs_ptr, rhs_end_ptr) ;
3650
+ auto rhs_do_copy_cx = new_sub_block_ctxt( bcx, "rhs_do_copy") ;
3651
+ rhs_copy_cx. build. CondBr ( not_at_end_rhs, rhs_do_copy_cx. llbb,
3652
+ next_cx. llbb) ;
3653
+
3654
+ auto dest_ptr_rhs_copy = rhs_do_copy_cx. build. Load ( dest_ptr_ptr) ;
3655
+ auto rhs_val = load_if_immediate( rhs_do_copy_cx, rhs_ptr, unit_ty) ;
3656
+ rslt = copy_val( rhs_do_copy_cx, INIT , dest_ptr_rhs_copy, rhs_val,
3657
+ unit_ty) ;
3658
+ rhs_do_copy_cx = rslt. bcx;
3659
+ rhs_do_copy_cx. build. Store ( rhs_do_copy_cx. build. InBoundsGEP (
3660
+ dest_ptr_rhs_copy, [ C_int ( 1 ) ] ) , dest_ptr_ptr) ;
3661
+ rhs_do_copy_cx. build. Store ( rhs_do_copy_cx. build. InBoundsGEP (
3662
+ rhs_ptr, [ C_int ( 1 ) ] ) , rhs_ptr_ptr) ;
3663
+ rhs_do_copy_cx. build. Br ( rhs_copy_cx. llbb) ;
3664
+
3665
+ // Finally done!
3666
+ ret res( next_cx, llvecptr) ;
3667
+ }
3502
3668
}
3503
3669
3504
3670
@@ -3523,6 +3689,9 @@ fn trans_eager_binop(&@block_ctxt cx, ast::binop op, &ty::t intype,
3523
3689
alt ( op) {
3524
3690
case ( ast:: add) {
3525
3691
if ( ty:: type_is_sequence( cx. fcx. lcx. ccx. tcx, intype) ) {
3692
+ if ( ty:: sequence_is_interior( cx. fcx. lcx. ccx. tcx, intype) ) {
3693
+ ret ivec:: trans_add( cx, intype, lhs, rhs) ;
3694
+ }
3526
3695
ret trans_vec_add( cx, intype, lhs, rhs) ;
3527
3696
}
3528
3697
if ( is_float) {
@@ -5170,6 +5339,7 @@ fn trans_vec(&@block_ctxt cx, &vec[@ast::expr] args, &ast::ann ann) ->
5170
5339
ret res( bcx, vec_val) ;
5171
5340
}
5172
5341
5342
+ // TODO: Move me to ivec::
5173
5343
fn trans_ivec( @block_ctxt bcx, & vec[ @ast:: expr] args, & ast:: ann ann) ->
5174
5344
result {
5175
5345
auto typ = node_ann_type( bcx. fcx. lcx. ccx, ann) ;
@@ -5183,17 +5353,12 @@ fn trans_ivec(@block_ctxt bcx, &vec[@ast::expr] args, &ast::ann ann) ->
5183
5353
bcx = rslt. bcx;
5184
5354
auto llalen = bcx. build. Mul ( unit_sz, C_uint ( abi:: ivec_default_length) ) ;
5185
5355
auto llunitty = type_of_or_i8( bcx, unit_ty) ;
5186
- auto llvecptr;
5187
- if ( ty:: type_has_dynamic_size( bcx. fcx. lcx. ccx. tcx, unit_ty) ) {
5188
- auto array_size = bcx. build. Add ( llsize_of( T_opaque_ivec ( ) ) , llalen) ;
5189
- llvecptr = array_alloca( bcx, T_i8 ( ) , array_size) ;
5190
- llvecptr = bcx. build. PointerCast ( llvecptr, T_ptr ( T_opaque_ivec ( ) ) ) ;
5191
- } else { llvecptr = alloca( bcx, T_ivec ( llunitty) ) ; }
5356
+ auto llvecptr = ivec:: alloc( bcx, unit_ty, llalen) ;
5192
5357
auto lllen = bcx. build. Mul ( C_uint ( vec:: len( args) ) , unit_sz) ;
5193
5358
// Allocate the vector pieces and store length and allocated length.
5194
5359
5195
5360
auto llfirsteltptr;
5196
- if ( vec:: len( args) > 0 u && vec:: len( args) < abi:: ivec_default_length) {
5361
+ if ( vec:: len( args) > 0 u && vec:: len( args) <= abi:: ivec_default_length) {
5197
5362
// Interior case.
5198
5363
5199
5364
bcx. build. Store ( lllen,
@@ -5222,7 +5387,7 @@ fn trans_ivec(@block_ctxt bcx, &vec[@ast::expr] args, &ast::ann ann) ->
5222
5387
bcx. build. InBoundsGEP ( llstubptr, stub_z) ) ;
5223
5388
bcx. build. Store ( lllen,
5224
5389
bcx. build. InBoundsGEP ( llstubptr, stub_a) ) ;
5225
- auto llheapty = struct_elt ( llstubty , abi :: ivec_heap_stub_elt_ptr ) ;
5390
+ auto llheapty = T_ivec_heap_part ( llunitty ) ;
5226
5391
if ( vec:: len( args) == 0 u) {
5227
5392
// Null heap pointer indicates a zero-length vector.
5228
5393
@@ -5236,7 +5401,7 @@ fn trans_ivec(@block_ctxt bcx, &vec[@ast::expr] args, &ast::ann ann) ->
5236
5401
auto llheapptr = rslt. val;
5237
5402
bcx. build. Store ( llheapptr,
5238
5403
bcx. build. InBoundsGEP ( llstubptr, stub_p) ) ;
5239
- auto heap_l = [ C_uint ( abi:: ivec_heap_elt_len) ] ;
5404
+ auto heap_l = [ C_int ( 0 ) , C_uint ( abi:: ivec_heap_elt_len) ] ;
5240
5405
bcx. build. Store ( lllen,
5241
5406
bcx. build. InBoundsGEP ( llheapptr, heap_l) ) ;
5242
5407
llfirsteltptr =
0 commit comments