提交 d2573828 编写于 作者: E Elliott Slaughter

Moved malloc and free upcalls into rust runtime.

上级 de82a9be
//! Runtime calls emitted by the compiler. //! Runtime calls emitted by the compiler.
import libc::c_char; import libc::c_char;
import libc::c_void;
import libc::size_t; import libc::size_t;
import libc::uintptr_t;
type rust_task = libc::c_void; type rust_task = c_void;
extern mod rustrt { extern mod rustrt {
#[rust_stack] #[rust_stack]
fn rust_upcall_fail(expr: *c_char, file: *c_char, line: size_t); fn rust_upcall_fail(expr: *c_char, file: *c_char, line: size_t);
#[rust_stack]
fn rust_upcall_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char;
#[rust_stack]
fn rust_upcall_exchange_free(ptr: *c_char);
#[rust_stack]
fn rust_upcall_malloc(td: *c_char, size: uintptr_t) -> *c_char;
#[rust_stack]
fn rust_upcall_free(ptr: *c_char);
} }
// FIXME (#2861): This needs both the attribute, and the name prefixed with // FIXME (#2861): This needs both the attribute, and the name prefixed with
...@@ -18,6 +32,26 @@ fn rt_fail(expr: *c_char, file: *c_char, line: size_t) { ...@@ -18,6 +32,26 @@ fn rt_fail(expr: *c_char, file: *c_char, line: size_t) {
rustrt::rust_upcall_fail(expr, file, line); rustrt::rust_upcall_fail(expr, file, line);
} }
#[rt(exchange_malloc)]
fn rt_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
ret rustrt::rust_upcall_exchange_malloc(td, size);
}
#[rt(exchange_free)]
fn rt_exchange_free(ptr: *c_char) {
rustrt::rust_upcall_exchange_free(ptr);
}
#[rt(malloc)]
fn rt_malloc(td: *c_char, size: uintptr_t) -> *c_char {
ret rustrt::rust_upcall_malloc(td, size);
}
#[rt(free)]
fn rt_free(ptr: *c_char) {
rustrt::rust_upcall_free(ptr);
}
// Local Variables: // Local Variables:
// mode: rust; // mode: rust;
// fill-column: 78; // fill-column: 78;
......
...@@ -170,6 +170,14 @@ upcall_exchange_malloc(type_desc *td, uintptr_t size) { ...@@ -170,6 +170,14 @@ upcall_exchange_malloc(type_desc *td, uintptr_t size) {
return args.retval; return args.retval;
} }
// FIXME (#2861): Alias used by libcore/rt.rs to avoid naming conflicts with
// autogenerated wrappers for upcall_exchange_malloc. Remove this when we
// fully move away away from the C upcall path.
extern "C" CDECL uintptr_t
rust_upcall_exchange_malloc(type_desc *td, uintptr_t size) {
return upcall_exchange_malloc(td, size);
}
struct s_exchange_free_args { struct s_exchange_free_args {
rust_task *task; rust_task *task;
void *ptr; void *ptr;
...@@ -189,6 +197,14 @@ upcall_exchange_free(void *ptr) { ...@@ -189,6 +197,14 @@ upcall_exchange_free(void *ptr) {
UPCALL_SWITCH_STACK(task, &args, upcall_s_exchange_free); UPCALL_SWITCH_STACK(task, &args, upcall_s_exchange_free);
} }
// FIXME (#2861): Alias used by libcore/rt.rs to avoid naming conflicts with
// autogenerated wrappers for upcall_exchange_free. Remove this when we fully
// move away away from the C upcall path.
extern "C" CDECL void
rust_upcall_exchange_free(void *ptr) {
return upcall_exchange_free(ptr);
}
/********************************************************************** /**********************************************************************
* Allocate an object in the task-local heap. * Allocate an object in the task-local heap.
*/ */
...@@ -230,6 +246,14 @@ upcall_malloc(type_desc *td, uintptr_t size) { ...@@ -230,6 +246,14 @@ upcall_malloc(type_desc *td, uintptr_t size) {
return args.retval; return args.retval;
} }
// FIXME (#2861): Alias used by libcore/rt.rs to avoid naming conflicts with
// autogenerated wrappers for upcall_malloc. Remove this when we fully move
// away away from the C upcall path.
extern "C" CDECL uintptr_t
rust_upcall_malloc(type_desc *td, uintptr_t size) {
return upcall_malloc(td, size);
}
/********************************************************************** /**********************************************************************
* Called whenever an object in the task-local heap is freed. * Called whenever an object in the task-local heap is freed.
*/ */
...@@ -262,6 +286,14 @@ upcall_free(void* ptr) { ...@@ -262,6 +286,14 @@ upcall_free(void* ptr) {
UPCALL_SWITCH_STACK(task, &args, upcall_s_free); UPCALL_SWITCH_STACK(task, &args, upcall_s_free);
} }
// FIXME (#2861): Alias used by libcore/rt.rs to avoid naming conflicts with
// autogenerated wrappers for upcall_free. Remove this when we fully move away
// away from the C upcall path.
extern "C" CDECL void
rust_upcall_free(void* ptr) {
upcall_free(ptr);
}
/********************************************************************** /**********************************************************************
* Sanity checks on boxes, insert when debugging possible * Sanity checks on boxes, insert when debugging possible
* use-after-free bugs. See maybe_validate_box() in trans.rs. * use-after-free bugs. See maybe_validate_box() in trans.rs.
......
...@@ -244,15 +244,13 @@ fn trans_foreign_call(cx: block, externs: hashmap<~str, ValueRef>, ...@@ -244,15 +244,13 @@ fn trans_foreign_call(cx: block, externs: hashmap<~str, ValueRef>,
fn trans_free(cx: block, v: ValueRef) -> block { fn trans_free(cx: block, v: ValueRef) -> block {
let _icx = cx.insn_ctxt(~"trans_free"); let _icx = cx.insn_ctxt(~"trans_free");
Call(cx, cx.ccx().upcalls.free, ~[PointerCast(cx, v, T_ptr(T_i8()))]); trans_rtcall(cx, ~"free", ~[PointerCast(cx, v, T_ptr(T_i8()))], ignore)
cx
} }
fn trans_unique_free(cx: block, v: ValueRef) -> block { fn trans_unique_free(cx: block, v: ValueRef) -> block {
let _icx = cx.insn_ctxt(~"trans_unique_free"); let _icx = cx.insn_ctxt(~"trans_unique_free");
Call(cx, cx.ccx().upcalls.exchange_free, trans_rtcall(cx, ~"exchange_free", ~[PointerCast(cx, v, T_ptr(T_i8()))],
~[PointerCast(cx, v, T_ptr(T_i8()))]); ignore)
ret cx;
} }
fn umax(cx: block, a: ValueRef, b: ValueRef) -> ValueRef { fn umax(cx: block, a: ValueRef, b: ValueRef) -> ValueRef {
...@@ -356,15 +354,13 @@ fn opaque_box_body(bcx: block, ...@@ -356,15 +354,13 @@ fn opaque_box_body(bcx: block,
// malloc_raw_dyn: allocates a box to contain a given type, but with a // malloc_raw_dyn: allocates a box to contain a given type, but with a
// potentially dynamic size. // potentially dynamic size.
fn malloc_raw_dyn(bcx: block, t: ty::t, heap: heap, fn malloc_raw_dyn(bcx: block, t: ty::t, heap: heap,
size: ValueRef) -> ValueRef { size: ValueRef) -> result {
let _icx = bcx.insn_ctxt(~"malloc_raw"); let _icx = bcx.insn_ctxt(~"malloc_raw");
let ccx = bcx.ccx(); let ccx = bcx.ccx();
let (mk_fn, upcall) = alt heap { let (mk_fn, rtcall) = alt heap {
heap_shared { (ty::mk_imm_box, ccx.upcalls.malloc) } heap_shared { (ty::mk_imm_box, ~"malloc") }
heap_exchange { heap_exchange { (ty::mk_imm_uniq, ~"exchange_malloc") }
(ty::mk_imm_uniq, ccx.upcalls.exchange_malloc )
}
}; };
// Grab the TypeRef type of box_ptr_ty. // Grab the TypeRef type of box_ptr_ty.
...@@ -376,37 +372,42 @@ fn malloc_raw_dyn(bcx: block, t: ty::t, heap: heap, ...@@ -376,37 +372,42 @@ fn malloc_raw_dyn(bcx: block, t: ty::t, heap: heap,
lazily_emit_all_tydesc_glue(ccx, static_ti); lazily_emit_all_tydesc_glue(ccx, static_ti);
// Allocate space: // Allocate space:
let rval = Call(bcx, upcall, ~[static_ti.tydesc, size]); let tydesc = PointerCast(bcx, static_ti.tydesc, T_ptr(T_i8()));
ret PointerCast(bcx, rval, llty); let rval = alloca_zeroed(bcx, T_ptr(T_i8()));
let bcx = trans_rtcall(bcx, rtcall, ~[tydesc, size], save_in(rval));
let retval = {bcx: bcx, val: PointerCast(bcx, Load(bcx, rval), llty)};
ret retval;
} }
// malloc_raw: expects an unboxed type and returns a pointer to // malloc_raw: expects an unboxed type and returns a pointer to
// enough space for a box of that type. This includes a rust_opaque_box // enough space for a box of that type. This includes a rust_opaque_box
// header. // header.
fn malloc_raw(bcx: block, t: ty::t, heap: heap) -> ValueRef { fn malloc_raw(bcx: block, t: ty::t, heap: heap) -> result {
malloc_raw_dyn(bcx, t, heap, llsize_of(bcx.ccx(), type_of(bcx.ccx(), t))) malloc_raw_dyn(bcx, t, heap, llsize_of(bcx.ccx(), type_of(bcx.ccx(), t)))
} }
// malloc_general_dyn: usefully wraps malloc_raw_dyn; allocates a box, // malloc_general_dyn: usefully wraps malloc_raw_dyn; allocates a box,
// and pulls out the body // and pulls out the body
fn malloc_general_dyn(bcx: block, t: ty::t, heap: heap, size: ValueRef) -> fn malloc_general_dyn(bcx: block, t: ty::t, heap: heap, size: ValueRef)
{box: ValueRef, body: ValueRef} { -> {bcx: block, box: ValueRef, body: ValueRef} {
let _icx = bcx.insn_ctxt(~"malloc_general"); let _icx = bcx.insn_ctxt(~"malloc_general");
let llbox = malloc_raw_dyn(bcx, t, heap, size); let {bcx: bcx, val: llbox} = malloc_raw_dyn(bcx, t, heap, size);
let non_gc_box = non_gc_box_cast(bcx, llbox); let non_gc_box = non_gc_box_cast(bcx, llbox);
let body = GEPi(bcx, non_gc_box, ~[0u, abi::box_field_body]); let body = GEPi(bcx, non_gc_box, ~[0u, abi::box_field_body]);
ret {box: llbox, body: body}; ret {bcx: bcx, box: llbox, body: body};
} }
fn malloc_general(bcx: block, t: ty::t, heap: heap) -> fn malloc_general(bcx: block, t: ty::t, heap: heap)
{box: ValueRef, body: ValueRef} { -> {bcx: block, box: ValueRef, body: ValueRef} {
malloc_general_dyn(bcx, t, heap, malloc_general_dyn(bcx, t, heap,
llsize_of(bcx.ccx(), type_of(bcx.ccx(), t))) llsize_of(bcx.ccx(), type_of(bcx.ccx(), t)))
} }
fn malloc_boxed(bcx: block, t: ty::t) -> {box: ValueRef, body: ValueRef} { fn malloc_boxed(bcx: block, t: ty::t)
-> {bcx: block, box: ValueRef, body: ValueRef} {
malloc_general(bcx, t, heap_shared) malloc_general(bcx, t, heap_shared)
} }
fn malloc_unique(bcx: block, t: ty::t) -> {box: ValueRef, body: ValueRef} { fn malloc_unique(bcx: block, t: ty::t)
-> {bcx: block, box: ValueRef, body: ValueRef} {
malloc_general(bcx, t, heap_exchange) malloc_general(bcx, t, heap_exchange)
} }
...@@ -1464,7 +1465,7 @@ fn trans_boxed_expr(bcx: block, contents: @ast::expr, ...@@ -1464,7 +1465,7 @@ fn trans_boxed_expr(bcx: block, contents: @ast::expr,
t: ty::t, heap: heap, t: ty::t, heap: heap,
dest: dest) -> block { dest: dest) -> block {
let _icx = bcx.insn_ctxt(~"trans_boxed_expr"); let _icx = bcx.insn_ctxt(~"trans_boxed_expr");
let {box, body} = malloc_general(bcx, t, heap); let {bcx, box, body} = malloc_general(bcx, t, heap);
add_clean_free(bcx, box, heap); add_clean_free(bcx, box, heap);
let bcx = trans_expr_save_in(bcx, contents, body); let bcx = trans_expr_save_in(bcx, contents, body);
revoke_clean(bcx, box); revoke_clean(bcx, box);
...@@ -3942,12 +3943,13 @@ fn trans_fail_value(bcx: block, sp_opt: option<span>, ...@@ -3942,12 +3943,13 @@ fn trans_fail_value(bcx: block, sp_opt: option<span>,
let V_str = PointerCast(bcx, V_fail_str, T_ptr(T_i8())); let V_str = PointerCast(bcx, V_fail_str, T_ptr(T_i8()));
let V_filename = PointerCast(bcx, V_filename, T_ptr(T_i8())); let V_filename = PointerCast(bcx, V_filename, T_ptr(T_i8()));
let args = ~[V_str, V_filename, C_int(ccx, V_line)]; let args = ~[V_str, V_filename, C_int(ccx, V_line)];
let bcx = trans_rtcall(bcx, ~"fail", args); let bcx = trans_rtcall(bcx, ~"fail", args, ignore);
Unreachable(bcx); Unreachable(bcx);
ret bcx; ret bcx;
} }
fn trans_rtcall(bcx: block, name: ~str, args: ~[ValueRef]) -> block { fn trans_rtcall(bcx: block, name: ~str, args: ~[ValueRef], dest: dest)
-> block {
let did = bcx.ccx().rtcalls[name]; let did = bcx.ccx().rtcalls[name];
let fty = if did.crate == ast::local_crate { let fty = if did.crate == ast::local_crate {
ty::node_id_to_type(bcx.ccx().tcx, did.node) ty::node_id_to_type(bcx.ccx().tcx, did.node)
...@@ -3958,7 +3960,7 @@ fn trans_rtcall(bcx: block, name: ~str, args: ~[ValueRef]) -> block { ...@@ -3958,7 +3960,7 @@ fn trans_rtcall(bcx: block, name: ~str, args: ~[ValueRef]) -> block {
ret trans_call_inner( ret trans_call_inner(
bcx, none, fty, rty, bcx, none, fty, rty,
|bcx| lval_static_fn_inner(bcx, did, 0, ~[], none), |bcx| lval_static_fn_inner(bcx, did, 0, ~[], none),
arg_vals(args), ignore); arg_vals(args), dest);
} }
fn trans_break_cont(bcx: block, to_end: bool) fn trans_break_cont(bcx: block, to_end: bool)
...@@ -5396,8 +5398,12 @@ fn gather_rtcalls(ccx: @crate_ctxt, crate: @ast::crate) { ...@@ -5396,8 +5398,12 @@ fn gather_rtcalls(ccx: @crate_ctxt, crate: @ast::crate) {
// supported. Also probably want to check type signature so we don't crash // supported. Also probably want to check type signature so we don't crash
// in some obscure place in LLVM if the user provides the wrong signature // in some obscure place in LLVM if the user provides the wrong signature
// for an rtcall. // for an rtcall.
if !ccx.rtcalls.contains_key(~"fail") { let expected_rtcalls =
fail ~"no definition for runtime call fail"; ~[~"exchange_free", ~"exchange_malloc", ~"fail", ~"free", ~"malloc"];
for vec::each(expected_rtcalls) |name| {
if !ccx.rtcalls.contains_key(name) {
fail #fmt("no definition for runtime call %s", name);
}
} }
} }
......
...@@ -138,7 +138,7 @@ fn mk_closure_tys(tcx: ty::ctxt, ...@@ -138,7 +138,7 @@ fn mk_closure_tys(tcx: ty::ctxt,
fn allocate_cbox(bcx: block, fn allocate_cbox(bcx: block,
ck: ty::closure_kind, ck: ty::closure_kind,
cdata_ty: ty::t) cdata_ty: ty::t)
-> ValueRef { -> result {
let _icx = bcx.insn_ctxt(~"closure::allocate_cbox"); let _icx = bcx.insn_ctxt(~"closure::allocate_cbox");
let ccx = bcx.ccx(), tcx = ccx.tcx; let ccx = bcx.ccx(), tcx = ccx.tcx;
...@@ -153,7 +153,7 @@ fn nuke_ref_count(bcx: block, llbox: ValueRef) { ...@@ -153,7 +153,7 @@ fn nuke_ref_count(bcx: block, llbox: ValueRef) {
} }
// Allocate and initialize the box: // Allocate and initialize the box:
let llbox = alt ck { let {bcx, val} = alt ck {
ty::ck_box { ty::ck_box {
malloc_raw(bcx, cdata_ty, heap_shared) malloc_raw(bcx, cdata_ty, heap_shared)
} }
...@@ -164,11 +164,11 @@ fn nuke_ref_count(bcx: block, llbox: ValueRef) { ...@@ -164,11 +164,11 @@ fn nuke_ref_count(bcx: block, llbox: ValueRef) {
let cbox_ty = tuplify_box_ty(tcx, cdata_ty); let cbox_ty = tuplify_box_ty(tcx, cdata_ty);
let llbox = base::alloc_ty(bcx, cbox_ty); let llbox = base::alloc_ty(bcx, cbox_ty);
nuke_ref_count(bcx, llbox); nuke_ref_count(bcx, llbox);
llbox {bcx: bcx, val: llbox}
} }
}; };
ret llbox; ret {bcx: bcx, val: val};
} }
type closure_result = { type closure_result = {
...@@ -191,7 +191,7 @@ fn store_environment(bcx: block, ...@@ -191,7 +191,7 @@ fn store_environment(bcx: block,
let cdata_ty = mk_closure_tys(tcx, bound_values); let cdata_ty = mk_closure_tys(tcx, bound_values);
// allocate closure in the heap // allocate closure in the heap
let llbox = allocate_cbox(bcx, ck, cdata_ty); let {bcx: bcx, val: llbox} = allocate_cbox(bcx, ck, cdata_ty);
let mut temp_cleanups = ~[]; let mut temp_cleanups = ~[];
// cbox_ty has the form of a tuple: (a, b, c) we want a ptr to a // cbox_ty has the form of a tuple: (a, b, c) we want a ptr to a
...@@ -362,14 +362,14 @@ fn trans_expr_fn(bcx: block, ...@@ -362,14 +362,14 @@ fn trans_expr_fn(bcx: block,
dest: dest) -> block { dest: dest) -> block {
let _icx = bcx.insn_ctxt(~"closure::trans_expr_fn"); let _icx = bcx.insn_ctxt(~"closure::trans_expr_fn");
if dest == ignore { ret bcx; } if dest == ignore { ret bcx; }
let ccx = bcx.ccx(), bcx = bcx; let ccx = bcx.ccx();
let fty = node_id_type(bcx, id); let fty = node_id_type(bcx, id);
let llfnty = type_of_fn_from_ty(ccx, fty); let llfnty = type_of_fn_from_ty(ccx, fty);
let sub_path = vec::append_one(bcx.fcx.path, path_name(@~"anon")); let sub_path = vec::append_one(bcx.fcx.path, path_name(@~"anon"));
let s = mangle_internal_name_by_path(ccx, sub_path); let s = mangle_internal_name_by_path(ccx, sub_path);
let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty); let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty);
let trans_closure_env = fn@(ck: ty::closure_kind) -> ValueRef { let trans_closure_env = fn@(ck: ty::closure_kind) -> result {
let cap_vars = capture::compute_capture_vars( let cap_vars = capture::compute_capture_vars(
ccx.tcx, id, proto, cap_clause); ccx.tcx, id, proto, cap_clause);
let ret_handle = alt is_loop_body { some(x) { x } none { none } }; let ret_handle = alt is_loop_body { some(x) { x } none { none } };
...@@ -384,20 +384,21 @@ fn trans_expr_fn(bcx: block, ...@@ -384,20 +384,21 @@ fn trans_expr_fn(bcx: block,
Store(bcx, C_bool(true), bcx.fcx.llretptr); Store(bcx, C_bool(true), bcx.fcx.llretptr);
} }
}); });
llbox {bcx: bcx, val: llbox}
}; };
let closure = alt proto { let {bcx: bcx, val: closure} = alt proto {
ast::proto_any | ast::proto_block { trans_closure_env(ty::ck_block) } ast::proto_any | ast::proto_block { trans_closure_env(ty::ck_block) }
ast::proto_box { trans_closure_env(ty::ck_box) } ast::proto_box { trans_closure_env(ty::ck_box) }
ast::proto_uniq { trans_closure_env(ty::ck_uniq) } ast::proto_uniq { trans_closure_env(ty::ck_uniq) }
ast::proto_bare { ast::proto_bare {
trans_closure(ccx, sub_path, decl, body, llfn, no_self, none, trans_closure(ccx, sub_path, decl, body, llfn, no_self, none,
id, |_fcx| { }, |_bcx| { }); id, |_fcx| { }, |_bcx| { });
C_null(T_opaque_box_ptr(ccx)) {bcx: bcx, val: C_null(T_opaque_box_ptr(ccx))}
} }
}; };
fill_fn_pair(bcx, get_dest_addr(dest), llfn, closure); fill_fn_pair(bcx, get_dest_addr(dest), llfn, closure);
ret bcx; ret bcx;
} }
...@@ -459,9 +460,12 @@ fn make_opaque_cbox_take_glue( ...@@ -459,9 +460,12 @@ fn make_opaque_cbox_take_glue(
let sz = Add(bcx, sz, shape::llsize_of(ccx, T_box_header(ccx))); let sz = Add(bcx, sz, shape::llsize_of(ccx, T_box_header(ccx)));
// Allocate memory, update original ptr, and copy existing data // Allocate memory, update original ptr, and copy existing data
let malloc = ccx.upcalls.exchange_malloc; let malloc = ~"exchange_malloc";
let cbox_out = Call(bcx, malloc, ~[tydesc, sz]); let opaque_tydesc = PointerCast(bcx, tydesc, T_ptr(T_i8()));
let cbox_out = PointerCast(bcx, cbox_out, llopaquecboxty); let rval = alloca_zeroed(bcx, T_ptr(T_i8()));
let bcx = trans_rtcall(bcx, malloc, ~[opaque_tydesc, sz],
save_in(rval));
let cbox_out = PointerCast(bcx, Load(bcx, rval), llopaquecboxty);
call_memmove(bcx, cbox_out, cbox_in, sz); call_memmove(bcx, cbox_out, cbox_in, sz);
Store(bcx, cbox_out, cboxptr); Store(bcx, cbox_out, cboxptr);
......
...@@ -288,7 +288,7 @@ fn trans_cast(bcx: block, val: @ast::expr, id: ast::node_id, dest: dest) ...@@ -288,7 +288,7 @@ fn trans_cast(bcx: block, val: @ast::expr, id: ast::node_id, dest: dest)
if dest == ignore { ret trans_expr(bcx, val, ignore); } if dest == ignore { ret trans_expr(bcx, val, ignore); }
let ccx = bcx.ccx(); let ccx = bcx.ccx();
let v_ty = expr_ty(bcx, val); let v_ty = expr_ty(bcx, val);
let {box: llbox, body: body} = malloc_boxed(bcx, v_ty); let {bcx: bcx, box: llbox, body: body} = malloc_boxed(bcx, v_ty);
add_clean_free(bcx, llbox, heap_shared); add_clean_free(bcx, llbox, heap_shared);
let bcx = trans_expr_save_in(bcx, val, body); let bcx = trans_expr_save_in(bcx, val, body);
revoke_clean(bcx, llbox); revoke_clean(bcx, llbox);
......
...@@ -68,7 +68,8 @@ fn alloc_raw(bcx: block, unit_ty: ty::t, ...@@ -68,7 +68,8 @@ fn alloc_raw(bcx: block, unit_ty: ty::t,
let vecbodyty = ty::mk_mut_unboxed_vec(bcx.tcx(), unit_ty); let vecbodyty = ty::mk_mut_unboxed_vec(bcx.tcx(), unit_ty);
let vecsize = Add(bcx, alloc, llsize_of(ccx, ccx.opaque_vec_type)); let vecsize = Add(bcx, alloc, llsize_of(ccx, ccx.opaque_vec_type));
let {box, body} = base::malloc_general_dyn(bcx, vecbodyty, heap, vecsize); let {bcx, box, body} =
base::malloc_general_dyn(bcx, vecbodyty, heap, vecsize);
Store(bcx, fill, GEPi(bcx, body, ~[0u, abi::vec_elt_fill])); Store(bcx, fill, GEPi(bcx, body, ~[0u, abi::vec_elt_fill]));
Store(bcx, alloc, GEPi(bcx, body, ~[0u, abi::vec_elt_alloc])); Store(bcx, alloc, GEPi(bcx, body, ~[0u, abi::vec_elt_alloc]));
ret {bcx: bcx, val: box}; ret {bcx: bcx, val: box};
......
...@@ -34,7 +34,8 @@ fn autoderef(bcx: block, v: ValueRef, t: ty::t) -> {v: ValueRef, t: ty::t} { ...@@ -34,7 +34,8 @@ fn autoderef(bcx: block, v: ValueRef, t: ty::t) -> {v: ValueRef, t: ty::t} {
fn duplicate(bcx: block, v: ValueRef, t: ty::t) -> result { fn duplicate(bcx: block, v: ValueRef, t: ty::t) -> result {
let _icx = bcx.insn_ctxt(~"uniq::duplicate"); let _icx = bcx.insn_ctxt(~"uniq::duplicate");
let content_ty = content_ty(t); let content_ty = content_ty(t);
let {box: dst_box, body: dst_body} = malloc_unique(bcx, content_ty); let {bcx: bcx, box: dst_box, body: dst_body} =
malloc_unique(bcx, content_ty);
let src_box = v; let src_box = v;
let src_body = opaque_box_body(bcx, content_ty, src_box); let src_body = opaque_box_body(bcx, content_ty, src_box);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册