Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
afc2dcd0
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,发现更多精彩内容 >>
提交
afc2dcd0
编写于
12月 20, 2016
作者:
M
Mark Simulacrum
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Make drop glue for unsized value pass two arguments instead of *(data, meta)
上级
1b38776c
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
137 addition
and
226 deletion
+137
-226
src/librustc_llvm/lib.rs
src/librustc_llvm/lib.rs
+2
-1
src/librustc_trans/callee.rs
src/librustc_trans/callee.rs
+2
-1
src/librustc_trans/cleanup.rs
src/librustc_trans/cleanup.rs
+6
-10
src/librustc_trans/glue.rs
src/librustc_trans/glue.rs
+87
-124
src/librustc_trans/mir/block.rs
src/librustc_trans/mir/block.rs
+36
-85
src/librustc_trans/trans_item.rs
src/librustc_trans/trans_item.rs
+4
-5
未找到文件。
src/librustc_llvm/lib.rs
浏览文件 @
afc2dcd0
...
...
@@ -270,7 +270,8 @@ pub fn mk_section_iter(llof: ObjectFileRef) -> SectionIter {
/// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
pub
fn
get_param
(
llfn
:
ValueRef
,
index
:
c_uint
)
->
ValueRef
{
unsafe
{
assert
!
(
index
<
LLVMCountParams
(
llfn
));
assert
!
(
index
<
LLVMCountParams
(
llfn
),
"out of bounds argument access: {} out of {} arguments"
,
index
,
LLVMCountParams
(
llfn
));
LLVMGetParam
(
llfn
,
index
)
}
}
...
...
src/librustc_trans/callee.rs
浏览文件 @
afc2dcd0
...
...
@@ -27,6 +27,7 @@
use
common
::{
self
,
CrateContext
,
FunctionContext
,
SharedCrateContext
};
use
adt
::
MaybeSizedValue
;
use
consts
;
use
declare
;
use
value
::
Value
;
...
...
@@ -364,7 +365,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
// Call the by-ref closure body with `self` in a cleanup scope,
// to drop `self` when the body returns, or in case it unwinds.
let
self_scope
=
fcx
.schedule_drop_mem
(
llenv
,
closure_ty
);
let
self_scope
=
fcx
.schedule_drop_mem
(
MaybeSizedValue
::
sized
(
llenv
)
,
closure_ty
);
let
llfn
=
callee
.reify
(
bcx
.ccx
);
let
llret
;
...
...
src/librustc_trans/cleanup.rs
浏览文件 @
afc2dcd0
...
...
@@ -18,12 +18,12 @@
//! corresponds to a normal exit from a block (for example, an expression
//! completing evaluation successfully without panic).
use
llvm
::
{
BasicBlockRef
,
ValueRef
}
;
use
llvm
::
BasicBlockRef
;
use
base
;
use
adt
::
MaybeSizedValue
;
use
common
::{
BlockAndBuilder
,
FunctionContext
,
Funclet
};
use
glue
;
use
type_
::
Type
;
use
value
::
Value
;
use
rustc
::
ty
::
Ty
;
pub
struct
CleanupScope
<
'tcx
>
{
...
...
@@ -36,7 +36,7 @@ pub struct CleanupScope<'tcx> {
#[derive(Copy,
Clone)]
pub
struct
DropValue
<
'tcx
>
{
val
:
ValueRef
,
val
:
MaybeSizedValue
,
ty
:
Ty
<
'tcx
>
,
skip_dtor
:
bool
,
}
...
...
@@ -94,7 +94,7 @@ fn get_landing_pad<'a>(&self, fcx: &FunctionContext<'a, 'tcx>) -> BasicBlockRef
impl
<
'a
,
'tcx
>
FunctionContext
<
'a
,
'tcx
>
{
/// Schedules a (deep) drop of `val`, which is a pointer to an instance of `ty`
pub
fn
schedule_drop_mem
(
&
self
,
val
:
ValueRef
,
ty
:
Ty
<
'tcx
>
)
->
CleanupScope
<
'tcx
>
{
pub
fn
schedule_drop_mem
(
&
self
,
val
:
MaybeSizedValue
,
ty
:
Ty
<
'tcx
>
)
->
CleanupScope
<
'tcx
>
{
if
!
self
.ccx
.shared
()
.type_needs_drop
(
ty
)
{
return
CleanupScope
::
noop
();
}
let
drop
=
DropValue
{
val
:
val
,
...
...
@@ -102,8 +102,6 @@ pub fn schedule_drop_mem(&self, val: ValueRef, ty: Ty<'tcx>) -> CleanupScope<'tc
skip_dtor
:
false
,
};
debug!
(
"schedule_drop_mem(val={:?}, ty={:?}) skip_dtor={}"
,
Value
(
val
),
ty
,
drop
.skip_dtor
);
CleanupScope
::
new
(
self
,
drop
)
}
...
...
@@ -112,7 +110,8 @@ pub fn schedule_drop_mem(&self, val: ValueRef, ty: Ty<'tcx>) -> CleanupScope<'tc
/// `ty`. The scheduled code handles extracting the discriminant
/// and dropping the contents associated with that variant
/// *without* executing any associated drop implementation.
pub
fn
schedule_drop_adt_contents
(
&
self
,
val
:
ValueRef
,
ty
:
Ty
<
'tcx
>
)
->
CleanupScope
<
'tcx
>
{
pub
fn
schedule_drop_adt_contents
(
&
self
,
val
:
MaybeSizedValue
,
ty
:
Ty
<
'tcx
>
)
->
CleanupScope
<
'tcx
>
{
// `if` below could be "!contents_needs_drop"; skipping drop
// is just an optimization, so sound to be conservative.
if
!
self
.ccx
.shared
()
.type_needs_drop
(
ty
)
{
return
CleanupScope
::
noop
();
}
...
...
@@ -123,9 +122,6 @@ pub fn schedule_drop_adt_contents(&self, val: ValueRef, ty: Ty<'tcx>) -> Cleanup
skip_dtor
:
true
,
};
debug!
(
"schedule_drop_adt_contents(val={:?}, ty={:?}) skip_dtor={}"
,
Value
(
val
),
ty
,
drop
.skip_dtor
);
CleanupScope
::
new
(
self
,
drop
)
}
}
...
...
src/librustc_trans/glue.rs
浏览文件 @
afc2dcd0
...
...
@@ -20,7 +20,7 @@
use
rustc
::
ty
::
subst
::{
Substs
};
use
rustc
::
traits
;
use
rustc
::
ty
::{
self
,
AdtKind
,
Ty
,
TypeFoldable
};
use
adt
;
use
adt
::{
self
,
MaybeSizedValue
}
;
use
base
::
*
;
use
callee
::
Callee
;
use
common
::
*
;
...
...
@@ -107,13 +107,13 @@ pub fn get_drop_glue_type<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, t: Ty<'t
}
}
fn
drop_ty
<
'a
,
'tcx
>
(
bcx
:
&
BlockAndBuilder
<
'a
,
'tcx
>
,
v
:
ValueRef
,
t
:
Ty
<
'tcx
>
)
{
call_drop_glue
(
bcx
,
v
,
t
,
false
,
None
)
fn
drop_ty
<
'a
,
'tcx
>
(
bcx
:
&
BlockAndBuilder
<
'a
,
'tcx
>
,
args
:
MaybeSizedValue
,
t
:
Ty
<
'tcx
>
)
{
call_drop_glue
(
bcx
,
args
,
t
,
false
,
None
)
}
pub
fn
call_drop_glue
<
'a
,
'tcx
>
(
bcx
:
&
BlockAndBuilder
<
'a
,
'tcx
>
,
v
:
ValueRef
,
mut
args
:
MaybeSizedValue
,
t
:
Ty
<
'tcx
>
,
skip_dtor
:
bool
,
funclet
:
Option
<&
'a
Funclet
>
,
...
...
@@ -129,14 +129,13 @@ pub fn call_drop_glue<'a, 'tcx>(
};
let
glue
=
get_drop_glue_core
(
ccx
,
g
);
let
glue_type
=
get_drop_glue_type
(
ccx
.shared
(),
t
);
let
ptr
=
if
glue_type
!=
t
{
bcx
.pointercast
(
v
,
type_of
(
ccx
,
glue_type
)
.ptr_to
())
}
else
{
v
};
if
glue_type
!=
t
{
args
.value
=
bcx
.pointercast
(
args
.value
,
type_of
(
ccx
,
glue_type
)
.ptr_to
());
}
// No drop-hint ==> call standard drop glue
bcx
.call
(
glue
,
&
[
ptr
],
funclet
.map
(|
b
|
b
.bundle
()));
bcx
.call
(
glue
,
&
[
args
.value
,
args
.meta
][
..
1
+
args
.has_meta
()
as
usize
],
funclet
.map
(|
b
|
b
.bundle
()));
}
}
...
...
@@ -189,7 +188,7 @@ pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, g: DropGlueKi
let
(
llfn
,
_
)
=
ccx
.drop_glues
()
.borrow
()
.get
(
&
g
)
.unwrap
()
.clone
();
let
fcx
=
FunctionContext
::
new
(
ccx
,
llfn
);
let
bcx
=
fcx
.get_entry_block
();
let
mut
bcx
=
fcx
.get_entry_block
();
ccx
.stats
()
.n_glues_created
.set
(
ccx
.stats
()
.n_glues_created
.get
()
+
1
);
// All glue functions take values passed *by alias*; this is a
...
...
@@ -205,9 +204,15 @@ pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, g: DropGlueKi
// non-null, (and maybe we need to continue doing so), but we now
// must definitely check for special bit-patterns corresponding to
// the special dtor markings.
let
v0
=
get_param
(
llfn
,
0
);
let
t
=
g
.ty
();
let
value
=
get_param
(
llfn
,
0
);
let
ptr
=
if
ccx
.shared
()
.type_is_sized
(
t
)
{
MaybeSizedValue
::
sized
(
value
)
}
else
{
MaybeSizedValue
::
unsized_
(
value
,
get_param
(
llfn
,
1
))
};
let
skip_dtor
=
match
g
{
DropGlueKind
::
Ty
(
_
)
=>
false
,
DropGlueKind
::
TyContents
(
_
)
=>
true
...
...
@@ -220,12 +225,9 @@ pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, g: DropGlueKi
// a safe-guard, assert TyBox not used with TyContents.
assert
!
(
!
skip_dtor
);
if
!
bcx
.ccx
.shared
()
.type_is_sized
(
content_ty
)
{
let
llval
=
get_dataptr
(
&
bcx
,
v0
);
let
llbox
=
bcx
.load
(
llval
);
drop_ty
(
&
bcx
,
v0
,
content_ty
);
// FIXME(#36457) -- we should pass unsized values to drop glue as two arguments
let
info
=
get_meta
(
&
bcx
,
v0
);
let
info
=
bcx
.load
(
info
);
let
llbox
=
bcx
.load
(
get_dataptr
(
&
bcx
,
ptr
.value
));
let
info
=
bcx
.load
(
get_meta
(
&
bcx
,
ptr
.value
));
drop_ty
(
&
bcx
,
MaybeSizedValue
::
unsized_
(
llbox
,
info
),
content_ty
);
let
(
llsize
,
llalign
)
=
size_and_align_of_dst
(
&
bcx
,
content_ty
,
info
);
// `Box<ZeroSizeType>` does not allocate.
...
...
@@ -241,9 +243,8 @@ pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, g: DropGlueKi
next_cx
}
}
else
{
let
llval
=
v0
;
let
llbox
=
bcx
.load
(
llval
);
drop_ty
(
&
bcx
,
llbox
,
content_ty
);
let
llbox
=
bcx
.load
(
ptr
.value
);
drop_ty
(
&
bcx
,
MaybeSizedValue
::
sized
(
llbox
),
content_ty
);
trans_exchange_free_ty
(
&
bcx
,
llbox
,
content_ty
);
bcx
}
...
...
@@ -252,23 +253,61 @@ pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, g: DropGlueKi
// No support in vtable for distinguishing destroying with
// versus without calling Drop::drop. Assert caller is
// okay with always calling the Drop impl, if any.
// FIXME(#36457) -- we should pass unsized values to drop glue as two arguments
assert
!
(
!
skip_dtor
);
let
data_ptr
=
get_dataptr
(
&
bcx
,
v0
);
let
vtable_ptr
=
bcx
.load
(
get_meta
(
&
bcx
,
v0
));
let
dtor
=
bcx
.load
(
vtable_ptr
);
bcx
.call
(
dtor
,
&
[
bcx
.pointercast
(
bcx
.load
(
data_ptr
),
Type
::
i8p
(
bcx
.ccx
))],
None
);
let
dtor
=
bcx
.load
(
ptr
.meta
);
bcx
.call
(
dtor
,
&
[
ptr
.value
],
None
);
bcx
}
ty
::
TyAdt
(
def
,
..
)
if
def
.dtor_kind
()
.is_present
()
&&
!
skip_dtor
=>
{
trans_custom_dtor
(
bcx
,
t
,
v0
,
def
.is_union
())
let
shallow_drop
=
def
.is_union
();
let
tcx
=
bcx
.tcx
();
let
def
=
t
.ty_adt_def
()
.unwrap
();
// Be sure to put the contents into a scope so we can use an invoke
// instruction to call the user destructor but still call the field
// destructors if the user destructor panics.
//
// FIXME (#14875) panic-in-drop semantics might be unsupported; we
// might well consider changing below to more direct code.
// Issue #23611: schedule cleanup of contents, re-inspecting the
// discriminant (if any) in case of variant swap in drop code.
let
contents_scope
=
if
!
shallow_drop
{
bcx
.fcx
()
.schedule_drop_adt_contents
(
ptr
,
t
)
}
else
{
CleanupScope
::
noop
()
};
let
trait_ref
=
ty
::
Binder
(
ty
::
TraitRef
{
def_id
:
tcx
.lang_items
.drop_trait
()
.unwrap
(),
substs
:
tcx
.mk_substs_trait
(
t
,
&
[])
});
let
vtbl
=
match
fulfill_obligation
(
bcx
.ccx
.shared
(),
DUMMY_SP
,
trait_ref
)
{
traits
::
VtableImpl
(
data
)
=>
data
,
_
=>
bug!
(
"dtor for {:?} is not an impl???"
,
t
)
};
let
dtor_did
=
def
.destructor
()
.unwrap
();
let
callee
=
Callee
::
def
(
bcx
.ccx
,
dtor_did
,
vtbl
.substs
);
let
fn_ty
=
callee
.direct_fn_type
(
bcx
.ccx
,
&
[]);
let
llret
;
let
args
=
&
[
ptr
.value
,
ptr
.meta
][
..
1
+
ptr
.has_meta
()
as
usize
];
if
let
Some
(
landing_pad
)
=
contents_scope
.landing_pad
{
let
normal_bcx
=
bcx
.fcx
()
.build_new_block
(
"normal-return"
);
llret
=
bcx
.invoke
(
callee
.reify
(
ccx
),
args
,
normal_bcx
.llbb
(),
landing_pad
,
None
);
bcx
=
normal_bcx
;
}
else
{
llret
=
bcx
.call
(
callee
.reify
(
bcx
.ccx
),
args
,
None
);
}
fn_ty
.apply_attrs_callsite
(
llret
);
contents_scope
.trans
(
&
bcx
);
bcx
}
ty
::
TyAdt
(
def
,
..
)
if
def
.is_union
()
=>
{
bcx
}
_
=>
{
if
bcx
.ccx
.shared
()
.type_needs_drop
(
t
)
{
drop_structural_ty
(
bcx
,
v0
,
t
)
drop_structural_ty
(
bcx
,
ptr
,
t
)
}
else
{
bcx
}
...
...
@@ -277,68 +316,6 @@ pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, g: DropGlueKi
bcx
.ret_void
();
}
fn
trans_custom_dtor
<
'a
,
'tcx
>
(
mut
bcx
:
BlockAndBuilder
<
'a
,
'tcx
>
,
t
:
Ty
<
'tcx
>
,
v0
:
ValueRef
,
shallow_drop
:
bool
)
->
BlockAndBuilder
<
'a
,
'tcx
>
{
debug!
(
"trans_custom_dtor t: {}"
,
t
);
let
tcx
=
bcx
.tcx
();
let
def
=
t
.ty_adt_def
()
.unwrap
();
// Be sure to put the contents into a scope so we can use an invoke
// instruction to call the user destructor but still call the field
// destructors if the user destructor panics.
//
// FIXME (#14875) panic-in-drop semantics might be unsupported; we
// might well consider changing below to more direct code.
// Issue #23611: schedule cleanup of contents, re-inspecting the
// discriminant (if any) in case of variant swap in drop code.
let
contents_scope
=
if
!
shallow_drop
{
bcx
.fcx
()
.schedule_drop_adt_contents
(
v0
,
t
)
}
else
{
CleanupScope
::
noop
()
};
let
(
sized_args
,
unsized_args
);
let
args
:
&
[
ValueRef
]
=
if
bcx
.ccx
.shared
()
.type_is_sized
(
t
)
{
sized_args
=
[
v0
];
&
sized_args
}
else
{
// FIXME(#36457) -- we should pass unsized values to drop glue as two arguments
unsized_args
=
[
bcx
.load
(
get_dataptr
(
&
bcx
,
v0
)),
bcx
.load
(
get_meta
(
&
bcx
,
v0
))
];
&
unsized_args
};
let
trait_ref
=
ty
::
Binder
(
ty
::
TraitRef
{
def_id
:
tcx
.lang_items
.drop_trait
()
.unwrap
(),
substs
:
tcx
.mk_substs_trait
(
t
,
&
[])
});
let
vtbl
=
match
fulfill_obligation
(
bcx
.ccx
.shared
(),
DUMMY_SP
,
trait_ref
)
{
traits
::
VtableImpl
(
data
)
=>
data
,
_
=>
bug!
(
"dtor for {:?} is not an impl???"
,
t
)
};
let
dtor_did
=
def
.destructor
()
.unwrap
();
let
callee
=
Callee
::
def
(
bcx
.ccx
,
dtor_did
,
vtbl
.substs
);
let
fn_ty
=
callee
.direct_fn_type
(
bcx
.ccx
,
&
[]);
let
llret
;
if
let
Some
(
landing_pad
)
=
contents_scope
.landing_pad
{
let
normal_bcx
=
bcx
.fcx
()
.build_new_block
(
"normal-return"
);
llret
=
bcx
.invoke
(
callee
.reify
(
bcx
.ccx
),
args
,
normal_bcx
.llbb
(),
landing_pad
,
None
);
bcx
=
normal_bcx
;
}
else
{
llret
=
bcx
.call
(
callee
.reify
(
bcx
.ccx
),
args
,
None
);
}
fn_ty
.apply_attrs_callsite
(
llret
);
contents_scope
.trans
(
&
bcx
);
bcx
}
pub
fn
size_and_align_of_dst
<
'a
,
'tcx
>
(
bcx
:
&
BlockAndBuilder
<
'a
,
'tcx
>
,
t
:
Ty
<
'tcx
>
,
info
:
ValueRef
)
->
(
ValueRef
,
ValueRef
)
{
...
...
@@ -448,7 +425,7 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &BlockAndBuilder<'a, 'tcx>,
// Iterates through the elements of a structural type, dropping them.
fn
drop_structural_ty
<
'a
,
'tcx
>
(
cx
:
BlockAndBuilder
<
'a
,
'tcx
>
,
av
:
ValueRef
,
ptr
:
MaybeSizedValue
,
t
:
Ty
<
'tcx
>
)
->
BlockAndBuilder
<
'a
,
'tcx
>
{
fn
iter_variant
<
'a
,
'tcx
>
(
cx
:
&
BlockAndBuilder
<
'a
,
'tcx
>
,
...
...
@@ -460,60 +437,47 @@ fn iter_variant<'a, 'tcx>(cx: &BlockAndBuilder<'a, 'tcx>,
for
(
i
,
field
)
in
variant
.fields
.iter
()
.enumerate
()
{
let
arg
=
monomorphize
::
field_ty
(
tcx
,
substs
,
field
);
let
field_ptr
=
adt
::
trans_field_ptr
(
&
cx
,
t
,
av
,
Disr
::
from
(
variant
.disr_val
),
i
);
drop_ty
(
&
cx
,
field_ptr
,
arg
);
drop_ty
(
&
cx
,
MaybeSizedValue
::
sized
(
field_ptr
)
,
arg
);
}
}
let
value
=
if
cx
.ccx
.shared
()
.type_is_sized
(
t
)
{
adt
::
MaybeSizedValue
::
sized
(
av
)
}
else
{
// FIXME(#36457) -- we should pass unsized values as two arguments
let
data
=
cx
.load
(
get_dataptr
(
&
cx
,
av
));
let
info
=
cx
.load
(
get_meta
(
&
cx
,
av
));
adt
::
MaybeSizedValue
::
unsized_
(
data
,
info
)
};
let
mut
cx
=
cx
;
match
t
.sty
{
ty
::
TyClosure
(
def_id
,
substs
)
=>
{
for
(
i
,
upvar_ty
)
in
substs
.upvar_tys
(
def_id
,
cx
.tcx
())
.enumerate
()
{
let
llupvar
=
adt
::
trans_field_ptr
(
&
cx
,
t
,
value
,
Disr
(
0
),
i
);
drop_ty
(
&
cx
,
llupvar
,
upvar_ty
);
let
llupvar
=
adt
::
trans_field_ptr
(
&
cx
,
t
,
ptr
,
Disr
(
0
),
i
);
drop_ty
(
&
cx
,
MaybeSizedValue
::
sized
(
llupvar
)
,
upvar_ty
);
}
}
ty
::
TyArray
(
_
,
n
)
=>
{
let
base
=
get_dataptr
(
&
cx
,
value
.value
);
let
base
=
get_dataptr
(
&
cx
,
ptr
.value
);
let
len
=
C_uint
(
cx
.ccx
,
n
);
let
unit_ty
=
t
.sequence_element_type
(
cx
.tcx
());
cx
=
tvec
::
slice_for_each
(
&
cx
,
base
,
unit_ty
,
len
,
|
bb
,
vv
|
drop_ty
(
bb
,
vv
,
unit_ty
));
cx
=
tvec
::
slice_for_each
(
&
cx
,
base
,
unit_ty
,
len
,
|
bb
,
vv
|
drop_ty
(
bb
,
MaybeSizedValue
::
sized
(
vv
),
unit_ty
));
}
ty
::
TySlice
(
_
)
|
ty
::
TyStr
=>
{
let
unit_ty
=
t
.sequence_element_type
(
cx
.tcx
());
cx
=
tvec
::
slice_for_each
(
&
cx
,
value
.value
,
unit_ty
,
value
.meta
,
|
bb
,
vv
|
drop_ty
(
bb
,
vv
,
unit_ty
));
cx
=
tvec
::
slice_for_each
(
&
cx
,
ptr
.value
,
unit_ty
,
ptr
.meta
,
|
bb
,
vv
|
drop_ty
(
bb
,
MaybeSizedValue
::
sized
(
vv
)
,
unit_ty
));
}
ty
::
TyTuple
(
ref
args
)
=>
{
for
(
i
,
arg
)
in
args
.iter
()
.enumerate
()
{
let
llfld_a
=
adt
::
trans_field_ptr
(
&
cx
,
t
,
value
,
Disr
(
0
),
i
);
drop_ty
(
&
cx
,
llfld_a
,
*
arg
);
let
llfld_a
=
adt
::
trans_field_ptr
(
&
cx
,
t
,
ptr
,
Disr
(
0
),
i
);
drop_ty
(
&
cx
,
MaybeSizedValue
::
sized
(
llfld_a
)
,
*
arg
);
}
}
ty
::
TyAdt
(
adt
,
substs
)
=>
match
adt
.adt_kind
()
{
AdtKind
::
Struct
=>
{
let
VariantInfo
{
fields
,
discr
}
=
VariantInfo
::
from_ty
(
cx
.tcx
(),
t
,
None
);
for
(
i
,
&
Field
(
_
,
field_ty
))
in
fields
.iter
()
.enumerate
()
{
let
llfld_a
=
adt
::
trans_field_ptr
(
&
cx
,
t
,
value
,
Disr
::
from
(
discr
),
i
);
let
val
=
if
cx
.ccx
.shared
()
.type_is_sized
(
field_ty
)
{
llfld_a
let
llfld_a
=
adt
::
trans_field_ptr
(
&
cx
,
t
,
ptr
,
Disr
::
from
(
discr
),
i
);
let
ptr
=
if
cx
.ccx
.shared
()
.type_is_sized
(
field_ty
)
{
MaybeSizedValue
::
sized
(
llfld_a
)
}
else
{
// FIXME(#36457) -- we should pass unsized values as two arguments
let
scratch
=
alloc_ty
(
&
cx
,
field_ty
,
"__fat_ptr_iter"
);
cx
.store
(
llfld_a
,
get_dataptr
(
&
cx
,
scratch
));
cx
.store
(
value
.meta
,
get_meta
(
&
cx
,
scratch
));
scratch
MaybeSizedValue
::
unsized_
(
llfld_a
,
ptr
.meta
)
};
drop_ty
(
&
cx
,
val
,
field_ty
);
drop_ty
(
&
cx
,
ptr
,
field_ty
);
}
}
AdtKind
::
Union
=>
{
...
...
@@ -525,17 +489,16 @@ fn iter_variant<'a, 'tcx>(cx: &BlockAndBuilder<'a, 'tcx>,
// NB: we must hit the discriminant first so that structural
// comparison know not to proceed when the discriminants differ.
match
adt
::
trans_switch
(
&
cx
,
t
,
av
,
false
)
{
match
adt
::
trans_switch
(
&
cx
,
t
,
ptr
.value
,
false
)
{
(
adt
::
BranchKind
::
Single
,
None
)
=>
{
if
n_variants
!=
0
{
assert
!
(
n_variants
==
1
);
iter_variant
(
&
cx
,
t
,
adt
::
MaybeSizedValue
::
sized
(
av
),
&
adt
.variants
[
0
],
substs
);
iter_variant
(
&
cx
,
t
,
ptr
,
&
adt
.variants
[
0
],
substs
);
}
}
(
adt
::
BranchKind
::
Switch
,
Some
(
lldiscrim_a
))
=>
{
let
tcx
=
cx
.tcx
();
drop_ty
(
&
cx
,
lldiscrim_a
,
tcx
.types.isize
);
drop_ty
(
&
cx
,
MaybeSizedValue
::
sized
(
lldiscrim_a
)
,
tcx
.types.isize
);
// Create a fall-through basic block for the "else" case of
// the switch instruction we're about to generate. Note that
...
...
@@ -561,7 +524,7 @@ fn iter_variant<'a, 'tcx>(cx: &BlockAndBuilder<'a, 'tcx>,
let
variant_cx
=
cx
.fcx
()
.build_new_block
(
&
variant_cx_name
);
let
case_val
=
adt
::
trans_case
(
&
cx
,
t
,
Disr
::
from
(
variant
.disr_val
));
variant_cx
.add_case
(
llswitch
,
case_val
,
variant_cx
.llbb
());
iter_variant
(
&
variant_cx
,
t
,
value
,
variant
,
substs
);
iter_variant
(
&
variant_cx
,
t
,
ptr
,
variant
,
substs
);
variant_cx
.br
(
next_cx
.llbb
());
}
cx
=
next_cx
;
...
...
src/librustc_trans/mir/block.rs
浏览文件 @
afc2dcd0
...
...
@@ -14,7 +14,7 @@
use
rustc
::
ty
::{
self
,
layout
};
use
rustc
::
mir
;
use
abi
::{
Abi
,
FnType
,
ArgType
};
use
adt
;
use
adt
::{
self
,
MaybeSizedValue
}
;
use
base
::{
self
,
Lifetime
};
use
callee
::{
Callee
,
CalleeData
,
Fn
,
Intrinsic
,
NamedTupleConstructor
,
Virtual
};
use
common
::{
self
,
BlockAndBuilder
,
Funclet
};
...
...
@@ -38,8 +38,6 @@
use
super
::
operand
::
OperandRef
;
use
super
::
operand
::
OperandValue
::{
Pair
,
Ref
,
Immediate
};
use
std
::
ptr
;
impl
<
'a
,
'tcx
>
MirContext
<
'a
,
'tcx
>
{
pub
fn
trans_block
(
&
mut
self
,
bb
:
mir
::
BasicBlock
,
funclets
:
&
IndexVec
<
mir
::
BasicBlock
,
Option
<
Funclet
>>
)
{
...
...
@@ -244,35 +242,27 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock,
let
lvalue
=
self
.trans_lvalue
(
&
bcx
,
location
);
let
drop_fn
=
glue
::
get_drop_glue
(
bcx
.ccx
,
ty
);
let
drop_ty
=
glue
::
get_drop_glue_type
(
bcx
.ccx
.shared
(),
ty
);
let
is_sized
=
bcx
.ccx
.shared
()
.type_is_sized
(
ty
);
let
llvalue
=
if
is_sized
{
if
drop_ty
!=
ty
{
let
ptr
=
if
bcx
.ccx
.shared
()
.type_is_sized
(
ty
)
{
let
value
=
if
drop_ty
!=
ty
{
bcx
.pointercast
(
lvalue
.llval
,
type_of
::
type_of
(
bcx
.ccx
,
drop_ty
)
.ptr_to
())
}
else
{
lvalue
.llval
}
};
MaybeSizedValue
::
sized
(
value
)
}
else
{
// FIXME(#36457) Currently drop glue takes sized
// values as a `*(data, meta)`, but elsewhere in
// MIR we pass `(data, meta)` as two separate
// arguments. It would be better to fix drop glue,
// but I am shooting for a quick fix to #35546
// here that can be cleanly backported to beta, so
// I want to avoid touching all of trans.
let
scratch
=
base
::
alloc_ty
(
&
bcx
,
ty
,
"drop"
);
Lifetime
::
Start
.call
(
&
bcx
,
scratch
);
bcx
.store
(
lvalue
.llval
,
base
::
get_dataptr
(
&
bcx
,
scratch
));
bcx
.store
(
lvalue
.llextra
,
base
::
get_meta
(
&
bcx
,
scratch
));
scratch
MaybeSizedValue
::
unsized_
(
lvalue
.llval
,
lvalue
.llextra
)
};
let
args
=
&
[
ptr
.value
,
ptr
.meta
][
..
1
+
ptr
.has_meta
()
as
usize
];
if
let
Some
(
unwind
)
=
unwind
{
bcx
.invoke
(
drop_fn
,
&
[
llvalue
],
self
.blocks
[
target
],
llblock
(
self
,
unwind
),
cleanup_bundle
);
bcx
.invoke
(
drop_fn
,
args
,
self
.blocks
[
target
],
llblock
(
self
,
unwind
),
cleanup_bundle
);
}
else
{
bcx
.call
(
drop_fn
,
&
[
llvalue
]
,
cleanup_bundle
);
bcx
.call
(
drop_fn
,
args
,
cleanup_bundle
);
funclet_br
(
self
,
bcx
,
target
);
}
}
...
...
@@ -429,7 +419,7 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock,
}
_
=>
None
};
let
intrinsic
=
intrinsic
.as_ref
()
.map
(|
s
|
&
s
[
..
]);
let
mut
intrinsic
=
intrinsic
.as_ref
()
.map
(|
s
|
&
s
[
..
]);
if
intrinsic
==
Some
(
"move_val_init"
)
{
let
&
(
_
,
target
)
=
destination
.as_ref
()
.unwrap
();
...
...
@@ -441,65 +431,6 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock,
return
;
}
// FIXME: This should proxy to the drop glue in the future when the ABI matches;
// most of the below code was copied from the match arm for TerminatorKind::Drop.
if
intrinsic
==
Some
(
"drop_in_place"
)
{
let
&
(
_
,
target
)
=
destination
.as_ref
()
.unwrap
();
let
ty
=
if
let
ty
::
TyFnDef
(
_
,
substs
,
_
)
=
callee
.ty.sty
{
substs
.type_at
(
0
)
}
else
{
bug!
(
"Unexpected ty: {}"
,
callee
.ty
);
};
// Double check for necessity to drop
if
!
bcx
.ccx
.shared
()
.type_needs_drop
(
ty
)
{
funclet_br
(
self
,
bcx
,
target
);
return
;
}
let
ptr
=
self
.trans_operand
(
&
bcx
,
&
args
[
0
]);
let
(
llval
,
llextra
)
=
match
ptr
.val
{
Immediate
(
llptr
)
=>
(
llptr
,
ptr
::
null_mut
()),
Pair
(
llptr
,
llextra
)
=>
(
llptr
,
llextra
),
Ref
(
_
)
=>
bug!
(
"Deref of by-Ref type {:?}"
,
ptr
.ty
)
};
let
drop_fn
=
glue
::
get_drop_glue
(
bcx
.ccx
,
ty
);
let
drop_ty
=
glue
::
get_drop_glue_type
(
bcx
.ccx
.shared
(),
ty
);
let
is_sized
=
bcx
.ccx
.shared
()
.type_is_sized
(
ty
);
let
llvalue
=
if
is_sized
{
if
drop_ty
!=
ty
{
bcx
.pointercast
(
llval
,
type_of
::
type_of
(
bcx
.ccx
,
drop_ty
)
.ptr_to
())
}
else
{
llval
}
}
else
{
// FIXME(#36457) Currently drop glue takes sized
// values as a `*(data, meta)`, but elsewhere in
// MIR we pass `(data, meta)` as two separate
// arguments. It would be better to fix drop glue,
// but I am shooting for a quick fix to #35546
// here that can be cleanly backported to beta, so
// I want to avoid touching all of trans.
let
scratch
=
base
::
alloc_ty
(
&
bcx
,
ty
,
"drop"
);
Lifetime
::
Start
.call
(
&
bcx
,
scratch
);
bcx
.store
(
llval
,
base
::
get_dataptr
(
&
bcx
,
scratch
));
bcx
.store
(
llextra
,
base
::
get_meta
(
&
bcx
,
scratch
));
scratch
};
if
let
Some
(
unwind
)
=
*
cleanup
{
bcx
.invoke
(
drop_fn
,
&
[
llvalue
],
self
.blocks
[
target
],
llblock
(
self
,
unwind
),
cleanup_bundle
);
}
else
{
bcx
.call
(
drop_fn
,
&
[
llvalue
],
cleanup_bundle
);
funclet_br
(
self
,
bcx
,
target
);
}
return
;
}
if
intrinsic
==
Some
(
"transmute"
)
{
let
&
(
ref
dest
,
target
)
=
destination
.as_ref
()
.unwrap
();
self
.with_lvalue_ref
(
&
bcx
,
dest
,
|
this
,
dest
|
{
...
...
@@ -517,6 +448,26 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock,
})
.collect
::
<
Vec
<
_
>>
();
let
fn_ty
=
callee
.direct_fn_type
(
bcx
.ccx
,
&
extra_args
);
if
intrinsic
==
Some
(
"drop_in_place"
)
{
let
&
(
_
,
target
)
=
destination
.as_ref
()
.unwrap
();
let
ty
=
if
let
ty
::
TyFnDef
(
_
,
substs
,
_
)
=
callee
.ty.sty
{
substs
.type_at
(
0
)
}
else
{
bug!
(
"Unexpected ty: {}"
,
callee
.ty
);
};
// Double check for necessity to drop
if
!
bcx
.ccx
.shared
()
.type_needs_drop
(
ty
)
{
funclet_br
(
self
,
bcx
,
target
);
return
;
}
let
drop_fn
=
glue
::
get_drop_glue
(
bcx
.ccx
,
ty
);
let
llty
=
fn_ty
.llvm_type
(
bcx
.ccx
)
.ptr_to
();
callee
.data
=
Fn
(
bcx
.pointercast
(
drop_fn
,
llty
));
intrinsic
=
None
;
}
// The arguments we'll be passing. Plus one to account for outptr, if used.
let
arg_count
=
fn_ty
.args
.len
()
+
fn_ty
.ret
.is_indirect
()
as
usize
;
let
mut
llargs
=
Vec
::
with_capacity
(
arg_count
);
...
...
src/librustc_trans/trans_item.rs
浏览文件 @
afc2dcd0
...
...
@@ -187,12 +187,11 @@ fn predefine_drop_glue(ccx: &CrateContext<'a, 'tcx>,
assert_eq!
(
dg
.ty
(),
glue
::
get_drop_glue_type
(
ccx
.shared
(),
dg
.ty
()));
let
t
=
dg
.ty
();
let
sig
=
tcx
.mk_fn_sig
(
iter
::
once
(
tcx
.mk_mut_ptr
(
t
cx
.types.i8
)),
tcx
.mk_nil
(),
false
);
let
sig
=
tcx
.mk_fn_sig
(
iter
::
once
(
tcx
.mk_mut_ptr
(
t
)),
tcx
.mk_nil
(),
false
);
// Create a FnType for fn(*mut i8) and substitute the real type in
// later - that prevents FnType from splitting fat pointers up.
let
mut
fn_ty
=
FnType
::
new
(
ccx
,
Abi
::
Rust
,
&
sig
,
&
[]);
fn_ty
.args
[
0
]
.original_ty
=
type_of
::
type_of
(
ccx
,
t
)
.ptr_to
();
debug!
(
"predefine_drop_glue: sig={}"
,
sig
);
let
fn_ty
=
FnType
::
new
(
ccx
,
Abi
::
Rust
,
&
sig
,
&
[]);
let
llfnty
=
fn_ty
.llvm_type
(
ccx
);
assert
!
(
declare
::
get_defined_value
(
ccx
,
symbol_name
)
.is_none
());
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录