Skip to content

Commit 91c9cb9

Browse files
committed
---
yaml --- r: 3219 b: refs/heads/master c: 2b5e403 h: refs/heads/master i: 3217: 4caf15f 3215: 9b497f4 v: v3
1 parent fa88306 commit 91c9cb9

File tree

2 files changed

+88
-7
lines changed

2 files changed

+88
-7
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: 8c6354ceb905895c9f305716c66d5c7a8e4d0225
2+
refs/heads/master: 2b5e40311ddb6afcacf772e54a96a5204223dcc5

trunk/src/comp/middle/trans.rs

Lines changed: 87 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,7 +1327,8 @@ fn dynamic_size_of(&@block_ctxt cx, ty::t t) -> result {
13271327
auto bcx = rslt.bcx;
13281328
auto llunitszptr = rslt.val;
13291329
auto llunitsz = bcx.build.Load(llunitszptr);
1330-
auto llsz = bcx.build.Add(llsize_of(T_opaque_ivec()), llunitsz);
1330+
auto llsz = bcx.build.Add(llsize_of(T_opaque_ivec()),
1331+
bcx.build.Mul(llunitsz, C_uint(abi::ivec_default_length)));
13311332
ret res(bcx, llsz);
13321333
}
13331334
}
@@ -2969,9 +2970,21 @@ fn memmove_ty(&@block_ctxt cx, ValueRef dst, ValueRef src, &ty::t t) ->
29692970
} else { ret res(cx, cx.build.Store(cx.build.Load(src), dst)); }
29702971
}
29712972

2973+
// Duplicates the heap-owned memory owned by a value of the given type.
2974+
fn duplicate_heap_parts(&@block_ctxt cx, ValueRef vptr, ty::t typ) -> result {
2975+
alt (ty::struct(cx.fcx.lcx.ccx.tcx, typ)) {
2976+
case (ty::ty_ivec(?tm)) {
2977+
ret ivec::duplicate_heap_part(cx, vptr, tm.ty);
2978+
}
2979+
case (ty::ty_str) {
2980+
ret ivec::duplicate_heap_part(cx, vptr,
2981+
ty::mk_mach(cx.fcx.lcx.ccx.tcx, common::ty_u8));
2982+
}
2983+
}
2984+
}
2985+
29722986
tag copy_action { INIT; DROP_EXISTING; }
29732987

2974-
// FIXME: This should copy the contents of the heap part for ivecs.
29752988
fn copy_val(&@block_ctxt cx, copy_action action, ValueRef dst, ValueRef src,
29762989
&ty::t t) -> result {
29772990

@@ -2991,7 +3004,11 @@ fn copy_val(&@block_ctxt cx, copy_action action, ValueRef dst, ValueRef src,
29913004
ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, t)) {
29923005
auto r = take_ty(cx, src, t);
29933006
if (action == DROP_EXISTING) { r = drop_ty(r.bcx, dst, t); }
2994-
ret memmove_ty(r.bcx, dst, src, t);
3007+
r = memmove_ty(r.bcx, dst, src, t);
3008+
if (ty::type_owns_heap_mem(cx.fcx.lcx.ccx.tcx, t)) {
3009+
r = duplicate_heap_parts(cx, dst, t);
3010+
}
3011+
ret r;
29953012
}
29963013
cx.fcx.lcx.ccx.sess.bug("unexpected type in trans::copy_val: " +
29973014
ty_to_str(cx.fcx.lcx.ccx.tcx, t));
@@ -3501,8 +3518,8 @@ mod ivec {
35013518
copy_loop_body_cx.llbb,
35023519
next_cx.llbb);
35033520
auto copy_src_ptr = copy_loop_body_cx.build.Load(src_ptr);
3504-
rslt =
3505-
copy_val(copy_loop_body_cx, INIT, copy_dest_ptr, copy_src_ptr, t);
3521+
rslt = copy_val(copy_loop_body_cx, INIT, copy_dest_ptr, copy_src_ptr,
3522+
unit_ty);
35063523
auto post_copy_cx = rslt.bcx;
35073524
// Increment both pointers.
35083525

