Skip to content

Commit bc21965

Browse files
committed
Use homebrew memcpy, not llvm intrinsic. Can't run the latter on a rust stack.
1 parent 156e1b3 commit bc21965

File tree

2 files changed

+66
-32
lines changed

2 files changed

+66
-32
lines changed

src/comp/back/abi.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ const int worst_case_glue_call_args = 7;
5959

6060
const int n_upcall_glues = 7;
6161

62+
fn memcpy_glue_name() -> str {
63+
ret "rust_memcpy_glue";
64+
}
65+
6266
fn upcall_glue_name(int n) -> str {
6367
ret "rust_upcall_" + util.common.istr(n);
6468
}
@@ -75,6 +79,10 @@ fn exit_task_glue_name() -> str {
7579
ret "rust_exit_task_glue";
7680
}
7781

82+
fn no_op_type_glue_name() -> str {
83+
ret "rust_no_op_type_glue";
84+
}
85+
7886
//
7987
// Local Variables:
8088
// mode: rust

src/comp/middle/trans.rs

Lines changed: 58 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ type glue_fns = rec(ValueRef activate_glue,
5151
ValueRef yield_glue,
5252
ValueRef exit_task_glue,
5353
vec[ValueRef] upcall_glues,
54-
ValueRef no_op_type_glue);
54+
ValueRef no_op_type_glue,
55+
ValueRef memcpy_glue);
5556

