Use a memset upcall to zero things without static alignment

This fixes issues #843 and #1546. The cost of an upcall is
unfortunate, though. I assume there must be a way to simply manually
compute the pointer or size, using something akin to the formula in
`align_to` in `rust_util.h`. I could not get this to work,
unfortunately.
This commit is contained in:
Marijn Haverbeke 2012-01-17 13:36:00 +01:00
parent e046360e69
commit 1c7a62c93b
4 changed files with 28 additions and 16 deletions

View File

@ -16,6 +16,7 @@ type upcalls =
free: ValueRef, free: ValueRef,
shared_malloc: ValueRef, shared_malloc: ValueRef,
shared_free: ValueRef, shared_free: ValueRef,
memset: ValueRef,
mark: ValueRef, mark: ValueRef,
create_shared_type_desc: ValueRef, create_shared_type_desc: ValueRef,
free_shared_type_desc: ValueRef, free_shared_type_desc: ValueRef,
@ -64,6 +65,7 @@ fn declare_upcalls(targ_cfg: @session::config,
T_ptr(T_i8())), T_ptr(T_i8())),
shared_free: shared_free:
dv("shared_free", [T_ptr(T_i8())]), dv("shared_free", [T_ptr(T_i8())]),
memset: dv("memset", [T_ptr(T_i8()), T_i8(), T_i32(), T_i32()]),
mark: mark:
d("mark", [T_ptr(T_i8())], int_t), d("mark", [T_ptr(T_i8())], int_t),
create_shared_type_desc: create_shared_type_desc:

View File

@ -1942,21 +1942,21 @@ fn call_memmove(cx: @block_ctxt, dst: ValueRef, src: ValueRef,
} }
fn call_bzero(cx: @block_ctxt, dst: ValueRef, n_bytes: ValueRef, fn call_bzero(cx: @block_ctxt, dst: ValueRef, n_bytes: ValueRef,
align_bytes: ValueRef) -> result { align_bytes: ValueRef) -> @block_ctxt {
// FIXME: switch to the 64-bit variant when on such a platform. // FIXME: switch to the 64-bit variant when on such a platform.
let ccx = bcx_ccx(cx); let ccx = bcx_ccx(cx), dst = dst;
let i = ccx.intrinsics;
assert (i.contains_key("llvm.memset.p0i8.i32"));
let memset = i.get("llvm.memset.p0i8.i32");
let dst_ptr = PointerCast(cx, dst, T_ptr(T_i8())); let dst_ptr = PointerCast(cx, dst, T_ptr(T_i8()));
let size = IntCast(cx, n_bytes, T_i32()); let size = IntCast(cx, n_bytes, T_i32());
let align = let align = IntCast(cx, align_bytes, T_i32());
if lib::llvm::llvm::LLVMIsConstant(align_bytes) == True { if lib::llvm::llvm::LLVMIsConstant(align_bytes) != True {
IntCast(cx, align_bytes, T_i32()) // Use our own upcall (see issue 843), since the LLVM intrinsic can
} else { IntCast(cx, C_int(ccx, 0), T_i32()) }; // only handle constant alignments.
let volatile = C_bool(false); Call(cx, ccx.upcalls.memset, [dst_ptr, C_u8(0u), size, align]);
ret rslt(cx, } else {
Call(cx, memset, [dst_ptr, C_u8(0u), size, align, volatile])); let memset = ccx.intrinsics.get("llvm.memset.p0i8.i32");
Call(cx, memset, [dst_ptr, C_u8(0u), size, align, C_bool(false)]);
}
cx
} }
fn memmove_ty(bcx: @block_ctxt, dst: ValueRef, src: ValueRef, t: ty::t) -> fn memmove_ty(bcx: @block_ctxt, dst: ValueRef, src: ValueRef, t: ty::t) ->
@ -3977,13 +3977,13 @@ fn zero_alloca(cx: @block_ctxt, llptr: ValueRef, t: ty::t)
let sp = cx.sp; let sp = cx.sp;
let llty = type_of(ccx, sp, t); let llty = type_of(ccx, sp, t);
Store(bcx, C_null(llty), llptr); Store(bcx, C_null(llty), llptr);
bcx
} else { } else {
let llsz = size_of(bcx, t); let {bcx, val: llsz} = size_of(bcx, t);
// FIXME passing in the align here is correct, but causes issue #843 // FIXME passing in the align here is correct, but causes issue #843
// let llalign = align_of(llsz.bcx, t); let {bcx, val: align} = align_of(bcx, t);
bcx = call_bzero(llsz.bcx, llptr, llsz.val, C_int(ccx, 0)).bcx; call_bzero(bcx, llptr, llsz, align)
} }
ret bcx;
} }
fn trans_stmt(cx: @block_ctxt, s: ast::stmt) -> @block_ctxt { fn trans_stmt(cx: @block_ctxt, s: ast::stmt) -> @block_ctxt {

View File

@ -227,6 +227,15 @@ upcall_shared_free(void* ptr) {
UPCALL_SWITCH_STACK(&args, upcall_s_shared_free); UPCALL_SWITCH_STACK(&args, upcall_s_shared_free);
} }
/************************************************************************
* Memset that, contrary to the llvm intrinsic, handles dynamic alignment
*/
extern "C" CDECL void
upcall_memset(void* ptr, char val, unsigned size, unsigned align) {
memset(ptr, val, align_to(size, align));
}
/********************************************************************** /**********************************************************************
* Called to deep copy a type descriptor onto the exchange heap. * Called to deep copy a type descriptor onto the exchange heap.
* Used when sending closures. It's possible that we should have * Used when sending closures. It's possible that we should have

View File

@ -74,6 +74,7 @@ upcall_rust_personality
upcall_s_shared_malloc upcall_s_shared_malloc
upcall_shared_malloc upcall_shared_malloc
upcall_shared_free upcall_shared_free
upcall_memset
upcall_vec_grow upcall_vec_grow
upcall_vec_push upcall_vec_push
upcall_call_shim_on_c_stack upcall_call_shim_on_c_stack