1
Fork 0

Teach copy_ty to finish via memcpy of tydesc-provided size.

This commit is contained in:
Graydon Hoare 2011-01-17 13:30:29 -08:00
parent 57b281533d
commit d1fdf0ab23

View file

@ -1240,14 +1240,13 @@ fn drop_ty(@block_ctxt cx,
fn build_memcpy(@block_ctxt cx, fn build_memcpy(@block_ctxt cx,
ValueRef dst, ValueRef dst,
ValueRef src, ValueRef src,
TypeRef llty) -> result { ValueRef n_bytes) -> result {
// FIXME: switch to the 64-bit variant when on such a platform. // FIXME: switch to the 64-bit variant when on such a platform.
check (cx.fcx.ccx.intrinsics.contains_key("llvm.memcpy.p0i8.p0i8.i32")); check (cx.fcx.ccx.intrinsics.contains_key("llvm.memcpy.p0i8.p0i8.i32"));
auto memcpy = cx.fcx.ccx.intrinsics.get("llvm.memcpy.p0i8.p0i8.i32"); auto memcpy = cx.fcx.ccx.intrinsics.get("llvm.memcpy.p0i8.p0i8.i32");
auto src_ptr = cx.build.PointerCast(src, T_ptr(T_i8())); auto src_ptr = cx.build.PointerCast(src, T_ptr(T_i8()));
auto dst_ptr = cx.build.PointerCast(dst, T_ptr(T_i8())); auto dst_ptr = cx.build.PointerCast(dst, T_ptr(T_i8()));
auto size = cx.build.IntCast(lib.llvm.llvm.LLVMSizeOf(llty), auto size = cx.build.IntCast(n_bytes, T_i32());
T_i32());
auto align = cx.build.IntCast(C_int(1), T_i32()); auto align = cx.build.IntCast(C_int(1), T_i32());
// FIXME: align seems like it should be // FIXME: align seems like it should be
@ -1260,6 +1259,20 @@ fn build_memcpy(@block_ctxt cx,
size, align, volatile))); size, align, volatile)));
} }
fn memcpy_ty(@block_ctxt cx,
ValueRef dst,
ValueRef src,
@ty.t t) -> result {
if (ty.type_has_dynamic_size(t)) {
auto llszptr = field_of_tydesc(cx, t, abi.tydesc_field_size);
auto llsz = cx.build.Load(llszptr);
ret build_memcpy(cx, dst, src, llsz);
} else {
ret res(cx, cx.build.Store(cx.build.Load(src), dst));
}
}
fn copy_ty(@block_ctxt cx, fn copy_ty(@block_ctxt cx,
bool is_init, bool is_init,
ValueRef dst, ValueRef dst,
@ -1278,15 +1291,13 @@ fn copy_ty(@block_ctxt cx,
} }
ret res(r.bcx, r.bcx.build.Store(src, dst)); ret res(r.bcx, r.bcx.build.Store(src, dst));
} else if (ty.type_is_structural(t)) { } else if (ty.type_is_structural(t) ||
ty.type_has_dynamic_size(t)) {
auto r = incr_all_refcnts(cx, src, t); auto r = incr_all_refcnts(cx, src, t);
if (! is_init) { if (! is_init) {
r = drop_ty(r.bcx, dst, t); r = drop_ty(r.bcx, dst, t);
} }
// In this one surprising case, we do a load/store on ret memcpy_ty(r.bcx, dst, src, t);
// structure types. This results in a memcpy. Usually
// we talk about structures by pointers in this file.
ret res(r.bcx, r.bcx.build.Store(r.bcx.build.Load(src), dst));
} }
cx.fcx.ccx.sess.bug("unexpected type in trans.copy_ty: " + cx.fcx.ccx.sess.bug("unexpected type in trans.copy_ty: " +
@ -2598,7 +2609,9 @@ impure fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result {
alt (e) { alt (e) {
case (some[@ast.expr](?ex)) { case (some[@ast.expr](?ex)) {
if (ty.type_is_nil(ty.expr_ty(ex))) { auto t = ty.expr_ty(ex);
if (ty.type_is_nil(t)) {
r.bcx.build.RetVoid(); r.bcx.build.RetVoid();
r.val = C_nil(); r.val = C_nil();
ret r; // FIXME: early return needed due to typestate bug ret r; // FIXME: early return needed due to typestate bug
@ -2606,8 +2619,8 @@ impure fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result {
alt (cx.fcx.llretptr) { alt (cx.fcx.llretptr) {
case (some[ValueRef](?llptr)) { case (some[ValueRef](?llptr)) {
// FIXME: Generic return: Needs to use tydesc. // Generic return via tydesc + retptr.
// r.bcx.build.Store(r.val, llptr); r = copy_ty(r.bcx, true, llptr, r.val, t);
r.bcx.build.RetVoid(); r.bcx.build.RetVoid();
} }
case (none[ValueRef]) { case (none[ValueRef]) {