5657
tag arity { nullary; n_ary; }
5758
type tag_info = rec(type_handle th,
@@ -1237,26 +1238,15 @@ fn drop_ty(@block_ctxt cx,
12371238
ret res(cx, C_nil());
12381239
}
12391240

1240-
fn build_memcpy(@block_ctxt cx,
1241-
ValueRef dst,
1242-
ValueRef src,
1243-
ValueRef n_bytes) -> result {
1244-
// FIXME: switch to the 64-bit variant when on such a platform.
1245-
check (cx.fcx.ccx.intrinsics.contains_key("llvm.memcpy.p0i8.p0i8.i32"));
1246-
auto memcpy = cx.fcx.ccx.intrinsics.get("llvm.memcpy.p0i8.p0i8.i32");
1241+
fn call_memcpy(@block_ctxt cx,
1242+
ValueRef dst,
1243+
ValueRef src,
1244+
ValueRef n_bytes) -> result {
12471245
auto src_ptr = cx.build.PointerCast(src, T_ptr(T_i8()));
12481246
auto dst_ptr = cx.build.PointerCast(dst, T_ptr(T_i8()));
1249-
auto size = cx.build.IntCast(n_bytes, T_i32());
1250-
auto align = cx.build.IntCast(C_int(1), T_i32());
1251-
1252-
// FIXME: align seems like it should be
1253-
// lib.llvm.llvm.LLVMAlignOf(llty);
1254-
// but this makes it upset because it's not a constant.
1255-
1256-
auto volatile = C_integral(0, T_i1());
1257-
ret res(cx, cx.build.Call(memcpy,
1258-
vec(dst_ptr, src_ptr,
1259-
size, align, volatile)));
1247+
auto size = cx.build.IntCast(n_bytes, T_int());
1248+
ret res(cx, cx.build.FastCall(cx.fcx.ccx.glues.memcpy_glue,
1249+
vec(dst_ptr, src_ptr, size)));
12601250
}
12611251

12621252
fn memcpy_ty(@block_ctxt cx,
@@ -1266,7 +1256,7 @@ fn memcpy_ty(@block_ctxt cx,
12661256
if (ty.type_has_dynamic_size(t)) {
12671257
auto llszptr = field_of_tydesc(cx, t, abi.tydesc_field_size);
12681258
auto llsz = cx.build.Load(llszptr);
1269-
ret build_memcpy(cx, dst, src, llsz);
1259+
ret call_memcpy(cx, dst, src, llsz);
12701260

12711261
} else {
12721262
ret res(cx, cx.build.Store(cx.build.Load(src), dst));
@@ -3624,21 +3614,11 @@ fn trans_main_fn(@crate_ctxt cx, ValueRef llcrate) {
36243614
fn declare_intrinsics(ModuleRef llmod) -> hashmap[str,ValueRef] {
36253615

36263616
let vec[TypeRef] T_trap_args = vec();
3627-
let vec[TypeRef] T_memcpy32_args = vec(T_ptr(T_i8()), T_ptr(T_i8()),
3628-
T_i32(), T_i32(), T_i1());
3629-
let vec[TypeRef] T_memcpy64_args = vec(T_ptr(T_i8()), T_ptr(T_i8()),
3630-
T_i32(), T_i32(), T_i1());
36313617
auto trap = decl_cdecl_fn(llmod, "llvm.trap",
36323618
T_fn(T_trap_args, T_void()));
3633-
auto memcpy32 = decl_cdecl_fn(llmod, "llvm.memcpy.p0i8.p0i8.i32",
3634-
T_fn(T_memcpy32_args, T_void()));
3635-
auto memcpy64 = decl_cdecl_fn(llmod, "llvm.memcpy.p0i8.p0i8.i64",
3636-
T_fn(T_memcpy64_args, T_void()));
36373619

36383620
auto intrinsics = new_str_hash[ValueRef]();
36393621
intrinsics.insert("llvm.trap", trap);
3640-
intrinsics.insert("llvm.memcpy.p0i8.p0i8.i32", memcpy32);
3641-
intrinsics.insert("llvm.memcpy.p0i8.p0i8.i64", memcpy64);
36423622
ret intrinsics;
36433623
}
36443624

@@ -3652,13 +3632,58 @@ fn check_module(ModuleRef llmod) {
36523632

36533633
fn make_no_op_type_glue(ModuleRef llmod) -> ValueRef {
36543634
auto ty = T_fn(vec(T_taskptr(), T_ptr(T_i8())), T_void());
3655-
auto fun = decl_fastcall_fn(llmod, "_rust_no_op_type_glue", ty);
3635+
auto fun = decl_fastcall_fn(llmod, abi.no_op_type_glue_name(), ty);
36563636
auto bb_name = _str.buf("_rust_no_op_type_glue_bb");
36573637
auto llbb = llvm.LLVMAppendBasicBlock(fun, bb_name);
36583638
new_builder(llbb).RetVoid();
36593639
ret fun;
36603640
}
36613641

3642+
fn make_memcpy_glue(ModuleRef llmod) -> ValueRef {
3643+
3644+
// We're not using the LLVM memcpy intrinsic. It appears to call through
3645+
// to the platform memcpy in some cases, which is not terribly safe to run
3646+
// on a rust stack.
3647+
3648+
auto p8 = T_ptr(T_i8());
3649+
3650+
auto ty = T_fn(vec(p8, p8, T_int()), T_void());
3651+
auto fun = decl_fastcall_fn(llmod, abi.memcpy_glue_name(), ty);
3652+
3653+
auto initbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("init"));
3654+
auto hdrbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("hdr"));
3655+
auto loopbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("loop"));
3656+
auto endbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("end"));
3657+
3658+
auto dst = llvm.LLVMGetParam(fun, 0u);
3659+
auto src = llvm.LLVMGetParam(fun, 1u);
3660+
auto count = llvm.LLVMGetParam(fun, 2u);
3661+
3662+
// Init block.
3663+
auto ib = new_builder(initbb);
3664+
auto ip = ib.Alloca(T_int());
3665+
ib.Store(C_int(0), ip);
3666+
ib.Br(hdrbb);
3667+
3668+
// Loop-header block
3669+
auto hb = new_builder(hdrbb);
3670+
auto i = hb.Load(ip);
3671+
hb.CondBr(hb.ICmp(lib.llvm.LLVMIntEQ, count, i), endbb, loopbb);
3672+
3673+
// Loop-body block
3674+
auto lb = new_builder(loopbb);
3675+
i = lb.Load(ip);
3676+
lb.Store(lb.Load(lb.GEP(src, vec(i))),
3677+
lb.GEP(dst, vec(i)));
3678+
lb.Store(lb.Add(i, C_int(1)), ip);
3679+
lb.Br(hdrbb);
3680+
3681+
// End block
3682+
auto eb = new_builder(endbb);
3683+
eb.RetVoid();
3684+
ret fun;
3685+
}
3686+
36623687
fn make_glues(ModuleRef llmod) -> @glue_fns {
36633688
ret @rec(activate_glue = decl_glue(llmod, abi.activate_glue_name()),
36643689
yield_glue = decl_glue(llmod, abi.yield_glue_name()),
@@ -3678,7 +3703,8 @@ fn make_glues(ModuleRef llmod) -> @glue_fns {
36783703
upcall_glues =
36793704
_vec.init_fn[ValueRef](bind decl_upcall(llmod, _),
36803705
abi.n_upcall_glues as uint),
3681-
no_op_type_glue = make_no_op_type_glue(llmod));
3706+
no_op_type_glue = make_no_op_type_glue(llmod),
3707+
memcpy_glue = make_memcpy_glue(llmod));
36823708
}
36833709

36843710
fn trans_crate(session.session sess, @ast.crate crate, str output,

0 commit comments

Comments
 (0)