mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-01 19:23:50 +00:00
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:
parent
e046360e69
commit
1c7a62c93b
@ -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:
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user