Skip to content

Commit 1c7a62c

Browse files
committed
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.
1 parent e046360 commit 1c7a62c

File tree

4 files changed

+28
-16
lines changed

4 files changed

+28
-16
lines changed

src/comp/back/upcall.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ type upcalls =
1616
free: ValueRef,
1717
shared_malloc: ValueRef,
1818
shared_free: ValueRef,
19+
memset: ValueRef,
1920
mark: ValueRef,
2021
create_shared_type_desc: ValueRef,
2122
free_shared_type_desc: ValueRef,
@@ -64,6 +65,7 @@ fn declare_upcalls(targ_cfg: @session::config,
6465
T_ptr(T_i8())),
6566
shared_free:
6667
dv("shared_free", [T_ptr(T_i8())]),
68+
memset: dv("memset", [T_ptr(T_i8()), T_i8(), T_i32(), T_i32()]),
6769
mark:
6870
d("mark", [T_ptr(T_i8())], int_t),
6971
create_shared_type_desc:

src/comp/middle/trans.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1942,21 +1942,21 @@ fn call_memmove(cx: @block_ctxt, dst: ValueRef, src: ValueRef,
19421942
}
19431943

19441944
fn call_bzero(cx: @block_ctxt, dst: ValueRef, n_bytes: ValueRef,
1945-
align_bytes: ValueRef) -> result {
1945+
align_bytes: ValueRef) -> @block_ctxt {
19461946
// FIXME: switch to the 64-bit variant when on such a platform.
1947-
let ccx = bcx_ccx(cx);
1948-
let i = ccx.intrinsics;
1949-
assert (i.contains_key("llvm.memset.p0i8.i32"));
1950-
let memset = i.get("llvm.memset.p0i8.i32");
1947+
let ccx = bcx_ccx(cx), dst = dst;
19511948
let dst_ptr = PointerCast(cx, dst, T_ptr(T_i8()));
19521949
let size = IntCast(cx, n_bytes, T_i32());
1953-
let align =
1954-
if lib::llvm::llvm::LLVMIsConstant(align_bytes) == True {
1955-
IntCast(cx, align_bytes, T_i32())
1956-
} else { IntCast(cx, C_int(ccx, 0), T_i32()) };
1957-
let volatile = C_bool(false);
1958-
ret rslt(cx,
1959-
Call(cx, memset, [dst_ptr, C_u8(0u), size, align, volatile]));
1950+
let align = IntCast(cx, align_bytes, T_i32());
1951+
if lib::llvm::llvm::LLVMIsConstant(align_bytes) != True {
1952+
// Use our own upcall (see issue 843), since the LLVM intrinsic can
1953+
// only handle constant alignments.
1954+
Call(cx, ccx.upcalls.memset, [dst_ptr, C_u8(0u), size, align]);
1955+
} else {
1956+
let memset = ccx.intrinsics.get("llvm.memset.p0i8.i32");
1957+
Call(cx, memset, [dst_ptr, C_u8(0u), size, align, C_bool(false)]);
1958+
}
1959+
cx
19601960
}
19611961

19621962
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)
39773977
let sp = cx.sp;
39783978
let llty = type_of(ccx, sp, t);
39793979
Store(bcx, C_null(llty), llptr);
3980+
bcx
39803981
} else {
3981-
let llsz = size_of(bcx, t);
3982+
let {bcx, val: llsz} = size_of(bcx, t);
39823983
// FIXME passing in the align here is correct, but causes issue #843
3983-
// let llalign = align_of(llsz.bcx, t);
3984-
bcx = call_bzero(llsz.bcx, llptr, llsz.val, C_int(ccx, 0)).bcx;
3984+
let {bcx, val: align} = align_of(bcx, t);
3985+
call_bzero(bcx, llptr, llsz, align)
39853986
}
3986-
ret bcx;
39873987
}
39883988

39893989
fn trans_stmt(cx: @block_ctxt, s: ast::stmt) -> @block_ctxt {

src/rt/rust_upcall.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,15 @@ upcall_shared_free(void* ptr) {
227227
UPCALL_SWITCH_STACK(&args, upcall_s_shared_free);
228228
}
229229

230+
/************************************************************************
231+
* Memset that, contrary to the llvm intrinsic, handles dynamic alignment
232+
*/
233+
234+
extern "C" CDECL void
235+
upcall_memset(void* ptr, char val, unsigned size, unsigned align) {
236+
memset(ptr, val, align_to(size, align));
237+
}
238+
230239
/**********************************************************************
231240
* Called to deep copy a type descriptor onto the exchange heap.
232241
* Used when sending closures. It's possible that we should have

src/rt/rustrt.def.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ upcall_rust_personality
7474
upcall_s_shared_malloc
7575
upcall_shared_malloc
7676
upcall_shared_free
77+
upcall_memset
7778
upcall_vec_grow
7879
upcall_vec_push
7980
upcall_call_shim_on_c_stack

0 commit comments

Comments
 (0)