@@ -3740,6 +3757,66 @@ mod ivec {
37403757

37413758
ret res(next_cx, llvecptr);
37423759
}
3760+
3761+
// NB: This does *not* adjust reference counts. The caller must have done
3762+
// this via take_ty() beforehand.
3763+
fn duplicate_heap_part(&@block_ctxt cx, ValueRef orig_vptr,
3764+
ty::t unit_ty) -> result {
3765+
// Cast to an opaque interior vector if we can't trust the pointer
3766+
// type.
3767+
auto vptr;
3768+
if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, unit_ty)) {
3769+
vptr = cx.build.PointerCast(orig_vptr, T_ptr(T_opaque_ivec()));
3770+
} else {
3771+
vptr = orig_vptr;
3772+
}
3773+
3774+
auto llunitty = type_of_or_i8(cx, unit_ty);
3775+
auto llheappartty = T_ivec_heap_part(llunitty);
3776+
3777+
// Check to see if the vector is heapified.
3778+
auto stack_len_ptr = cx.build.InBoundsGEP(vptr, [C_int(0),
3779+
C_uint(abi::ivec_elt_len)]);
3780+
auto stack_len = cx.build.Load(stack_len_ptr);
3781+
auto stack_len_is_zero = cx.build.ICmp(lib::llvm::LLVMIntEQ,
3782+
stack_len, C_int(0));
3783+
auto maybe_on_heap_cx = new_sub_block_ctxt(cx, "maybe_on_heap");
3784+
auto next_cx = new_sub_block_ctxt(cx, "next");
3785+
cx.build.CondBr(stack_len_is_zero, maybe_on_heap_cx.llbb,
3786+
next_cx.llbb);
3787+
3788+
auto stub_ptr = maybe_on_heap_cx.build.PointerCast(vptr,
3789+
T_ptr(T_ivec_heap(llunitty)));
3790+
auto heap_ptr_ptr = maybe_on_heap_cx.build.InBoundsGEP(stub_ptr,
3791+
[C_int(0), C_uint(abi::ivec_heap_stub_elt_ptr)]);
3792+
auto heap_ptr = maybe_on_heap_cx.build.Load(heap_ptr_ptr);
3793+
auto heap_ptr_is_nonnull = maybe_on_heap_cx.build.ICmp(
3794+
lib::llvm::LLVMIntNE, heap_ptr, C_null(T_ptr(llheappartty)));
3795+
auto on_heap_cx = new_sub_block_ctxt(cx, "on_heap");
3796+
maybe_on_heap_cx.build.CondBr(heap_ptr_is_nonnull, on_heap_cx.llbb,
3797+
next_cx.llbb);
3798+
3799+
// Ok, the vector is on the heap. Copy the heap part.
3800+
auto alen_ptr = on_heap_cx.build.InBoundsGEP(stub_ptr,
3801+
[C_int(0), C_uint(abi::ivec_heap_stub_elt_alen)]);
3802+
auto alen = on_heap_cx.build.Load(alen_ptr);
3803+
3804+
auto heap_part_sz = on_heap_cx.build.Add(alen,
3805+
llsize_of(T_opaque_ivec_heap_part()));
3806+
auto rslt = trans_raw_malloc(on_heap_cx, T_ptr(llheappartty),
3807+
heap_part_sz);
3808+
on_heap_cx = rslt.bcx;
3809+
auto new_heap_ptr = rslt.val;
3810+
3811+
rslt = call_memmove(on_heap_cx, new_heap_ptr, heap_ptr, heap_part_sz,
3812+
C_int(4)); // FIXME: align
3813+
on_heap_cx = rslt.bcx;
3814+
3815+
on_heap_cx.build.Store(new_heap_ptr, heap_ptr_ptr);
3816+
on_heap_cx.build.Br(next_cx.llbb);
3817+
3818+
ret res(next_cx, C_nil());
3819+
}
37433820
}
37443821

37453822
fn trans_vec_add(&@block_ctxt cx, &ty::t t, ValueRef lhs, ValueRef rhs) ->
@@ -5431,6 +5508,8 @@ fn trans_ivec(@block_ctxt bcx, &vec[@ast::expr] args, &ast::ann ann) ->
54315508
auto unit_sz = ares.llunitsz;
54325509
auto llalen = ares.llalen;
54335510

5511+
find_scope_cx(bcx).cleanups += [clean(bind drop_ty(_, llvecptr, typ))];
5512+
54345513
auto lllen = bcx.build.Mul(C_uint(vec::len(args)), unit_sz);
54355514
// Allocate the vector pieces and store length and allocated length.
54365515

@@ -5459,15 +5538,17 @@ fn trans_ivec(@block_ctxt bcx, &vec[@ast::expr] args, &ast::ann ann) ->
54595538
auto llstubty = T_ivec_heap(llunitty);
54605539
auto llstubptr = bcx.build.PointerCast(llvecptr, T_ptr(llstubty));
54615540
bcx.build.Store(C_int(0), bcx.build.InBoundsGEP(llstubptr, stub_z));
5462-
bcx.build.Store(lllen, bcx.build.InBoundsGEP(llstubptr, stub_a));
54635541
auto llheapty = T_ivec_heap_part(llunitty);
54645542
if (vec::len(args) == 0u) {
54655543
// Null heap pointer indicates a zero-length vector.
54665544

5545+
bcx.build.Store(llalen, bcx.build.InBoundsGEP(llstubptr, stub_a));
54675546
bcx.build.Store(C_null(T_ptr(llheapty)),
54685547
bcx.build.InBoundsGEP(llstubptr, stub_p));
54695548
llfirsteltptr = C_null(T_ptr(llunitty));
54705549
} else {
5550+
bcx.build.Store(lllen, bcx.build.InBoundsGEP(llstubptr, stub_a));
5551+
54715552
auto llheapsz = bcx.build.Add(llsize_of(llheapty), lllen);
54725553
auto rslt = trans_raw_malloc(bcx, T_ptr(llheapty), llheapsz);
54735554
bcx = rslt.bcx;

0 commit comments

Comments
 (0)