Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
b3c1713b
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,发现更多精彩内容 >>
未验证
提交
b3c1713b
编写于
6月 10, 2016
作者:
O
Oliver Schneider
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
expose a minimal API and use it in the binary
上级
3b804942
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
127 addition
and
95 deletion
+127
-95
src/bin/miri.rs
src/bin/miri.rs
+82
-3
src/interpreter/mod.rs
src/interpreter/mod.rs
+27
-84
src/interpreter/stepper.rs
src/interpreter/stepper.rs
+3
-7
src/lib.rs
src/lib.rs
+15
-1
未找到文件。
src/bin/miri.rs
浏览文件 @
b3c1713b
...
...
@@ -7,11 +7,21 @@
extern
crate
rustc_driver
;
extern
crate
env_logger
;
extern
crate
log_settings
;
extern
crate
log
;
extern
crate
syntax
;
#[macro_use]
extern
crate
log
;
use
miri
::
interpreter
;
use
miri
::{
GlobalEvalContext
,
CachedMir
,
step
,
EvalError
,
Frame
,
};
use
rustc
::
session
::
Session
;
use
rustc_driver
::{
driver
,
CompilerCalls
};
use
rustc
::
ty
::{
TyCtxt
,
subst
};
use
rustc
::
mir
::
mir_map
::
MirMap
;
use
rustc
::
hir
::
def_id
::
DefId
;
struct
MiriCompilerCalls
;
...
...
@@ -25,13 +35,82 @@ fn build_controller(
control
.after_analysis.callback
=
Box
::
new
(|
state
|
{
state
.session
.abort_if_errors
();
interpret
er
::
interpret
_start_points
(
state
.tcx
.unwrap
(),
state
.mir_map
.unwrap
());
interpret_start_points
(
state
.tcx
.unwrap
(),
state
.mir_map
.unwrap
());
});
control
}
}
fn
interpret_start_points
<
'a
,
'tcx
>
(
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
mir_map
:
&
MirMap
<
'tcx
>
,
)
{
let
initial_indentation
=
::
log_settings
::
settings
()
.indentation
;
for
(
&
id
,
mir
)
in
&
mir_map
.map
{
for
attr
in
tcx
.map
.attrs
(
id
)
{
use
syntax
::
attr
::
AttrMetaMethods
;
if
attr
.check_name
(
"miri_run"
)
{
let
item
=
tcx
.map
.expect_item
(
id
);
::
log_settings
::
settings
()
.indentation
=
initial_indentation
;
debug!
(
"Interpreting: {}"
,
item
.name
);
let
mut
gecx
=
GlobalEvalContext
::
new
(
tcx
,
mir_map
);
let
substs
=
tcx
.mk_substs
(
subst
::
Substs
::
empty
());
let
return_ptr
=
gecx
.alloc_ret_ptr
(
mir
.return_ty
,
substs
);
gecx
.push_stack_frame
(
tcx
.map
.local_def_id
(
id
),
mir
.span
,
CachedMir
::
Ref
(
mir
),
substs
,
return_ptr
);
loop
{
match
(
step
(
&
mut
gecx
),
return_ptr
)
{
(
Ok
(
true
),
_
)
=>
{},
(
Ok
(
false
),
Some
(
ptr
))
=>
if
log_enabled!
(::
log
::
LogLevel
::
Debug
)
{
gecx
.memory
()
.dump
(
ptr
.alloc_id
);
break
;
},
(
Ok
(
false
),
None
)
=>
{
warn!
(
"diverging function returned"
);
break
;
},
// FIXME: diverging functions can end up here in some future miri
(
Err
(
e
),
_
)
=>
{
report
(
tcx
,
&
gecx
,
e
);
break
;
},
}
}
}
}
}
}
fn
report
(
tcx
:
TyCtxt
,
gecx
:
&
GlobalEvalContext
,
e
:
EvalError
)
{
let
frame
=
gecx
.stack
()
.last
()
.expect
(
"stackframe was empty"
);
let
block
=
frame
.mir
.basic_block_data
(
frame
.next_block
);
let
span
=
if
frame
.stmt
<
block
.statements
.len
()
{
block
.statements
[
frame
.stmt
]
.span
}
else
{
block
.terminator
()
.span
};
let
mut
err
=
tcx
.sess
.struct_span_err
(
span
,
&
e
.to_string
());
for
&
Frame
{
def_id
,
substs
,
span
,
..
}
in
gecx
.stack
()
.iter
()
.rev
()
{
// FIXME(solson): Find a way to do this without this Display impl hack.
use
rustc
::
util
::
ppaux
;
use
std
::
fmt
;
struct
Instance
<
'tcx
>
(
DefId
,
&
'tcx
subst
::
Substs
<
'tcx
>
);
impl
<
'tcx
>
fmt
::
Display
for
Instance
<
'tcx
>
{
fn
fmt
(
&
self
,
f
:
&
mut
fmt
::
Formatter
)
->
fmt
::
Result
{
ppaux
::
parameterized
(
f
,
self
.1
,
self
.0
,
ppaux
::
Ns
::
Value
,
&
[],
|
tcx
|
tcx
.lookup_item_type
(
self
.0
)
.generics
)
}
}
err
.span_note
(
span
,
&
format!
(
"inside call to {}"
,
Instance
(
def_id
,
substs
)));
}
err
.emit
();
}
#[miri_run]
fn
main
()
{
init_logger
();
...
...
src/interpreter/mod.rs
浏览文件 @
b3c1713b
...
...
@@ -24,6 +24,10 @@
mod
stepper
;
pub
fn
step
<
'fncx
,
'a
:
'fncx
,
'tcx
:
'a
>
(
gecx
:
&
'fncx
mut
GlobalEvalContext
<
'a
,
'tcx
>
)
->
EvalResult
<
bool
>
{
stepper
::
Stepper
::
new
(
gecx
)
.step
()
}
pub
struct
GlobalEvalContext
<
'a
,
'tcx
:
'a
>
{
/// The results of the type checker, from rustc.
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
...
...
@@ -45,38 +49,38 @@ pub struct GlobalEvalContext<'a, 'tcx: 'a> {
}
/// A stack frame.
struct
Frame
<
'a
,
'tcx
:
'a
>
{
pub
struct
Frame
<
'a
,
'tcx
:
'a
>
{
/// The def_id of the current function
def_id
:
DefId
,
pub
def_id
:
DefId
,
/// The span of the call site
span
:
codemap
::
Span
,
pub
span
:
codemap
::
Span
,
/// type substitutions for the current function invocation
substs
:
&
'tcx
Substs
<
'tcx
>
,
pub
substs
:
&
'tcx
Substs
<
'tcx
>
,
/// The MIR for the function called on this frame.
mir
:
CachedMir
<
'a
,
'tcx
>
,
pub
mir
:
CachedMir
<
'a
,
'tcx
>
,
/// The block that is currently executed (or will be executed after the above call stacks return)
next_block
:
mir
::
BasicBlock
,
pub
next_block
:
mir
::
BasicBlock
,
/// A pointer for writing the return value of the current call if it's not a diverging call.
return_ptr
:
Option
<
Pointer
>
,
pub
return_ptr
:
Option
<
Pointer
>
,
/// The list of locals for the current function, stored in order as
/// `[arguments..., variables..., temporaries...]`. The variables begin at `self.var_offset`
/// and the temporaries at `self.temp_offset`.
locals
:
Vec
<
Pointer
>
,
pub
locals
:
Vec
<
Pointer
>
,
/// The offset of the first variable in `self.locals`.
var_offset
:
usize
,
pub
var_offset
:
usize
,
/// The offset of the first temporary in `self.locals`.
temp_offset
:
usize
,
pub
temp_offset
:
usize
,
/// The index of the currently evaluated statment
stmt
:
usize
,
pub
stmt
:
usize
,
}
#[derive(Copy,
Clone,
Debug,
Eq,
PartialEq)]
...
...
@@ -94,7 +98,7 @@ enum LvalueExtra {
}
#[derive(Clone)]
enum
CachedMir
<
'mir
,
'tcx
:
'mir
>
{
pub
enum
CachedMir
<
'mir
,
'tcx
:
'mir
>
{
Ref
(
&
'mir
mir
::
Mir
<
'tcx
>
),
Owned
(
Rc
<
mir
::
Mir
<
'tcx
>>
)
}
...
...
@@ -120,7 +124,7 @@ enum ConstantKind {
}
impl
<
'a
,
'tcx
>
GlobalEvalContext
<
'a
,
'tcx
>
{
fn
new
(
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
mir_map
:
&
'a
MirMap
<
'tcx
>
)
->
Self
{
pub
fn
new
(
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
mir_map
:
&
'a
MirMap
<
'tcx
>
)
->
Self
{
GlobalEvalContext
{
tcx
:
tcx
,
mir_map
:
mir_map
,
...
...
@@ -135,7 +139,7 @@ fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir_map: &'a MirMap<'tcx>) -> Self {
}
}
fn
alloc_ret_ptr
(
&
mut
self
,
output_ty
:
ty
::
FnOutput
<
'tcx
>
,
substs
:
&
'tcx
Substs
<
'tcx
>
)
->
Option
<
Pointer
>
{
pub
fn
alloc_ret_ptr
(
&
mut
self
,
output_ty
:
ty
::
FnOutput
<
'tcx
>
,
substs
:
&
'tcx
Substs
<
'tcx
>
)
->
Option
<
Pointer
>
{
match
output_ty
{
ty
::
FnConverging
(
ty
)
=>
{
let
size
=
self
.type_size
(
ty
,
substs
);
...
...
@@ -145,6 +149,14 @@ fn alloc_ret_ptr(&mut self, output_ty: ty::FnOutput<'tcx>, substs: &'tcx Substs<
}
}
pub
fn
memory
(
&
self
)
->
&
Memory
{
&
self
.memory
}
pub
fn
stack
(
&
self
)
->
&
[
Frame
]
{
&
self
.stack
}
// TODO(solson): Try making const_to_primval instead.
fn
const_to_ptr
(
&
mut
self
,
const_val
:
&
const_val
::
ConstVal
)
->
EvalResult
<
Pointer
>
{
use
rustc
::
middle
::
const_val
::
ConstVal
::
*
;
...
...
@@ -308,34 +320,7 @@ fn type_layout(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> &'tcx Layout
})
}
#[inline(never)]
#[cold]
fn
report
(
&
self
,
e
:
EvalError
)
{
let
stmt
=
self
.frame
()
.stmt
;
let
block
=
self
.basic_block
();
let
span
=
if
stmt
<
block
.statements
.len
()
{
block
.statements
[
stmt
]
.span
}
else
{
block
.terminator
()
.span
};
let
mut
err
=
self
.tcx.sess
.struct_span_err
(
span
,
&
e
.to_string
());
for
&
Frame
{
def_id
,
substs
,
span
,
..
}
in
self
.stack
.iter
()
.rev
()
{
// FIXME(solson): Find a way to do this without this Display impl hack.
use
rustc
::
util
::
ppaux
;
use
std
::
fmt
;
struct
Instance
<
'tcx
>
(
DefId
,
&
'tcx
Substs
<
'tcx
>
);
impl
<
'tcx
>
fmt
::
Display
for
Instance
<
'tcx
>
{
fn
fmt
(
&
self
,
f
:
&
mut
fmt
::
Formatter
)
->
fmt
::
Result
{
ppaux
::
parameterized
(
f
,
self
.1
,
self
.0
,
ppaux
::
Ns
::
Value
,
&
[],
|
tcx
|
tcx
.lookup_item_type
(
self
.0
)
.generics
)
}
}
err
.span_note
(
span
,
&
format!
(
"inside call to {}"
,
Instance
(
def_id
,
substs
)));
}
err
.emit
();
}
fn
push_stack_frame
(
&
mut
self
,
def_id
:
DefId
,
span
:
codemap
::
Span
,
mir
:
CachedMir
<
'a
,
'tcx
>
,
substs
:
&
'tcx
Substs
<
'tcx
>
,
pub
fn
push_stack_frame
(
&
mut
self
,
def_id
:
DefId
,
span
:
codemap
::
Span
,
mir
:
CachedMir
<
'a
,
'tcx
>
,
substs
:
&
'tcx
Substs
<
'tcx
>
,
return_ptr
:
Option
<
Pointer
>
)
{
let
arg_tys
=
mir
.arg_decls
.iter
()
.map
(|
a
|
a
.ty
);
...
...
@@ -1387,48 +1372,6 @@ pub fn get_impl_method<'a, 'tcx>(
}
}
pub
fn
interpret_start_points
<
'a
,
'tcx
>
(
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
mir_map
:
&
MirMap
<
'tcx
>
,
)
{
let
initial_indentation
=
::
log_settings
::
settings
()
.indentation
;
for
(
&
id
,
mir
)
in
&
mir_map
.map
{
for
attr
in
tcx
.map
.attrs
(
id
)
{
use
syntax
::
attr
::
AttrMetaMethods
;
if
attr
.check_name
(
"miri_run"
)
{
let
item
=
tcx
.map
.expect_item
(
id
);
::
log_settings
::
settings
()
.indentation
=
initial_indentation
;
debug!
(
"Interpreting: {}"
,
item
.name
);
let
mut
gecx
=
GlobalEvalContext
::
new
(
tcx
,
mir_map
);
let
substs
=
tcx
.mk_substs
(
subst
::
Substs
::
empty
());
let
return_ptr
=
gecx
.alloc_ret_ptr
(
mir
.return_ty
,
substs
);
gecx
.push_stack_frame
(
tcx
.map
.local_def_id
(
id
),
mir
.span
,
CachedMir
::
Ref
(
mir
),
substs
,
return_ptr
);
loop
{
match
(
stepper
::
step
(
&
mut
gecx
),
return_ptr
)
{
(
Ok
(
true
),
_
)
=>
{},
(
Ok
(
false
),
Some
(
ptr
))
=>
if
log_enabled!
(::
log
::
LogLevel
::
Debug
)
{
gecx
.memory
.dump
(
ptr
.alloc_id
);
break
;
},
(
Ok
(
false
),
None
)
=>
{
warn!
(
"diverging function returned"
);
break
;
},
// FIXME: diverging functions can end up here in some future miri
(
Err
(
e
),
_
)
=>
{
gecx
.report
(
e
);
break
;
},
}
}
}
}
}
}
// TODO(solson): Upstream these methods into rustc::ty::layout.
trait
IntegerExt
{
...
...
src/interpreter/stepper.rs
浏览文件 @
b3c1713b
...
...
@@ -12,16 +12,12 @@
use
syntax
::
codemap
::
Span
;
use
std
::
rc
::
Rc
;
struct
Stepper
<
'fncx
,
'a
:
'fncx
,
'tcx
:
'a
>
{
pub
(
super
)
struct
Stepper
<
'fncx
,
'a
:
'fncx
,
'tcx
:
'a
>
{
gecx
:
&
'fncx
mut
GlobalEvalContext
<
'a
,
'tcx
>
,
}
pub
fn
step
<
'fncx
,
'a
:
'fncx
,
'tcx
:
'a
>
(
gecx
:
&
'fncx
mut
GlobalEvalContext
<
'a
,
'tcx
>
)
->
EvalResult
<
bool
>
{
Stepper
::
new
(
gecx
)
.step
()
}
impl
<
'fncx
,
'a
,
'tcx
>
Stepper
<
'fncx
,
'a
,
'tcx
>
{
fn
new
(
gecx
:
&
'fncx
mut
GlobalEvalContext
<
'a
,
'tcx
>
)
->
Self
{
pub
(
super
)
fn
new
(
gecx
:
&
'fncx
mut
GlobalEvalContext
<
'a
,
'tcx
>
)
->
Self
{
Stepper
{
gecx
:
gecx
,
}
...
...
@@ -47,7 +43,7 @@ fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> EvalResult<()> {
}
// returns true as long as there are more things to do
fn
step
(
&
mut
self
)
->
EvalResult
<
bool
>
{
pub
(
super
)
fn
step
(
&
mut
self
)
->
EvalResult
<
bool
>
{
if
self
.gecx.stack
.is_empty
()
{
return
Ok
(
false
);
}
...
...
src/lib.rs
浏览文件 @
b3c1713b
...
...
@@ -20,6 +20,20 @@
extern
crate
byteorder
;
mod
error
;
pub
mod
interpreter
;
mod
interpreter
;
mod
memory
;
mod
primval
;
pub
use
error
::{
EvalError
,
EvalResult
,
};
pub
use
interpreter
::{
GlobalEvalContext
,
step
,
Frame
,
CachedMir
,
};
pub
use
memory
::
Memory
;
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录