Skip to content

Commit ec02af3

Browse files
committed
---
yaml --- r: 3138 b: refs/heads/master c: 1fa9133 h: refs/heads/master v: v3
1 parent 65335df commit ec02af3

File tree

2 files changed

+175
-10
lines changed

2 files changed

+175
-10
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 260aa408f390cf457eb19507fc80ec388a039f8e
2+
refs/heads/master: 1fa9133b76ec4641e5470cbea8a8f95ec32f9563

trunk/src/comp/middle/trans.rs

Lines changed: 174 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3499,6 +3499,172 @@ mod ivec {
34993499
post_copy_cx.build.Br(copy_loop_header_cx.llbb);
35003500
ret res(next_cx, C_nil());
35013501
}
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+
}
35023668
}
35033669

35043670

@@ -3523,6 +3689,9 @@ fn trans_eager_binop(&@block_ctxt cx, ast::binop op, &ty::t intype,
35233689
alt (op) {
35243690
case (ast::add) {
35253691
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+
}
35263695
ret trans_vec_add(cx, intype, lhs, rhs);
35273696
}
35283697
if (is_float) {
@@ -5170,6 +5339,7 @@ fn trans_vec(&@block_ctxt cx, &vec[@ast::expr] args, &ast::ann ann) ->
51705339
ret res(bcx, vec_val);
51715340
}
51725341

5342+
// TODO: Move me to ivec::
51735343
fn trans_ivec(@block_ctxt bcx, &vec[@ast::expr] args, &ast::ann ann) ->
51745344
result {
51755345
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) ->
51835353
bcx = rslt.bcx;
51845354
auto llalen = bcx.build.Mul(unit_sz, C_uint(abi::ivec_default_length));
51855355
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);
51925357
auto lllen = bcx.build.Mul(C_uint(vec::len(args)), unit_sz);
51935358
// Allocate the vector pieces and store length and allocated length.
51945359

51955360
auto llfirsteltptr;
5196-
if (vec::len(args) > 0u && vec::len(args) < abi::ivec_default_length) {
5361+
if (vec::len(args) > 0u && vec::len(args) <= abi::ivec_default_length) {
51975362
// Interior case.
51985363

51995364
bcx.build.Store(lllen,
@@ -5222,7 +5387,7 @@ fn trans_ivec(@block_ctxt bcx, &vec[@ast::expr] args, &ast::ann ann) ->
52225387
bcx.build.InBoundsGEP(llstubptr, stub_z));
52235388
bcx.build.Store(lllen,
52245389
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);
52265391
if (vec::len(args) == 0u) {
52275392
// Null heap pointer indicates a zero-length vector.
52285393

@@ -5236,7 +5401,7 @@ fn trans_ivec(@block_ctxt bcx, &vec[@ast::expr] args, &ast::ann ann) ->
52365401
auto llheapptr = rslt.val;
52375402
bcx.build.Store(llheapptr,
52385403
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)];
52405405
bcx.build.Store(lllen,
52415406
bcx.build.InBoundsGEP(llheapptr, heap_l));
52425407
llfirsteltptr =

0 commit comments

Comments
 (0)