Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
ee7687a5
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,发现更多精彩内容 >>
提交
ee7687a5
编写于
3月 08, 2016
作者:
E
Eduard Burtescu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
mir: Reintroduce the temporary block after invokes, to handle critical edges.
上级
41fc5f7c
变更
1
显示空白变更内容
内联
并排
Showing
1 changed file
with
59 addition
and
48 deletion
+59
-48
src/librustc_trans/trans/mir/block.rs
src/librustc_trans/trans/mir/block.rs
+59
-48
未找到文件。
src/librustc_trans/trans/mir/block.rs
浏览文件 @
ee7687a5
...
@@ -218,63 +218,74 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
...
@@ -218,63 +218,74 @@ pub fn trans_block(&mut self, bb: mir::BasicBlock) {
let
fn_ptr
=
callee
.reify
(
bcx
.ccx
())
.val
;
let
fn_ptr
=
callee
.reify
(
bcx
.ccx
())
.val
;
// Many different ways to call a function handled here
// Many different ways to call a function handled here
match
(
cleanup
,
destination
)
{
if
let
Some
(
cleanup
)
=
cleanup
.map
(|
bb
|
self
.bcx
(
bb
))
{
// The two cases below are the only ones to use LLVM’s `invoke`.
// We translate the copy into a temporary block. The temporary block is
(
&
Some
(
cleanup
),
&
None
)
=>
{
// necessary because the current block has already been terminated (by
let
cleanup
=
self
.bcx
(
cleanup
);
// `invoke`) and we cannot really translate into the target block
let
landingpad
=
self
.make_landing_pad
(
cleanup
);
// because:
let
unreachable_blk
=
self
.unreachable_block
();
// * The target block may have more than a single precedesor;
let
cs
=
bcx
.invoke
(
fn_ptr
,
// * Some LLVM insns cannot have a preceeding store insn (phi,
&
llargs
,
// cleanuppad), and adding/prepending the store now may render
unreachable_blk
.llbb
,
// those other instructions invalid.
landingpad
.llbb
(),
//
cleanup_bundle
.as_ref
());
// NB: This approach still may break some LLVM code. For example if the
fn_ty
.apply_attrs_callsite
(
cs
);
// target block starts with a `phi` (which may only match on immediate
landingpad
.at_start
(|
bcx
|
for
op
in
args
{
// precedesors), it cannot know about this temporary block thus
self
.set_operand_dropped
(
bcx
,
op
);
// resulting in an invalid code:
});
//
},
// this:
(
&
Some
(
cleanup
),
&
Some
((
_
,
success
)))
=>
{
// …
let
cleanup
=
self
.bcx
(
cleanup
);
// %0 = …
// %1 = invoke to label %temp …
// temp:
// store ty %1, ty* %dest
// br label %actualtargetblock
// actualtargetblock: ; preds: %temp, …
// phi … [%this, …], [%0, …] ; ERROR: phi requires to match only on
// ; immediate precedesors
let
ret_bcx
=
if
destination
.is_some
()
{
self
.fcx
.new_block
(
""
,
None
)
}
else
{
self
.unreachable_block
()
};
let
landingpad
=
self
.make_landing_pad
(
cleanup
);
let
landingpad
=
self
.make_landing_pad
(
cleanup
);
let
invokeret
=
bcx
.invoke
(
fn_ptr
,
let
invokeret
=
bcx
.invoke
(
fn_ptr
,
&
llargs
,
&
llargs
,
self
.llblock
(
success
)
,
ret_bcx
.llbb
,
landingpad
.llbb
(),
landingpad
.llbb
(),
cleanup_bundle
.as_ref
());
cleanup_bundle
.as_ref
());
fn_ty
.apply_attrs_callsite
(
invokeret
);
fn_ty
.apply_attrs_callsite
(
invokeret
);
if
let
Some
(
ret_dest
)
=
ret_dest
{
// We translate the copy straight into the beginning of the target
// block.
self
.bcx
(
success
)
.at_start
(|
bcx
|
bcx
.with_block
(
|
bcx
|
{
fn_ty
.ret
.store
(
bcx
,
invokeret
,
ret_dest
.llval
);
}));
}
self
.bcx
(
success
)
.at_start
(|
bcx
|
for
op
in
args
{
self
.set_operand_dropped
(
bcx
,
op
);
});
landingpad
.at_start
(|
bcx
|
for
op
in
args
{
landingpad
.at_start
(|
bcx
|
for
op
in
args
{
self
.set_operand_dropped
(
bcx
,
op
);
self
.set_operand_dropped
(
bcx
,
op
);
});
});
},
(
&
None
,
&
None
)
=>
{
if
let
Some
((
_
,
target
))
=
*
destination
{
let
cs
=
bcx
.call
(
fn_ptr
,
&
llargs
,
cleanup_bundle
.as_ref
());
let
ret_bcx
=
ret_bcx
.build
();
fn_ty
.apply_attrs_callsite
(
cs
);
if
let
Some
(
ret_dest
)
=
ret_dest
{
// no need to drop args, because the call never returns
fn_ty
.ret
.store
(
&
ret_bcx
,
invokeret
,
ret_dest
.llval
);
bcx
.unreachable
();
}
for
op
in
args
{
self
.set_operand_dropped
(
&
ret_bcx
,
op
);
}
}
(
&
None
,
&
Some
((
_
,
target
)))
=>
{
ret_bcx
.br
(
self
.llblock
(
target
));
}
}
else
{
let
llret
=
bcx
.call
(
fn_ptr
,
&
llargs
,
cleanup_bundle
.as_ref
());
let
llret
=
bcx
.call
(
fn_ptr
,
&
llargs
,
cleanup_bundle
.as_ref
());
fn_ty
.apply_attrs_callsite
(
llret
);
fn_ty
.apply_attrs_callsite
(
llret
);
if
let
Some
((
_
,
target
))
=
*
destination
{
if
let
Some
(
ret_dest
)
=
ret_dest
{
if
let
Some
(
ret_dest
)
=
ret_dest
{
bcx
.with_block
(|
bcx
|
{
fn_ty
.ret
.store
(
&
bcx
,
llret
,
ret_dest
.llval
);
fn_ty
.ret
.store
(
bcx
,
llret
,
ret_dest
.llval
);
});
}
}
for
op
in
args
{
for
op
in
args
{
self
.set_operand_dropped
(
&
bcx
,
op
);
self
.set_operand_dropped
(
&
bcx
,
op
);
}
}
funclet_br
(
bcx
,
self
.llblock
(
target
));
funclet_br
(
bcx
,
self
.llblock
(
target
));
}
else
{
// no need to drop args, because the call never returns
bcx
.unreachable
();
}
}
}
}
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录