Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
d2573828
R
Rust
项目概览
int
/
Rust
大约 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
d2573828
编写于
7月 17, 2012
作者:
E
Elliott Slaughter
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Moved malloc and free upcalls into rust runtime.
上级
de82a9be
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
123 addition
and
45 deletion
+123
-45
src/libcore/rt.rs
src/libcore/rt.rs
+35
-1
src/rt/rust_upcall.cpp
src/rt/rust_upcall.cpp
+32
-0
src/rustc/middle/trans/base.rs
src/rustc/middle/trans/base.rs
+34
-28
src/rustc/middle/trans/closure.rs
src/rustc/middle/trans/closure.rs
+17
-13
src/rustc/middle/trans/impl.rs
src/rustc/middle/trans/impl.rs
+1
-1
src/rustc/middle/trans/tvec.rs
src/rustc/middle/trans/tvec.rs
+2
-1
src/rustc/middle/trans/uniq.rs
src/rustc/middle/trans/uniq.rs
+2
-1
未找到文件。
src/libcore/rt.rs
浏览文件 @
d2573828
//! Runtime calls emitted by the compiler.
import
libc
::
c_char
;
import
libc
::
c_void
;
import
libc
::
size_t
;
import
libc
::
uintptr_t
;
type
rust_task
=
libc
::
c_void
;
type
rust_task
=
c_void
;
extern
mod
rustrt
{
#[rust_stack]
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
...
...
@@ -18,6 +32,26 @@ fn rt_fail(expr: *c_char, file: *c_char, line: size_t) {
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:
// mode: rust;
// fill-column: 78;
...
...
src/rt/rust_upcall.cpp
浏览文件 @
d2573828
...
...
@@ -170,6 +170,14 @@ upcall_exchange_malloc(type_desc *td, uintptr_t size) {
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
{
rust_task
*
task
;
void
*
ptr
;
...
...
@@ -189,6 +197,14 @@ upcall_exchange_free(void *ptr) {
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.
*/
...
...
@@ -230,6 +246,14 @@ upcall_malloc(type_desc *td, uintptr_t size) {
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.
*/
...
...
@@ -262,6 +286,14 @@ upcall_free(void* ptr) {
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
* use-after-free bugs. See maybe_validate_box() in trans.rs.
...
...
src/rustc/middle/trans/base.rs
浏览文件 @
d2573828
...
...
@@ -244,15 +244,13 @@ fn trans_foreign_call(cx: block, externs: hashmap<~str, ValueRef>,
fn
trans_free
(
cx
:
block
,
v
:
ValueRef
)
->
block
{
let
_
icx
=
cx
.insn_ctxt
(
~
"trans_free"
);
Call
(
cx
,
cx
.ccx
()
.upcalls.free
,
~
[
PointerCast
(
cx
,
v
,
T_ptr
(
T_i8
()))]);
cx
trans_rtcall
(
cx
,
~
"free"
,
~
[
PointerCast
(
cx
,
v
,
T_ptr
(
T_i8
()))],
ignore
)
}
fn
trans_unique_free
(
cx
:
block
,
v
:
ValueRef
)
->
block
{
let
_
icx
=
cx
.insn_ctxt
(
~
"trans_unique_free"
);
Call
(
cx
,
cx
.ccx
()
.upcalls.exchange_free
,
~
[
PointerCast
(
cx
,
v
,
T_ptr
(
T_i8
()))]);
ret
cx
;
trans_rtcall
(
cx
,
~
"exchange_free"
,
~
[
PointerCast
(
cx
,
v
,
T_ptr
(
T_i8
()))],
ignore
)
}
fn
umax
(
cx
:
block
,
a
:
ValueRef
,
b
:
ValueRef
)
->
ValueRef
{
...
...
@@ -356,15 +354,13 @@ fn opaque_box_body(bcx: block,
// malloc_raw_dyn: allocates a box to contain a given type, but with a
// potentially dynamic size.
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
ccx
=
bcx
.ccx
();
let
(
mk_fn
,
upcall
)
=
alt
heap
{
heap_shared
{
(
ty
::
mk_imm_box
,
ccx
.upcalls.malloc
)
}
heap_exchange
{
(
ty
::
mk_imm_uniq
,
ccx
.upcalls.exchange_malloc
)
}
let
(
mk_fn
,
rtcall
)
=
alt
heap
{
heap_shared
{
(
ty
::
mk_imm_box
,
~
"malloc"
)
}
heap_exchange
{
(
ty
::
mk_imm_uniq
,
~
"exchange_malloc"
)
}
};
// Grab the TypeRef type of box_ptr_ty.
...
...
@@ -376,37 +372,42 @@ fn malloc_raw_dyn(bcx: block, t: ty::t, heap: heap,
lazily_emit_all_tydesc_glue
(
ccx
,
static_ti
);
// Allocate space:
let
rval
=
Call
(
bcx
,
upcall
,
~
[
static_ti
.tydesc
,
size
]);
ret
PointerCast
(
bcx
,
rval
,
llty
);
let
tydesc
=
PointerCast
(
bcx
,
static_ti
.tydesc
,
T_ptr
(
T_i8
()));
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
// enough space for a box of that type. This includes a rust_opaque_box
// 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_general_dyn: usefully wraps malloc_raw_dyn; allocates a box,
// and pulls out the body
fn
malloc_general_dyn
(
bcx
:
block
,
t
:
ty
::
t
,
heap
:
heap
,
size
:
ValueRef
)
->
{
box
:
ValueRef
,
body
:
ValueRef
}
{
fn
malloc_general_dyn
(
bcx
:
block
,
t
:
ty
::
t
,
heap
:
heap
,
size
:
ValueRef
)
->
{
bcx
:
block
,
box
:
ValueRef
,
body
:
ValueRef
}
{
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
body
=
GEPi
(
bcx
,
non_gc_box
,
~
[
0u
,
abi
::
box_field_body
]);
ret
{
box
:
llbox
,
body
:
body
};
ret
{
b
cx
:
bcx
,
b
ox
:
llbox
,
body
:
body
};
}
fn
malloc_general
(
bcx
:
block
,
t
:
ty
::
t
,
heap
:
heap
)
->
{
box
:
ValueRef
,
body
:
ValueRef
}
{
fn
malloc_general
(
bcx
:
block
,
t
:
ty
::
t
,
heap
:
heap
)
->
{
bcx
:
block
,
box
:
ValueRef
,
body
:
ValueRef
}
{
malloc_general_dyn
(
bcx
,
t
,
heap
,
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
)
}
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
)
}
...
...
@@ -1464,7 +1465,7 @@ fn trans_boxed_expr(bcx: block, contents: @ast::expr,
t
:
ty
::
t
,
heap
:
heap
,
dest
:
dest
)
->
block
{
let
_
icx
=
bcx
.insn_ctxt
(
~
"trans_boxed_expr"
);
let
{
box
,
body
}
=
malloc_general
(
bcx
,
t
,
heap
);
let
{
b
cx
,
b
ox
,
body
}
=
malloc_general
(
bcx
,
t
,
heap
);
add_clean_free
(
bcx
,
box
,
heap
);
let
bcx
=
trans_expr_save_in
(
bcx
,
contents
,
body
);
revoke_clean
(
bcx
,
box
);
...
...
@@ -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_filename
=
PointerCast
(
bcx
,
V_filename
,
T_ptr
(
T_i8
()));
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
);
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
fty
=
if
did
.crate
==
ast
::
local_crate
{
ty
::
node_id_to_type
(
bcx
.ccx
()
.tcx
,
did
.node
)
...
...
@@ -3958,7 +3960,7 @@ fn trans_rtcall(bcx: block, name: ~str, args: ~[ValueRef]) -> block {
ret
trans_call_inner
(
bcx
,
none
,
fty
,
rty
,
|
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
)
...
...
@@ -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
// in some obscure place in LLVM if the user provides the wrong signature
// for an rtcall.
if
!
ccx
.rtcalls
.contains_key
(
~
"fail"
)
{
fail
~
"no definition for runtime call fail"
;
let
expected_rtcalls
=
~
[
~
"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
);
}
}
}
...
...
src/rustc/middle/trans/closure.rs
浏览文件 @
d2573828
...
...
@@ -138,7 +138,7 @@ fn mk_closure_tys(tcx: ty::ctxt,
fn
allocate_cbox
(
bcx
:
block
,
ck
:
ty
::
closure_kind
,
cdata_ty
:
ty
::
t
)
->
ValueRef
{
->
result
{
let
_
icx
=
bcx
.insn_ctxt
(
~
"closure::allocate_cbox"
);
let
ccx
=
bcx
.ccx
(),
tcx
=
ccx
.tcx
;
...
...
@@ -153,7 +153,7 @@ fn nuke_ref_count(bcx: block, llbox: ValueRef) {
}
// Allocate and initialize the box:
let
llbox
=
alt
ck
{
let
{
bcx
,
val
}
=
alt
ck
{
ty
::
ck_box
{
malloc_raw
(
bcx
,
cdata_ty
,
heap_shared
)
}
...
...
@@ -164,11 +164,11 @@ fn nuke_ref_count(bcx: block, llbox: ValueRef) {
let
cbox_ty
=
tuplify_box_ty
(
tcx
,
cdata_ty
);
let
llbox
=
base
::
alloc_ty
(
bcx
,
cbox_ty
);
nuke_ref_count
(
bcx
,
llbox
);
llbox
{
bcx
:
bcx
,
val
:
llbox
}
}
};
ret
llbox
;
ret
{
bcx
:
bcx
,
val
:
val
}
;
}
type
closure_result
=
{
...
...
@@ -191,7 +191,7 @@ fn store_environment(bcx: block,
let
cdata_ty
=
mk_closure_tys
(
tcx
,
bound_values
);
// 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
=
~
[];
// 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,
dest
:
dest
)
->
block
{
let
_
icx
=
bcx
.insn_ctxt
(
~
"closure::trans_expr_fn"
);
if
dest
==
ignore
{
ret
bcx
;
}
let
ccx
=
bcx
.ccx
()
,
bcx
=
bcx
;
let
ccx
=
bcx
.ccx
();
let
fty
=
node_id_type
(
bcx
,
id
);
let
llfnty
=
type_of_fn_from_ty
(
ccx
,
fty
);
let
sub_path
=
vec
::
append_one
(
bcx
.fcx.path
,
path_name
(
@~
"anon"
));
let
s
=
mangle_internal_name_by_path
(
ccx
,
sub_path
);
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
(
ccx
.tcx
,
id
,
proto
,
cap_clause
);
let
ret_handle
=
alt
is_loop_body
{
some
(
x
)
{
x
}
none
{
none
}
};
...
...
@@ -384,20 +384,21 @@ fn trans_expr_fn(bcx: block,
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_box
{
trans_closure_env
(
ty
::
ck_box
)
}
ast
::
proto_uniq
{
trans_closure_env
(
ty
::
ck_uniq
)
}
ast
::
proto_bare
{
trans_closure
(
ccx
,
sub_path
,
decl
,
body
,
llfn
,
no_self
,
none
,
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
);
ret
bcx
;
}
...
...
@@ -459,9 +460,12 @@ fn make_opaque_cbox_take_glue(
let
sz
=
Add
(
bcx
,
sz
,
shape
::
llsize_of
(
ccx
,
T_box_header
(
ccx
)));
// Allocate memory, update original ptr, and copy existing data
let
malloc
=
ccx
.upcalls.exchange_malloc
;
let
cbox_out
=
Call
(
bcx
,
malloc
,
~
[
tydesc
,
sz
]);
let
cbox_out
=
PointerCast
(
bcx
,
cbox_out
,
llopaquecboxty
);
let
malloc
=
~
"exchange_malloc"
;
let
opaque_tydesc
=
PointerCast
(
bcx
,
tydesc
,
T_ptr
(
T_i8
()));
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
);
Store
(
bcx
,
cbox_out
,
cboxptr
);
...
...
src/rustc/middle/trans/impl.rs
浏览文件 @
d2573828
...
...
@@ -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
);
}
let
ccx
=
bcx
.ccx
();
let
v_ty
=
expr_ty
(
bcx
,
val
);
let
{
box
:
llbox
,
body
:
body
}
=
malloc_boxed
(
bcx
,
v_ty
);
let
{
b
cx
:
bcx
,
b
ox
:
llbox
,
body
:
body
}
=
malloc_boxed
(
bcx
,
v_ty
);
add_clean_free
(
bcx
,
llbox
,
heap_shared
);
let
bcx
=
trans_expr_save_in
(
bcx
,
val
,
body
);
revoke_clean
(
bcx
,
llbox
);
...
...
src/rustc/middle/trans/tvec.rs
浏览文件 @
d2573828
...
...
@@ -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
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
,
alloc
,
GEPi
(
bcx
,
body
,
~
[
0u
,
abi
::
vec_elt_alloc
]));
ret
{
bcx
:
bcx
,
val
:
box
};
...
...
src/rustc/middle/trans/uniq.rs
浏览文件 @
d2573828
...
...
@@ -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
{
let
_
icx
=
bcx
.insn_ctxt
(
~
"uniq::duplicate"
);
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_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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录