Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
ee982d43
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,发现更多精彩内容 >>
提交
ee982d43
编写于
5月 23, 2017
作者:
A
Ariel Ben-Yehuda
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
fix translation of MSVC funclets that loop to their own start
上级
6adfbaf2
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
93 addition
and
80 deletion
+93
-80
src/librustc_data_structures/indexed_vec.rs
src/librustc_data_structures/indexed_vec.rs
+7
-0
src/librustc_trans/common.rs
src/librustc_trans/common.rs
+0
-9
src/librustc_trans/mir/analyze.rs
src/librustc_trans/mir/analyze.rs
+10
-0
src/librustc_trans/mir/block.rs
src/librustc_trans/mir/block.rs
+44
-53
src/librustc_trans/mir/mod.rs
src/librustc_trans/mir/mod.rs
+32
-18
未找到文件。
src/librustc_data_structures/indexed_vec.rs
浏览文件 @
ee982d43
...
...
@@ -212,6 +212,13 @@ fn index_mut(&mut self, index: I) -> &mut T {
}
}
impl
<
I
:
Idx
,
T
>
Default
for
IndexVec
<
I
,
T
>
{
#[inline]
fn
default
()
->
Self
{
Self
::
new
()
}
}
impl
<
I
:
Idx
,
T
>
Extend
<
T
>
for
IndexVec
<
I
,
T
>
{
#[inline]
fn
extend
<
J
:
IntoIterator
<
Item
=
T
>>
(
&
mut
self
,
iter
:
J
)
{
...
...
src/librustc_trans/common.rs
浏览文件 @
ee982d43
...
...
@@ -191,15 +191,6 @@ pub fn bundle(&self) -> &OperandBundleDef {
}
}
impl
Clone
for
Funclet
{
fn
clone
(
&
self
)
->
Funclet
{
Funclet
{
cleanuppad
:
self
.cleanuppad
,
operand
:
OperandBundleDef
::
new
(
"funclet"
,
&
[
self
.cleanuppad
]),
}
}
}
pub
fn
val_ty
(
v
:
ValueRef
)
->
Type
{
unsafe
{
Type
::
from_ref
(
llvm
::
LLVMTypeOf
(
v
))
...
...
src/librustc_trans/mir/analyze.rs
浏览文件 @
ee982d43
...
...
@@ -197,6 +197,16 @@ pub enum CleanupKind {
Internal
{
funclet
:
mir
::
BasicBlock
}
}
impl
CleanupKind
{
pub
fn
funclet_bb
(
self
,
for_bb
:
mir
::
BasicBlock
)
->
Option
<
mir
::
BasicBlock
>
{
match
self
{
CleanupKind
::
NotCleanup
=>
None
,
CleanupKind
::
Funclet
=>
Some
(
for_bb
),
CleanupKind
::
Internal
{
funclet
}
=>
Some
(
funclet
),
}
}
}
pub
fn
cleanup_kinds
<
'a
,
'tcx
>
(
mir
:
&
mir
::
Mir
<
'tcx
>
)
->
IndexVec
<
mir
::
BasicBlock
,
CleanupKind
>
{
fn
discover_masters
<
'tcx
>
(
result
:
&
mut
IndexVec
<
mir
::
BasicBlock
,
CleanupKind
>
,
mir
:
&
mir
::
Mir
<
'tcx
>
)
{
...
...
src/librustc_trans/mir/block.rs
浏览文件 @
ee982d43
...
...
@@ -19,8 +19,7 @@
use
base
::{
self
,
Lifetime
};
use
callee
;
use
builder
::
Builder
;
use
common
::{
self
,
Funclet
};
use
common
::{
C_bool
,
C_str_slice
,
C_struct
,
C_u32
,
C_undef
};
use
common
::{
self
,
C_bool
,
C_str_slice
,
C_struct
,
C_u32
,
C_undef
};
use
consts
;
use
machine
::
llalign_of_min
;
use
meth
;
...
...
@@ -28,95 +27,88 @@
use
type_of
;
use
type_
::
Type
;
use
rustc_data_structures
::
indexed_vec
::
IndexVec
;
use
syntax
::
symbol
::
Symbol
;
use
std
::
cmp
;
use
super
::{
MirContext
,
LocalRef
};
use
super
::
analyze
::
CleanupKind
;
use
super
::
constant
::
Const
;
use
super
::
lvalue
::{
Alignment
,
LvalueRef
};
use
super
::
operand
::
OperandRef
;
use
super
::
operand
::
OperandValue
::{
Pair
,
Ref
,
Immediate
};
impl
<
'a
,
'tcx
>
MirContext
<
'a
,
'tcx
>
{
pub
fn
trans_block
(
&
mut
self
,
bb
:
mir
::
BasicBlock
,
funclets
:
&
IndexVec
<
mir
::
BasicBlock
,
Option
<
Funclet
>>
)
{
pub
fn
trans_block
(
&
mut
self
,
bb
:
mir
::
BasicBlock
)
{
let
mut
bcx
=
self
.get_builder
(
bb
);
let
data
=
&
self
.mir
[
bb
];
debug!
(
"trans_block({:?}={:?})"
,
bb
,
data
);
let
funclet
=
match
self
.cleanup_kinds
[
bb
]
{
CleanupKind
::
Internal
{
funclet
}
=>
funclets
[
funclet
]
.as_ref
(),
_
=>
funclets
[
bb
]
.as_ref
(),
};
for
statement
in
&
data
.statements
{
bcx
=
self
.trans_statement
(
bcx
,
statement
);
}
self
.trans_terminator
(
bcx
,
bb
,
data
.terminator
()
,
funclet
);
self
.trans_terminator
(
bcx
,
bb
,
data
.terminator
());
}
fn
trans_terminator
(
&
mut
self
,
mut
bcx
:
Builder
<
'a
,
'tcx
>
,
bb
:
mir
::
BasicBlock
,
terminator
:
&
mir
::
Terminator
<
'tcx
>
,
funclet
:
Option
<&
Funclet
>
)
terminator
:
&
mir
::
Terminator
<
'tcx
>
)
{
debug!
(
"trans_terminator: {:?}"
,
terminator
);
// Create the cleanup bundle, if needed.
let
tcx
=
bcx
.tcx
();
let
span
=
terminator
.source_info.span
;
let
funclet_bb
=
self
.cleanup_kinds
[
bb
]
.funclet_bb
(
bb
);
let
funclet
=
funclet_bb
.and_then
(|
funclet_bb
|
self
.funclets
[
funclet_bb
]
.as_ref
());
let
cleanup_pad
=
funclet
.map
(|
lp
|
lp
.cleanuppad
());
let
cleanup_bundle
=
funclet
.map
(|
l
|
l
.bundle
());
let
funclet_br
=
|
this
:
&
Self
,
bcx
:
Builder
,
bb
:
mir
::
BasicBlock
|
{
let
lltarget
=
this
.blocks
[
bb
];
if
let
Some
(
cp
)
=
cleanup_pad
{
match
this
.cleanup_kinds
[
bb
]
{
CleanupKind
::
Funclet
=>
{
// micro-optimization: generate a `ret` rather than a jump
// to a return block
bcx
.cleanup_ret
(
cp
,
Some
(
lltarget
));
}
CleanupKind
::
Internal
{
..
}
=>
bcx
.br
(
lltarget
),
CleanupKind
::
NotCleanup
=>
bug!
(
"jump from cleanup bb to bb {:?}"
,
bb
)
let
lltarget
=
|
this
:
&
mut
Self
,
target
:
mir
::
BasicBlock
|
{
let
lltarget
=
this
.blocks
[
target
];
let
target_funclet
=
this
.cleanup_kinds
[
target
]
.funclet_bb
(
target
);
match
(
funclet_bb
,
target_funclet
)
{
(
None
,
None
)
=>
(
lltarget
,
false
),
(
Some
(
f
),
Some
(
t_f
))
if
f
==
t_f
||
!
base
::
wants_msvc_seh
(
tcx
.sess
)
=>
(
lltarget
,
false
),
(
None
,
Some
(
_
))
=>
{
// jump *into* cleanup - need a landing pad if GNU
(
this
.landing_pad_to
(
target
),
false
)
}
(
Some
(
_
),
None
)
=>
span_bug!
(
span
,
"{:?} - jump out of cleanup?"
,
terminator
),
(
Some
(
_
),
Some
(
_
))
=>
{
(
this
.landing_pad_to
(
target
),
true
)
}
}
else
{
bcx
.br
(
lltarget
);
}
};
let
llblock
=
|
this
:
&
mut
Self
,
target
:
mir
::
BasicBlock
|
{
let
lltarget
=
this
.blocks
[
target
];
if
let
Some
(
cp
)
=
cleanup_pad
{
match
this
.cleanup_kinds
[
target
]
{
CleanupKind
::
Funclet
=>
{
// MSVC cross-funclet jump - need a trampoline
let
(
lltarget
,
is_cleanupret
)
=
lltarget
(
this
,
target
);
if
is_cleanupret
{
// MSVC cross-funclet jump - need a trampoline
debug!
(
"llblock: creating cleanup trampoline for {:?}"
,
target
);
let
name
=
&
format!
(
"{:?}_cleanup_trampoline_{:?}"
,
bb
,
target
);
let
trampoline
=
this
.new_block
(
name
);
trampoline
.cleanup_ret
(
cleanup_pad
.unwrap
(),
Some
(
lltarget
));
trampoline
.llbb
()
}
else
{
lltarget
}
};
debug!
(
"llblock: creating cleanup trampoline for {:?}"
,
target
);
let
name
=
&
format!
(
"{:?}_cleanup_trampoline_{:?}"
,
bb
,
target
);
let
trampoline
=
this
.new_block
(
name
);
trampoline
.cleanup_ret
(
cp
,
Some
(
lltarget
));
trampoline
.llbb
()
}
CleanupKind
::
Internal
{
..
}
=>
lltarget
,
CleanupKind
::
NotCleanup
=>
bug!
(
"jump from cleanup bb {:?} to bb {:?}"
,
bb
,
target
)
}
let
funclet_br
=
|
this
:
&
mut
Self
,
bcx
:
Builder
,
target
:
mir
::
BasicBlock
|
{
let
(
lltarget
,
is_cleanupret
)
=
lltarget
(
this
,
target
);
if
is_cleanupret
{
// micro-optimization: generate a `ret` rather than a jump
// to a trampoline.
bcx
.cleanup_ret
(
cleanup_pad
.unwrap
(),
Some
(
lltarget
));
}
else
{
if
let
(
CleanupKind
::
NotCleanup
,
CleanupKind
::
Funclet
)
=
(
this
.cleanup_kinds
[
bb
],
this
.cleanup_kinds
[
target
])
{
// jump *into* cleanup - need a landing pad if GNU
this
.landing_pad_to
(
target
)
}
else
{
lltarget
}
bcx
.br
(
lltarget
);
}
};
...
...
@@ -168,7 +160,6 @@ fn trans_terminator(&mut self,
}
};
let
span
=
terminator
.source_info.span
;
self
.set_debug_loc
(
&
bcx
,
terminator
.source_info
);
match
terminator
.kind
{
mir
::
TerminatorKind
::
Resume
=>
{
...
...
@@ -752,7 +743,7 @@ fn landing_pad_to(&mut self, target_bb: mir::BasicBlock) -> BasicBlockRef {
fn
landing_pad_uncached
(
&
mut
self
,
target_bb
:
BasicBlockRef
)
->
BasicBlockRef
{
if
base
::
wants_msvc_seh
(
self
.ccx
.sess
())
{
return
target_bb
;
span_bug!
(
self
.mir.span
,
"landing pad was not inserted?"
)
}
let
bcx
=
self
.new_block
(
"cleanup"
);
...
...
src/librustc_trans/mir/mod.rs
浏览文件 @
ee982d43
...
...
@@ -69,6 +69,10 @@ pub struct MirContext<'a, 'tcx:'a> {
/// The funclet status of each basic block
cleanup_kinds
:
IndexVec
<
mir
::
BasicBlock
,
analyze
::
CleanupKind
>
,
/// When targeting MSVC, this stores the cleanup info for each funclet
/// BB. This is initialized as we compute the funclets' head block in RPO.
funclets
:
&
'a
IndexVec
<
mir
::
BasicBlock
,
Option
<
Funclet
>>
,
/// This stores the landing-pad block for a given BB, computed lazily on GNU
/// and eagerly on MSVC.
landing_pads
:
IndexVec
<
mir
::
BasicBlock
,
Option
<
BasicBlockRef
>>
,
...
...
@@ -202,8 +206,11 @@ pub fn trans_mir<'a, 'tcx: 'a>(
debuginfo
::
create_function_debug_context
(
ccx
,
instance
,
sig
,
llfn
,
mir
);
let
bcx
=
Builder
::
new_block
(
ccx
,
llfn
,
"start"
);
let
cleanup_kinds
=
analyze
::
cleanup_kinds
(
&
mir
);
if
mir
.basic_blocks
()
.iter
()
.any
(|
bb
|
bb
.is_cleanup
)
{
bcx
.set_personality_fn
(
ccx
.eh_personality
());
}
let
cleanup_kinds
=
analyze
::
cleanup_kinds
(
&
mir
);
// Allocate a `Block` for every basic block, except
// the start block, if nothing loops back to it.
let
reentrant_start_block
=
!
mir
.predecessors_for
(
mir
::
START_BLOCK
)
.is_empty
();
...
...
@@ -218,6 +225,7 @@ pub fn trans_mir<'a, 'tcx: 'a>(
// Compute debuginfo scopes from MIR scopes.
let
scopes
=
debuginfo
::
create_mir_scopes
(
ccx
,
mir
,
&
debug_context
);
let
(
landing_pads
,
funclets
)
=
create_funclets
(
&
bcx
,
&
cleanup_kinds
,
&
block_bcxs
);
let
mut
mircx
=
MirContext
{
mir
:
mir
,
...
...
@@ -228,7 +236,8 @@ pub fn trans_mir<'a, 'tcx: 'a>(
blocks
:
block_bcxs
,
unreachable_block
:
None
,
cleanup_kinds
:
cleanup_kinds
,
landing_pads
:
IndexVec
::
from_elem
(
None
,
mir
.basic_blocks
()),
landing_pads
:
landing_pads
,
funclets
:
&
funclets
,
scopes
:
scopes
,
locals
:
IndexVec
::
new
(),
debug_context
:
debug_context
,
...
...
@@ -306,28 +315,13 @@ pub fn trans_mir<'a, 'tcx: 'a>(
// emitting should be enabled.
debuginfo
::
start_emitting_source_locations
(
&
mircx
.debug_context
);
let
funclets
:
IndexVec
<
mir
::
BasicBlock
,
Option
<
Funclet
>>
=
mircx
.cleanup_kinds
.iter_enumerated
()
.map
(|(
bb
,
cleanup_kind
)|
{
if
let
CleanupKind
::
Funclet
=
*
cleanup_kind
{
let
bcx
=
mircx
.get_builder
(
bb
);
unsafe
{
llvm
::
LLVMSetPersonalityFn
(
mircx
.llfn
,
mircx
.ccx
.eh_personality
());
}
if
base
::
wants_msvc_seh
(
ccx
.sess
())
{
return
Some
(
Funclet
::
new
(
bcx
.cleanup_pad
(
None
,
&
[])));
}
}
None
})
.collect
();
let
rpo
=
traversal
::
reverse_postorder
(
&
mir
);
let
mut
visited
=
BitVector
::
new
(
mir
.basic_blocks
()
.len
());
// Translate the body of each block using reverse postorder
for
(
bb
,
_
)
in
rpo
{
visited
.insert
(
bb
.index
());
mircx
.trans_block
(
bb
,
&
funclets
);
mircx
.trans_block
(
bb
);
}
// Remove blocks that haven't been visited, or have no
...
...
@@ -343,6 +337,26 @@ pub fn trans_mir<'a, 'tcx: 'a>(
}
}
fn
create_funclets
<
'a
,
'tcx
>
(
bcx
:
&
Builder
<
'a
,
'tcx
>
,
cleanup_kinds
:
&
IndexVec
<
mir
::
BasicBlock
,
CleanupKind
>
,
block_bcxs
:
&
IndexVec
<
mir
::
BasicBlock
,
BasicBlockRef
>
)
->
(
IndexVec
<
mir
::
BasicBlock
,
Option
<
BasicBlockRef
>>
,
IndexVec
<
mir
::
BasicBlock
,
Option
<
Funclet
>>
)
{
block_bcxs
.iter_enumerated
()
.zip
(
cleanup_kinds
)
.map
(|((
bb
,
&
llbb
),
cleanup_kind
)|
{
match
*
cleanup_kind
{
CleanupKind
::
Funclet
if
base
::
wants_msvc_seh
(
bcx
.sess
())
=>
{
let
cleanup_bcx
=
bcx
.build_sibling_block
(
&
format!
(
"funclet_{:?}"
,
bb
));
let
cleanup
=
cleanup_bcx
.cleanup_pad
(
None
,
&
[]);
cleanup_bcx
.br
(
llbb
);
(
Some
(
cleanup_bcx
.llbb
()),
Some
(
Funclet
::
new
(
cleanup
)))
}
_
=>
(
None
,
None
)
}
})
.unzip
()
}
/// Produce, for each argument, a `ValueRef` pointing at the
/// argument's value. As arguments are lvalues, these are always
/// indirect.
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录