Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
e8a22b69
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,发现更多精彩内容 >>
提交
e8a22b69
编写于
10月 26, 2018
作者:
O
Oliver Scherer
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Rename `Value` to `Immediate` for miri
上级
87a3c1ee
变更
14
隐藏空白更改
内联
并排
Showing
14 changed file
with
189 addition
and
186 deletion
+189
-186
src/librustc_mir/const_eval.rs
src/librustc_mir/const_eval.rs
+4
-4
src/librustc_mir/interpret/cast.rs
src/librustc_mir/interpret/cast.rs
+19
-19
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/eval_context.rs
+7
-7
src/librustc_mir/interpret/intrinsics.rs
src/librustc_mir/interpret/intrinsics.rs
+12
-12
src/librustc_mir/interpret/mod.rs
src/librustc_mir/interpret/mod.rs
+1
-1
src/librustc_mir/interpret/operand.rs
src/librustc_mir/interpret/operand.rs
+73
-70
src/librustc_mir/interpret/operator.rs
src/librustc_mir/interpret/operator.rs
+9
-9
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/place.rs
+34
-34
src/librustc_mir/interpret/snapshot.rs
src/librustc_mir/interpret/snapshot.rs
+3
-3
src/librustc_mir/interpret/step.rs
src/librustc_mir/interpret/step.rs
+6
-6
src/librustc_mir/interpret/terminator.rs
src/librustc_mir/interpret/terminator.rs
+7
-7
src/librustc_mir/interpret/validity.rs
src/librustc_mir/interpret/validity.rs
+3
-3
src/librustc_mir/transform/const_prop.rs
src/librustc_mir/transform/const_prop.rs
+10
-10
src/tools/linkchecker/main.rs
src/tools/linkchecker/main.rs
+1
-1
未找到文件。
src/librustc_mir/const_eval.rs
浏览文件 @
e8a22b69
...
...
@@ -32,7 +32,7 @@
use
syntax
::
source_map
::{
Span
,
DUMMY_SP
};
use
interpret
::{
self
,
PlaceTy
,
MemPlace
,
OpTy
,
Operand
,
Valu
e
,
Scalar
,
ConstValue
,
Pointer
,
PlaceTy
,
MemPlace
,
OpTy
,
Operand
,
Immediat
e
,
Scalar
,
ConstValue
,
Pointer
,
EvalResult
,
EvalError
,
EvalErrorKind
,
GlobalId
,
EvalContext
,
StackPopCleanup
,
Allocation
,
AllocId
,
MemoryKind
,
snapshot
,
RefTracking
,
...
...
@@ -115,7 +115,7 @@ pub fn op_to_const<'tcx>(
_
=>
false
,
};
let
normalized_op
=
if
normalize
{
ecx
.try_read_
valu
e
(
op
)
?
ecx
.try_read_
immediat
e
(
op
)
?
}
else
{
match
op
.op
{
Operand
::
Indirect
(
mplace
)
=>
Err
(
mplace
),
...
...
@@ -137,9 +137,9 @@ pub fn op_to_const<'tcx>(
let
alloc
=
ecx
.tcx
.intern_const_alloc
(
alloc
);
ConstValue
::
ByRef
(
ptr
.alloc_id
,
alloc
,
ptr
.offset
)
},
Ok
(
Valu
e
::
Scalar
(
x
))
=>
Ok
(
Immediat
e
::
Scalar
(
x
))
=>
ConstValue
::
Scalar
(
x
.not_undef
()
?
),
Ok
(
Valu
e
::
ScalarPair
(
a
,
b
))
=>
Ok
(
Immediat
e
::
ScalarPair
(
a
,
b
))
=>
ConstValue
::
ScalarPair
(
a
.not_undef
()
?
,
b
.not_undef
()
?
),
};
Ok
(
ty
::
Const
::
from_const_value
(
ecx
.tcx.tcx
,
val
,
op
.layout.ty
))
...
...
src/librustc_mir/interpret/cast.rs
浏览文件 @
e8a22b69
...
...
@@ -19,7 +19,7 @@
use
rustc
::
mir
::
CastKind
;
use
rustc_apfloat
::
Float
;
use
super
::{
EvalContext
,
Machine
,
PlaceTy
,
OpTy
,
Valu
e
};
use
super
::{
EvalContext
,
Machine
,
PlaceTy
,
OpTy
,
Immediat
e
};
impl
<
'a
,
'mir
,
'tcx
,
M
:
Machine
<
'a
,
'mir
,
'tcx
>>
EvalContext
<
'a
,
'mir
,
'tcx
,
M
>
{
fn
type_is_fat_ptr
(
&
self
,
ty
:
Ty
<
'tcx
>
)
->
bool
{
...
...
@@ -45,7 +45,7 @@ pub fn cast(
Misc
=>
{
let
src_layout
=
src
.layout
;
let
src
=
self
.read_
valu
e
(
src
)
?
;
let
src
=
self
.read_
immediat
e
(
src
)
?
;
let
src
=
if
M
::
ENABLE_PTR_TRACKING_HOOKS
&&
src_layout
.ty
.is_region_ptr
()
{
// The only `Misc` casts on references are those creating raw pointers.
...
...
@@ -61,14 +61,14 @@ pub fn cast(
if
self
.type_is_fat_ptr
(
src_layout
.ty
)
{
match
(
src
,
self
.type_is_fat_ptr
(
dest
.layout.ty
))
{
// pointers to extern types
(
Valu
e
::
Scalar
(
_
),
_
)
|
(
Immediat
e
::
Scalar
(
_
),
_
)
|
// slices and trait objects to other slices/trait objects
(
Valu
e
::
ScalarPair
(
..
),
true
)
=>
{
// No change to
valu
e
self
.write_
valu
e
(
src
,
dest
)
?
;
(
Immediat
e
::
ScalarPair
(
..
),
true
)
=>
{
// No change to
immediat
e
self
.write_
immediat
e
(
src
,
dest
)
?
;
}
// slices and trait objects to thin pointers (dropping the metadata)
(
Valu
e
::
ScalarPair
(
data
,
_
),
false
)
=>
{
(
Immediat
e
::
ScalarPair
(
data
,
_
),
false
)
=>
{
self
.write_scalar
(
data
,
dest
)
?
;
}
}
...
...
@@ -118,11 +118,11 @@ pub fn cast(
}
UnsafeFnPointer
=>
{
let
src
=
self
.read_
valu
e
(
src
)
?
;
let
src
=
self
.read_
immediat
e
(
src
)
?
;
match
dest
.layout.ty.sty
{
ty
::
FnPtr
(
_
)
=>
{
// No change to value
self
.write_
valu
e
(
*
src
,
dest
)
?
;
self
.write_
immediat
e
(
*
src
,
dest
)
?
;
}
ref
other
=>
bug!
(
"fn to unsafe fn cast on {:?}"
,
other
),
}
...
...
@@ -144,8 +144,8 @@ pub fn cast(
ty
::
ClosureKind
::
FnOnce
,
);
let
fn_ptr
=
self
.memory
.create_fn_alloc
(
instance
)
.with_default_tag
();
let
val
=
Valu
e
::
Scalar
(
Scalar
::
Ptr
(
fn_ptr
.into
())
.into
());
self
.write_
valu
e
(
val
,
dest
)
?
;
let
val
=
Immediat
e
::
Scalar
(
Scalar
::
Ptr
(
fn_ptr
.into
())
.into
());
self
.write_
immediat
e
(
val
,
dest
)
?
;
}
ref
other
=>
bug!
(
"closure fn pointer on {:?}"
,
other
),
}
...
...
@@ -326,24 +326,24 @@ fn unsize_into_ptr(
match
(
&
src_pointee_ty
.sty
,
&
dest_pointee_ty
.sty
)
{
(
&
ty
::
Array
(
_
,
length
),
&
ty
::
Slice
(
_
))
=>
{
let
ptr
=
self
.read_
valu
e
(
src
)
?
.to_scalar_ptr
()
?
;
let
ptr
=
self
.read_
immediat
e
(
src
)
?
.to_scalar_ptr
()
?
;
// u64 cast is from usize to u64, which is always good
let
val
=
Valu
e
::
new_slice
(
ptr
,
length
.unwrap_usize
(
self
.tcx.tcx
),
self
.tcx.tcx
);
self
.write_
valu
e
(
val
,
dest
)
let
val
=
Immediat
e
::
new_slice
(
ptr
,
length
.unwrap_usize
(
self
.tcx.tcx
),
self
.tcx.tcx
);
self
.write_
immediat
e
(
val
,
dest
)
}
(
&
ty
::
Dynamic
(
..
),
&
ty
::
Dynamic
(
..
))
=>
{
// For now, upcasts are limited to changes in marker
// traits, and hence never actually require an actual
// change to the vtable.
let
val
=
self
.read_
valu
e
(
src
)
?
;
self
.write_
valu
e
(
*
val
,
dest
)
let
val
=
self
.read_
immediat
e
(
src
)
?
;
self
.write_
immediat
e
(
*
val
,
dest
)
}
(
_
,
&
ty
::
Dynamic
(
ref
data
,
_
))
=>
{
// Initial cast from sized to dyn trait
let
vtable
=
self
.get_vtable
(
src_pointee_ty
,
data
.principal
())
?
;
let
ptr
=
self
.read_
valu
e
(
src
)
?
.to_scalar_ptr
()
?
;
let
val
=
Valu
e
::
new_dyn_trait
(
ptr
,
vtable
);
self
.write_
valu
e
(
val
,
dest
)
let
ptr
=
self
.read_
immediat
e
(
src
)
?
.to_scalar_ptr
()
?
;
let
val
=
Immediat
e
::
new_dyn_trait
(
ptr
,
vtable
);
self
.write_
immediat
e
(
val
,
dest
)
}
_
=>
bug!
(
"invalid unsizing {:?} -> {:?}"
,
src
.layout.ty
,
dest
.layout.ty
),
...
...
src/librustc_mir/interpret/eval_context.rs
浏览文件 @
e8a22b69
...
...
@@ -32,7 +32,7 @@
use
rustc_data_structures
::
fx
::
FxHashMap
;
use
super
::{
Valu
e
,
Operand
,
MemPlace
,
MPlaceTy
,
Place
,
PlaceTy
,
ScalarMaybeUndef
,
Immediat
e
,
Operand
,
MemPlace
,
MPlaceTy
,
Place
,
PlaceTy
,
ScalarMaybeUndef
,
Memory
,
Machine
};
...
...
@@ -333,9 +333,9 @@ pub fn layout_of_local(
self
.layout_of
(
local_ty
)
}
pub
fn
str_to_
value
(
&
mut
self
,
s
:
&
str
)
->
EvalResult
<
'tcx
,
Valu
e
<
M
::
PointerTag
>>
{
pub
fn
str_to_
immediate
(
&
mut
self
,
s
:
&
str
)
->
EvalResult
<
'tcx
,
Immediat
e
<
M
::
PointerTag
>>
{
let
ptr
=
self
.memory
.allocate_static_bytes
(
s
.as_bytes
())
.with_default_tag
();
Ok
(
Valu
e
::
new_slice
(
Scalar
::
Ptr
(
ptr
),
s
.len
()
as
u64
,
self
.tcx.tcx
))
Ok
(
Immediat
e
::
new_slice
(
Scalar
::
Ptr
(
ptr
),
s
.len
()
as
u64
,
self
.tcx.tcx
))
}
/// Return the actual dynamic size and alignment of the place at the given type.
...
...
@@ -457,11 +457,11 @@ pub fn push_stack_frame(
// don't allocate at all for trivial constants
if
mir
.local_decls
.len
()
>
1
{
// We put some marker
valu
e into the locals that we later want to initialize.
// We put some marker
immediat
e into the locals that we later want to initialize.
// This can be anything except for LocalValue::Dead -- because *that* is the
// value we use for things that we know are initially dead.
let
dummy
=
LocalValue
::
Live
(
Operand
::
Immediate
(
Valu
e
::
Scalar
(
ScalarMaybeUndef
::
Undef
)));
LocalValue
::
Live
(
Operand
::
Immediate
(
Immediat
e
::
Scalar
(
ScalarMaybeUndef
::
Undef
)));
let
mut
locals
=
IndexVec
::
from_elem
(
dummy
,
&
mir
.local_decls
);
// Return place is handled specially by the `eval_place` functions, and the
// entry in `locals` should never be used. Make it dead, to be sure.
...
...
@@ -652,13 +652,13 @@ pub fn dump_place(&self, place: Place<M::PointerTag>) {
ptr
=>
write!
(
msg
,
" by integral ref: {:?}"
,
ptr
)
.unwrap
(),
}
}
Ok
(
Operand
::
Immediate
(
Valu
e
::
Scalar
(
val
)))
=>
{
Ok
(
Operand
::
Immediate
(
Immediat
e
::
Scalar
(
val
)))
=>
{
write!
(
msg
,
" {:?}"
,
val
)
.unwrap
();
if
let
ScalarMaybeUndef
::
Scalar
(
Scalar
::
Ptr
(
ptr
))
=
val
{
allocs
.push
(
ptr
.alloc_id
);
}
}
Ok
(
Operand
::
Immediate
(
Valu
e
::
ScalarPair
(
val1
,
val2
)))
=>
{
Ok
(
Operand
::
Immediate
(
Immediat
e
::
ScalarPair
(
val1
,
val2
)))
=>
{
write!
(
msg
,
" ({:?}, {:?})"
,
val1
,
val2
)
.unwrap
();
if
let
ScalarMaybeUndef
::
Scalar
(
Scalar
::
Ptr
(
ptr
))
=
val1
{
allocs
.push
(
ptr
.alloc_id
);
...
...
src/librustc_mir/interpret/intrinsics.rs
浏览文件 @
e8a22b69
...
...
@@ -115,8 +115,8 @@ pub fn emulate_intrinsic(
|
"add_with_overflow"
|
"sub_with_overflow"
|
"mul_with_overflow"
=>
{
let
lhs
=
self
.read_
valu
e
(
args
[
0
])
?
;
let
rhs
=
self
.read_
valu
e
(
args
[
1
])
?
;
let
lhs
=
self
.read_
immediat
e
(
args
[
0
])
?
;
let
rhs
=
self
.read_
immediat
e
(
args
[
1
])
?
;
let
(
bin_op
,
ignore_overflow
)
=
match
intrinsic_name
{
"overflowing_add"
=>
(
BinOp
::
Add
,
true
),
"overflowing_sub"
=>
(
BinOp
::
Sub
,
true
),
...
...
@@ -133,8 +133,8 @@ pub fn emulate_intrinsic(
}
}
"unchecked_shl"
|
"unchecked_shr"
=>
{
let
l
=
self
.read_
valu
e
(
args
[
0
])
?
;
let
r
=
self
.read_
valu
e
(
args
[
1
])
?
;
let
l
=
self
.read_
immediat
e
(
args
[
0
])
?
;
let
r
=
self
.read_
immediat
e
(
args
[
1
])
?
;
let
bin_op
=
match
intrinsic_name
{
"unchecked_shl"
=>
BinOp
::
Shl
,
"unchecked_shr"
=>
BinOp
::
Shr
,
...
...
@@ -172,8 +172,8 @@ pub fn hook_fn(
// Some fn calls are actually BinOp intrinsics
if
let
Some
((
op
,
oflo
))
=
self
.tcx
.is_binop_lang_item
(
def_id
)
{
let
dest
=
dest
.expect
(
"128 lowerings can't diverge"
);
let
l
=
self
.read_
valu
e
(
args
[
0
])
?
;
let
r
=
self
.read_
valu
e
(
args
[
1
])
?
;
let
l
=
self
.read_
immediat
e
(
args
[
0
])
?
;
let
r
=
self
.read_
immediat
e
(
args
[
1
])
?
;
if
oflo
{
self
.binop_with_overflow
(
op
,
l
,
r
,
dest
)
?
;
}
else
{
...
...
@@ -183,7 +183,7 @@ pub fn hook_fn(
}
else
if
Some
(
def_id
)
==
self
.tcx
.lang_items
()
.panic_fn
()
{
assert
!
(
args
.len
()
==
1
);
// &(&'static str, &'static str, u32, u32)
let
ptr
=
self
.read_
valu
e
(
args
[
0
])
?
;
let
ptr
=
self
.read_
immediat
e
(
args
[
0
])
?
;
let
place
=
self
.ref_to_mplace
(
ptr
)
?
;
let
(
msg
,
file
,
line
,
col
)
=
(
self
.mplace_field
(
place
,
0
)
?
,
...
...
@@ -192,9 +192,9 @@ pub fn hook_fn(
self
.mplace_field
(
place
,
3
)
?
,
);
let
msg_place
=
self
.ref_to_mplace
(
self
.read_
valu
e
(
msg
.into
())
?
)
?
;
let
msg_place
=
self
.ref_to_mplace
(
self
.read_
immediat
e
(
msg
.into
())
?
)
?
;
let
msg
=
Symbol
::
intern
(
self
.read_str
(
msg_place
)
?
);
let
file_place
=
self
.ref_to_mplace
(
self
.read_
valu
e
(
file
.into
())
?
)
?
;
let
file_place
=
self
.ref_to_mplace
(
self
.read_
immediat
e
(
file
.into
())
?
)
?
;
let
file
=
Symbol
::
intern
(
self
.read_str
(
file_place
)
?
);
let
line
=
self
.read_scalar
(
line
.into
())
?
.to_u32
()
?
;
let
col
=
self
.read_scalar
(
col
.into
())
?
.to_u32
()
?
;
...
...
@@ -203,7 +203,7 @@ pub fn hook_fn(
assert
!
(
args
.len
()
==
2
);
// &'static str, &(&'static str, u32, u32)
let
msg
=
args
[
0
];
let
ptr
=
self
.read_
valu
e
(
args
[
1
])
?
;
let
ptr
=
self
.read_
immediat
e
(
args
[
1
])
?
;
let
place
=
self
.ref_to_mplace
(
ptr
)
?
;
let
(
file
,
line
,
col
)
=
(
self
.mplace_field
(
place
,
0
)
?
,
...
...
@@ -211,9 +211,9 @@ pub fn hook_fn(
self
.mplace_field
(
place
,
2
)
?
,
);
let
msg_place
=
self
.ref_to_mplace
(
self
.read_
valu
e
(
msg
.into
())
?
)
?
;
let
msg_place
=
self
.ref_to_mplace
(
self
.read_
immediat
e
(
msg
.into
())
?
)
?
;
let
msg
=
Symbol
::
intern
(
self
.read_str
(
msg_place
)
?
);
let
file_place
=
self
.ref_to_mplace
(
self
.read_
valu
e
(
file
.into
())
?
)
?
;
let
file_place
=
self
.ref_to_mplace
(
self
.read_
immediat
e
(
file
.into
())
?
)
?
;
let
file
=
Symbol
::
intern
(
self
.read_str
(
file_place
)
?
);
let
line
=
self
.read_scalar
(
line
.into
())
?
.to_u32
()
?
;
let
col
=
self
.read_scalar
(
col
.into
())
?
.to_u32
()
?
;
...
...
src/librustc_mir/interpret/mod.rs
浏览文件 @
e8a22b69
...
...
@@ -36,6 +36,6 @@
pub
use
self
::
machine
::{
Machine
,
AllocMap
,
MayLeak
};
pub
use
self
::
operand
::{
ScalarMaybeUndef
,
Value
,
Val
Ty
,
Operand
,
OpTy
};
pub
use
self
::
operand
::{
ScalarMaybeUndef
,
Immediate
,
Imm
Ty
,
Operand
,
OpTy
};
pub
use
self
::
validity
::
RefTracking
;
src/librustc_mir/interpret/operand.rs
浏览文件 @
e8a22b69
...
...
@@ -146,32 +146,32 @@ pub fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'tcx, i64> {
/// In particular, thanks to `ScalarPair`, arithmetic operations and casts can be entirely
/// defined on `Value`, and do not have to work with a `Place`.
#[derive(Copy,
Clone,
Debug,
Hash,
PartialEq,
Eq)]
pub
enum
Valu
e
<
Tag
=
(),
Id
=
AllocId
>
{
pub
enum
Immediat
e
<
Tag
=
(),
Id
=
AllocId
>
{
Scalar
(
ScalarMaybeUndef
<
Tag
,
Id
>
),
ScalarPair
(
ScalarMaybeUndef
<
Tag
,
Id
>
,
ScalarMaybeUndef
<
Tag
,
Id
>
),
}
impl
Valu
e
{
impl
Immediat
e
{
#[inline]
pub
fn
with_default_tag
<
Tag
>
(
self
)
->
Valu
e
<
Tag
>
pub
fn
with_default_tag
<
Tag
>
(
self
)
->
Immediat
e
<
Tag
>
where
Tag
:
Default
{
match
self
{
Value
::
Scalar
(
x
)
=>
Valu
e
::
Scalar
(
x
.with_default_tag
()),
Valu
e
::
ScalarPair
(
x
,
y
)
=>
Valu
e
::
ScalarPair
(
x
.with_default_tag
(),
y
.with_default_tag
()),
Immediate
::
Scalar
(
x
)
=>
Immediat
e
::
Scalar
(
x
.with_default_tag
()),
Immediat
e
::
ScalarPair
(
x
,
y
)
=>
Immediat
e
::
ScalarPair
(
x
.with_default_tag
(),
y
.with_default_tag
()),
}
}
}
impl
<
'tcx
,
Tag
>
Valu
e
<
Tag
>
{
impl
<
'tcx
,
Tag
>
Immediat
e
<
Tag
>
{
#[inline]
pub
fn
erase_tag
(
self
)
->
Valu
e
pub
fn
erase_tag
(
self
)
->
Immediat
e
{
match
self
{
Value
::
Scalar
(
x
)
=>
Valu
e
::
Scalar
(
x
.erase_tag
()),
Valu
e
::
ScalarPair
(
x
,
y
)
=>
Valu
e
::
ScalarPair
(
x
.erase_tag
(),
y
.erase_tag
()),
Immediate
::
Scalar
(
x
)
=>
Immediat
e
::
Scalar
(
x
.erase_tag
()),
Immediat
e
::
ScalarPair
(
x
,
y
)
=>
Immediat
e
::
ScalarPair
(
x
.erase_tag
(),
y
.erase_tag
()),
}
}
...
...
@@ -180,18 +180,21 @@ pub fn new_slice(
len
:
u64
,
cx
:
impl
HasDataLayout
)
->
Self
{
Value
::
ScalarPair
(
val
.into
(),
Scalar
::
from_uint
(
len
,
cx
.data_layout
()
.pointer_size
)
.into
())
Immediate
::
ScalarPair
(
val
.into
(),
Scalar
::
from_uint
(
len
,
cx
.data_layout
()
.pointer_size
)
.into
(),
)
}
pub
fn
new_dyn_trait
(
val
:
Scalar
<
Tag
>
,
vtable
:
Pointer
<
Tag
>
)
->
Self
{
Valu
e
::
ScalarPair
(
val
.into
(),
Scalar
::
Ptr
(
vtable
)
.into
())
Immediat
e
::
ScalarPair
(
val
.into
(),
Scalar
::
Ptr
(
vtable
)
.into
())
}
#[inline]
pub
fn
to_scalar_or_undef
(
self
)
->
ScalarMaybeUndef
<
Tag
>
{
match
self
{
Valu
e
::
Scalar
(
val
)
=>
val
,
Valu
e
::
ScalarPair
(
..
)
=>
bug!
(
"Got a fat pointer where a scalar was expected"
),
Immediat
e
::
Scalar
(
val
)
=>
val
,
Immediat
e
::
ScalarPair
(
..
)
=>
bug!
(
"Got a fat pointer where a scalar was expected"
),
}
}
...
...
@@ -203,18 +206,18 @@ pub fn to_scalar(self) -> EvalResult<'tcx, Scalar<Tag>> {
#[inline]
pub
fn
to_scalar_pair
(
self
)
->
EvalResult
<
'tcx
,
(
Scalar
<
Tag
>
,
Scalar
<
Tag
>
)
>
{
match
self
{
Valu
e
::
Scalar
(
..
)
=>
bug!
(
"Got a thin pointer where a scalar pair was expected"
),
Valu
e
::
ScalarPair
(
a
,
b
)
=>
Ok
((
a
.not_undef
()
?
,
b
.not_undef
()
?
))
Immediat
e
::
Scalar
(
..
)
=>
bug!
(
"Got a thin pointer where a scalar pair was expected"
),
Immediat
e
::
ScalarPair
(
a
,
b
)
=>
Ok
((
a
.not_undef
()
?
,
b
.not_undef
()
?
))
}
}
/// Convert the
valu
e into a pointer (or a pointer-sized integer).
/// Convert the
immediat
e into a pointer (or a pointer-sized integer).
/// Throws away the second half of a ScalarPair!
#[inline]
pub
fn
to_scalar_ptr
(
self
)
->
EvalResult
<
'tcx
,
Scalar
<
Tag
>>
{
match
self
{
Valu
e
::
Scalar
(
ptr
)
|
Valu
e
::
ScalarPair
(
ptr
,
_
)
=>
ptr
.not_undef
(),
Immediat
e
::
Scalar
(
ptr
)
|
Immediat
e
::
ScalarPair
(
ptr
,
_
)
=>
ptr
.not_undef
(),
}
}
...
...
@@ -229,19 +232,19 @@ pub fn to_meta(self) -> EvalResult<'tcx, Option<Scalar<Tag>>> {
}
}
// ScalarPair needs a type to interpret, so we often have a
valu
e and a type together
// ScalarPair needs a type to interpret, so we often have a
n immediat
e and a type together
// as input for binary and cast operations.
#[derive(Copy,
Clone,
Debug)]
pub
struct
Val
Ty
<
'tcx
,
Tag
=
()
>
{
value
:
Valu
e
<
Tag
>
,
pub
struct
Imm
Ty
<
'tcx
,
Tag
=
()
>
{
immediate
:
Immediat
e
<
Tag
>
,
pub
layout
:
TyLayout
<
'tcx
>
,
}
impl
<
'tcx
,
Tag
>
::
std
::
ops
::
Deref
for
Val
Ty
<
'tcx
,
Tag
>
{
type
Target
=
Valu
e
<
Tag
>
;
impl
<
'tcx
,
Tag
>
::
std
::
ops
::
Deref
for
Imm
Ty
<
'tcx
,
Tag
>
{
type
Target
=
Immediat
e
<
Tag
>
;
#[inline(always)]
fn
deref
(
&
self
)
->
&
Valu
e
<
Tag
>
{
&
self
.
valu
e
fn
deref
(
&
self
)
->
&
Immediat
e
<
Tag
>
{
&
self
.
immediat
e
}
}
...
...
@@ -250,7 +253,7 @@ fn deref(&self) -> &Value<Tag> {
/// memory and to avoid having to store arbitrary-sized data here.
#[derive(Copy,
Clone,
Debug,
Hash,
PartialEq,
Eq)]
pub
enum
Operand
<
Tag
=
(),
Id
=
AllocId
>
{
Immediate
(
Valu
e
<
Tag
,
Id
>
),
Immediate
(
Immediat
e
<
Tag
,
Id
>
),
Indirect
(
MemPlace
<
Tag
,
Id
>
),
}
...
...
@@ -288,11 +291,11 @@ pub fn to_mem_place(self) -> MemPlace<Tag>
}
#[inline]
pub
fn
to_immediate
(
self
)
->
Valu
e
<
Tag
>
pub
fn
to_immediate
(
self
)
->
Immediat
e
<
Tag
>
where
Tag
:
::
std
::
fmt
::
Debug
{
match
self
{
Operand
::
Immediate
(
val
)
=>
val
,
Operand
::
Immediate
(
imm
)
=>
imm
,
_
=>
bug!
(
"to_immediate: expected Operand::Immediate, got {:?}"
,
self
),
}
...
...
@@ -323,11 +326,11 @@ fn from(mplace: MPlaceTy<'tcx, Tag>) -> Self {
}
}
impl
<
'tcx
,
Tag
>
From
<
Val
Ty
<
'tcx
,
Tag
>>
for
OpTy
<
'tcx
,
Tag
>
{
impl
<
'tcx
,
Tag
>
From
<
Imm
Ty
<
'tcx
,
Tag
>>
for
OpTy
<
'tcx
,
Tag
>
{
#[inline(always)]
fn
from
(
val
:
Val
Ty
<
'tcx
,
Tag
>
)
->
Self
{
fn
from
(
val
:
Imm
Ty
<
'tcx
,
Tag
>
)
->
Self
{
OpTy
{
op
:
Operand
::
Immediate
(
val
.
valu
e
),
op
:
Operand
::
Immediate
(
val
.
immediat
e
),
layout
:
val
.layout
}
}
...
...
@@ -367,12 +370,12 @@ fn from_known_layout<'tcx>(
}
impl
<
'a
,
'mir
,
'tcx
,
M
:
Machine
<
'a
,
'mir
,
'tcx
>>
EvalContext
<
'a
,
'mir
,
'tcx
,
M
>
{
/// Try reading a
valu
e in memory; this is interesting particularly for ScalarPair.
/// Try reading a
n immediat
e in memory; this is interesting particularly for ScalarPair.
/// Return None if the layout does not permit loading this as a value.
pub
(
super
)
fn
try_read_
valu
e_from_mplace
(
pub
(
super
)
fn
try_read_
immediat
e_from_mplace
(
&
self
,
mplace
:
MPlaceTy
<
'tcx
,
M
::
PointerTag
>
,
)
->
EvalResult
<
'tcx
,
Option
<
Valu
e
<
M
::
PointerTag
>>>
{
)
->
EvalResult
<
'tcx
,
Option
<
Immediat
e
<
M
::
PointerTag
>>>
{
if
mplace
.layout
.is_unsized
()
{
// Don't touch unsized
return
Ok
(
None
);
...
...
@@ -383,14 +386,14 @@ pub(super) fn try_read_value_from_mplace(
// Not all ZSTs have a layout we would handle below, so just short-circuit them
// all here.
self
.memory
.check_align
(
ptr
,
ptr_align
)
?
;
return
Ok
(
Some
(
Valu
e
::
Scalar
(
Scalar
::
zst
()
.into
())));
return
Ok
(
Some
(
Immediat
e
::
Scalar
(
Scalar
::
zst
()
.into
())));
}
let
ptr
=
ptr
.to_ptr
()
?
;
match
mplace
.layout.abi
{
layout
::
Abi
::
Scalar
(
..
)
=>
{
let
scalar
=
self
.memory
.read_scalar
(
ptr
,
ptr_align
,
mplace
.layout.size
)
?
;
Ok
(
Some
(
Valu
e
::
Scalar
(
scalar
)))
Ok
(
Some
(
Immediat
e
::
Scalar
(
scalar
)))
}
layout
::
Abi
::
ScalarPair
(
ref
a
,
ref
b
)
=>
{
let
(
a
,
b
)
=
(
&
a
.value
,
&
b
.value
);
...
...
@@ -401,25 +404,25 @@ pub(super) fn try_read_value_from_mplace(
let
b_ptr
=
ptr
.offset
(
b_offset
,
self
)
?
.into
();
let
a_val
=
self
.memory
.read_scalar
(
a_ptr
,
ptr_align
,
a_size
)
?
;
let
b_val
=
self
.memory
.read_scalar
(
b_ptr
,
ptr_align
,
b_size
)
?
;
Ok
(
Some
(
Valu
e
::
ScalarPair
(
a_val
,
b_val
)))
Ok
(
Some
(
Immediat
e
::
ScalarPair
(
a_val
,
b_val
)))
}
_
=>
Ok
(
None
),
}
}
/// Try returning an immediate
value
for the operand.
/// If the layout does not permit loading this as a
valu
e, return where in memory
/// Try returning an immediate for the operand.
/// If the layout does not permit loading this as a
n immediat
e, return where in memory
/// we can find the data.
/// Note that for a given layout, this operation will either always fail or always
/// succeed! Whether it succeeds depends on whether the layout can be represented
/// in a `
Valu
e`, not on which data is stored there currently.
pub
(
crate
)
fn
try_read_
valu
e
(
/// in a `
Immediat
e`, not on which data is stored there currently.
pub
(
crate
)
fn
try_read_
immediat
e
(
&
self
,
src
:
OpTy
<
'tcx
,
M
::
PointerTag
>
,
)
->
EvalResult
<
'tcx
,
Result
<
Valu
e
<
M
::
PointerTag
>
,
MemPlace
<
M
::
PointerTag
>>>
{
)
->
EvalResult
<
'tcx
,
Result
<
Immediat
e
<
M
::
PointerTag
>
,
MemPlace
<
M
::
PointerTag
>>>
{
Ok
(
match
src
.try_as_mplace
()
{
Ok
(
mplace
)
=>
{
if
let
Some
(
val
)
=
self
.try_read_
valu
e_from_mplace
(
mplace
)
?
{
if
let
Some
(
val
)
=
self
.try_read_
immediat
e_from_mplace
(
mplace
)
?
{
Ok
(
val
)
}
else
{
Err
(
*
mplace
)
...
...
@@ -429,14 +432,14 @@ pub(crate) fn try_read_value(
})
}
/// Read a
valu
e from a place, asserting that that is possible with the given layout.
/// Read a
n immediat
e from a place, asserting that that is possible with the given layout.
#[inline(always)]
pub
fn
read_
valu
e
(
pub
fn
read_
immediat
e
(
&
self
,
op
:
OpTy
<
'tcx
,
M
::
PointerTag
>
)
->
EvalResult
<
'tcx
,
Val
Ty
<
'tcx
,
M
::
PointerTag
>>
{
if
let
Ok
(
value
)
=
self
.try_read_valu
e
(
op
)
?
{
Ok
(
ValTy
{
valu
e
,
layout
:
op
.layout
})
)
->
EvalResult
<
'tcx
,
Imm
Ty
<
'tcx
,
M
::
PointerTag
>>
{
if
let
Ok
(
immediate
)
=
self
.try_read_immediat
e
(
op
)
?
{
Ok
(
ImmTy
{
immediat
e
,
layout
:
op
.layout
})
}
else
{
bug!
(
"primitive read failed for type: {:?}"
,
op
.layout.ty
);
}
...
...
@@ -447,10 +450,7 @@ pub fn read_scalar(
&
self
,
op
:
OpTy
<
'tcx
,
M
::
PointerTag
>
)
->
EvalResult
<
'tcx
,
ScalarMaybeUndef
<
M
::
PointerTag
>>
{
match
*
self
.read_value
(
op
)
?
{
Value
::
ScalarPair
(
..
)
=>
bug!
(
"got ScalarPair for type: {:?}"
,
op
.layout.ty
),
Value
::
Scalar
(
val
)
=>
Ok
(
val
),
}
Ok
(
self
.read_immediate
(
op
)
?
.to_scalar_or_undef
())
}
// Turn the MPlace into a string (must already be dereferenced!)
...
...
@@ -470,16 +470,16 @@ pub fn uninit_operand(
layout
:
TyLayout
<
'tcx
>
)
->
EvalResult
<
'tcx
,
Operand
<
M
::
PointerTag
>>
{
// This decides which types we will use the Immediate optimization for, and hence should
// match what `try_read_
valu
e` and `eval_place_to_op` support.
// match what `try_read_
immediat
e` and `eval_place_to_op` support.
if
layout
.is_zst
()
{
return
Ok
(
Operand
::
Immediate
(
Valu
e
::
Scalar
(
Scalar
::
zst
()
.into
())));
return
Ok
(
Operand
::
Immediate
(
Immediat
e
::
Scalar
(
Scalar
::
zst
()
.into
())));
}
Ok
(
match
layout
.abi
{
layout
::
Abi
::
Scalar
(
..
)
=>
Operand
::
Immediate
(
Valu
e
::
Scalar
(
ScalarMaybeUndef
::
Undef
)),
Operand
::
Immediate
(
Immediat
e
::
Scalar
(
ScalarMaybeUndef
::
Undef
)),
layout
::
Abi
::
ScalarPair
(
..
)
=>
Operand
::
Immediate
(
Valu
e
::
ScalarPair
(
Operand
::
Immediate
(
Immediat
e
::
ScalarPair
(
ScalarMaybeUndef
::
Undef
,
ScalarMaybeUndef
::
Undef
,
)),
...
...
@@ -510,22 +510,22 @@ pub fn operand_field(
let
field
=
field
.try_into
()
.unwrap
();
let
field_layout
=
op
.layout
.field
(
self
,
field
)
?
;
if
field_layout
.is_zst
()
{
let
val
=
Valu
e
::
Scalar
(
Scalar
::
zst
()
.into
());
return
Ok
(
OpTy
{
op
:
Operand
::
Immediate
(
val
),
layout
:
field_layout
});
let
immediate
=
Immediat
e
::
Scalar
(
Scalar
::
zst
()
.into
());
return
Ok
(
OpTy
{
op
:
Operand
::
Immediate
(
immediate
),
layout
:
field_layout
});
}
let
offset
=
op
.layout.fields
.offset
(
field
);
let
valu
e
=
match
base
{
let
immediat
e
=
match
base
{
// the field covers the entire type
_
if
offset
.bytes
()
==
0
&&
field_layout
.size
==
op
.layout.size
=>
base
,
// extract fields from types with `ScalarPair` ABI
Valu
e
::
ScalarPair
(
a
,
b
)
=>
{
Immediat
e
::
ScalarPair
(
a
,
b
)
=>
{
let
val
=
if
offset
.bytes
()
==
0
{
a
}
else
{
b
};
Valu
e
::
Scalar
(
val
)
Immediat
e
::
Scalar
(
val
)
},
Valu
e
::
Scalar
(
val
)
=>
Immediat
e
::
Scalar
(
val
)
=>
bug!
(
"field access on non aggregate {:#?}, {:#?}"
,
val
,
op
.layout
),
};
Ok
(
OpTy
{
op
:
Operand
::
Immediate
(
valu
e
),
layout
:
field_layout
})
Ok
(
OpTy
{
op
:
Operand
::
Immediate
(
immediat
e
),
layout
:
field_layout
})
}
pub
fn
operand_downcast
(
...
...
@@ -551,7 +551,7 @@ pub(super) fn deref_operand(
&
self
,
src
:
OpTy
<
'tcx
,
M
::
PointerTag
>
,
)
->
EvalResult
<
'tcx
,
MPlaceTy
<
'tcx
,
M
::
PointerTag
>>
{
let
val
=
self
.read_
valu
e
(
src
)
?
;
let
val
=
self
.read_
immediat
e
(
src
)
?
;
trace!
(
"deref to {} on {:?}"
,
val
.layout.ty
,
*
val
);
Ok
(
self
.ref_to_mplace
(
val
)
?
)
}
...
...
@@ -568,7 +568,7 @@ pub fn operand_projection(
Deref
=>
self
.deref_operand
(
base
)
?
.into
(),
Subslice
{
..
}
|
ConstantIndex
{
..
}
|
Index
(
_
)
=>
if
base
.layout
.is_zst
()
{
OpTy
{
op
:
Operand
::
Immediate
(
Valu
e
::
Scalar
(
Scalar
::
zst
()
.into
())),
op
:
Operand
::
Immediate
(
Immediat
e
::
Scalar
(
Scalar
::
zst
()
.into
())),
// the actual index doesn't matter, so we just pick a convenient one like 0
layout
:
base
.layout
.field
(
self
,
0
)
?
,
}
...
...
@@ -682,9 +682,12 @@ pub(super) fn const_value_to_op(
)
.with_default_tag
())
},
ConstValue
::
ScalarPair
(
a
,
b
)
=>
Ok
(
Operand
::
Immediate
(
Value
::
ScalarPair
(
a
.into
(),
b
.into
()))
.with_default_tag
()),
Ok
(
Operand
::
Immediate
(
Immediate
::
ScalarPair
(
a
.into
(),
b
.into
(),
))
.with_default_tag
()),
ConstValue
::
Scalar
(
x
)
=>
Ok
(
Operand
::
Immediate
(
Valu
e
::
Scalar
(
x
.into
()))
.with_default_tag
()),
Ok
(
Operand
::
Immediate
(
Immediat
e
::
Scalar
(
x
.into
()))
.with_default_tag
()),
}
}
pub
fn
const_to_op
(
...
...
@@ -722,7 +725,7 @@ pub fn read_discriminant(
}
// read raw discriminant value
let
discr_op
=
self
.operand_field
(
rval
,
0
)
?
;
let
discr_val
=
self
.read_
valu
e
(
discr_op
)
?
;
let
discr_val
=
self
.read_
immediat
e
(
discr_op
)
?
;
let
raw_discr
=
discr_val
.to_scalar
()
?
;
trace!
(
"discr value: {:?}"
,
raw_discr
);
// post-process
...
...
src/librustc_mir/interpret/operator.rs
浏览文件 @
e8a22b69
...
...
@@ -15,7 +15,7 @@
use
rustc_apfloat
::
Float
;
use
rustc
::
mir
::
interpret
::{
EvalResult
,
Scalar
};
use
super
::{
EvalContext
,
PlaceTy
,
Value
,
Machine
,
Val
Ty
};
use
super
::{
EvalContext
,
PlaceTy
,
Immediate
,
Machine
,
Imm
Ty
};
impl
<
'a
,
'mir
,
'tcx
,
M
:
Machine
<
'a
,
'mir
,
'tcx
>>
EvalContext
<
'a
,
'mir
,
'tcx
,
M
>
{
...
...
@@ -24,13 +24,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
pub
fn
binop_with_overflow
(
&
mut
self
,
op
:
mir
::
BinOp
,
left
:
Val
Ty
<
'tcx
,
M
::
PointerTag
>
,
right
:
Val
Ty
<
'tcx
,
M
::
PointerTag
>
,
left
:
Imm
Ty
<
'tcx
,
M
::
PointerTag
>
,
right
:
Imm
Ty
<
'tcx
,
M
::
PointerTag
>
,
dest
:
PlaceTy
<
'tcx
,
M
::
PointerTag
>
,
)
->
EvalResult
<
'tcx
>
{
let
(
val
,
overflowed
)
=
self
.binary_op_val
(
op
,
left
,
right
)
?
;
let
val
=
Valu
e
::
ScalarPair
(
val
.into
(),
Scalar
::
from_bool
(
overflowed
)
.into
());
self
.write_
valu
e
(
val
,
dest
)
let
val
=
Immediat
e
::
ScalarPair
(
val
.into
(),
Scalar
::
from_bool
(
overflowed
)
.into
());
self
.write_
immediat
e
(
val
,
dest
)
}
/// Applies the binary operation `op` to the arguments and writes the result to the
...
...
@@ -38,8 +38,8 @@ pub fn binop_with_overflow(
pub
fn
binop_ignore_overflow
(
&
mut
self
,
op
:
mir
::
BinOp
,
left
:
Val
Ty
<
'tcx
,
M
::
PointerTag
>
,
right
:
Val
Ty
<
'tcx
,
M
::
PointerTag
>
,
left
:
Imm
Ty
<
'tcx
,
M
::
PointerTag
>
,
right
:
Imm
Ty
<
'tcx
,
M
::
PointerTag
>
,
dest
:
PlaceTy
<
'tcx
,
M
::
PointerTag
>
,
)
->
EvalResult
<
'tcx
>
{
let
(
val
,
_
overflowed
)
=
self
.binary_op_val
(
op
,
left
,
right
)
?
;
...
...
@@ -288,8 +288,8 @@ fn binary_int_op(
pub
fn
binary_op_val
(
&
self
,
bin_op
:
mir
::
BinOp
,
left
:
Val
Ty
<
'tcx
,
M
::
PointerTag
>
,
right
:
Val
Ty
<
'tcx
,
M
::
PointerTag
>
,
left
:
Imm
Ty
<
'tcx
,
M
::
PointerTag
>
,
right
:
Imm
Ty
<
'tcx
,
M
::
PointerTag
>
,
)
->
EvalResult
<
'tcx
,
(
Scalar
<
M
::
PointerTag
>
,
bool
)
>
{
self
.binary_op
(
bin_op
,
...
...
src/librustc_mir/interpret/place.rs
浏览文件 @
e8a22b69
...
...
@@ -25,7 +25,7 @@
};
use
super
::{
EvalContext
,
Machine
,
AllocMap
,
Value
,
Val
Ty
,
ScalarMaybeUndef
,
Operand
,
OpTy
,
MemoryKind
Immediate
,
Imm
Ty
,
ScalarMaybeUndef
,
Operand
,
OpTy
,
MemoryKind
};
#[derive(Copy,
Clone,
Debug,
Hash,
PartialEq,
Eq)]
...
...
@@ -201,10 +201,10 @@ pub(super) fn vtable(self) -> EvalResult<'tcx, Pointer<Tag>> {
impl
<
'tcx
,
Tag
:
::
std
::
fmt
::
Debug
>
OpTy
<
'tcx
,
Tag
>
{
#[inline(always)]
pub
fn
try_as_mplace
(
self
)
->
Result
<
MPlaceTy
<
'tcx
,
Tag
>
,
Valu
e
<
Tag
>>
{
pub
fn
try_as_mplace
(
self
)
->
Result
<
MPlaceTy
<
'tcx
,
Tag
>
,
Immediat
e
<
Tag
>>
{
match
self
.op
{
Operand
::
Indirect
(
mplace
)
=>
Ok
(
MPlaceTy
{
mplace
,
layout
:
self
.layout
}),
Operand
::
Immediate
(
value
)
=>
Err
(
value
),
Operand
::
Immediate
(
imm
)
=>
Err
(
imm
),
}
}
...
...
@@ -269,7 +269,7 @@ impl<'a, 'mir, 'tcx, Tag, M> EvalContext<'a, 'mir, 'tcx, M>
/// Alignment is just based on the type. This is the inverse of `create_ref`.
pub
fn
ref_to_mplace
(
&
self
,
val
:
Val
Ty
<
'tcx
,
M
::
PointerTag
>
,
val
:
Imm
Ty
<
'tcx
,
M
::
PointerTag
>
,
)
->
EvalResult
<
'tcx
,
MPlaceTy
<
'tcx
,
M
::
PointerTag
>>
{
let
pointee_type
=
val
.layout.ty
.builtin_deref
(
true
)
.unwrap
()
.ty
;
let
layout
=
self
.layout_of
(
pointee_type
)
?
;
...
...
@@ -304,7 +304,7 @@ pub fn create_ref(
&
mut
self
,
place
:
MPlaceTy
<
'tcx
,
M
::
PointerTag
>
,
mutbl
:
Option
<
hir
::
Mutability
>
,
)
->
EvalResult
<
'tcx
,
Valu
e
<
M
::
PointerTag
>>
{
)
->
EvalResult
<
'tcx
,
Immediat
e
<
M
::
PointerTag
>>
{
// Pointer tag tracking might want to adjust the tag
let
place
=
if
M
::
ENABLE_PTR_TRACKING_HOOKS
{
let
(
size
,
_
)
=
self
.size_and_align_of_mplace
(
place
)
?
...
...
@@ -315,8 +315,8 @@ pub fn create_ref(
*
place
};
Ok
(
match
place
.meta
{
None
=>
Valu
e
::
Scalar
(
place
.ptr
.into
()),
Some
(
meta
)
=>
Valu
e
::
ScalarPair
(
place
.ptr
.into
(),
meta
.into
()),
None
=>
Immediat
e
::
Scalar
(
place
.ptr
.into
()),
Some
(
meta
)
=>
Immediat
e
::
ScalarPair
(
place
.ptr
.into
(),
meta
.into
()),
})
}
...
...
@@ -629,17 +629,17 @@ pub fn write_scalar(
val
:
impl
Into
<
ScalarMaybeUndef
<
M
::
PointerTag
>>
,
dest
:
PlaceTy
<
'tcx
,
M
::
PointerTag
>
,
)
->
EvalResult
<
'tcx
>
{
self
.write_
value
(
Valu
e
::
Scalar
(
val
.into
()),
dest
)
self
.write_
immediate
(
Immediat
e
::
Scalar
(
val
.into
()),
dest
)
}
/// Write a
valu
e to a place
/// Write a
n immediat
e to a place
#[inline(always)]
pub
fn
write_
valu
e
(
pub
fn
write_
immediat
e
(
&
mut
self
,
src
_val
:
Valu
e
<
M
::
PointerTag
>
,
src
:
Immediat
e
<
M
::
PointerTag
>
,
dest
:
PlaceTy
<
'tcx
,
M
::
PointerTag
>
,
)
->
EvalResult
<
'tcx
>
{
self
.write_
value_no_validate
(
src_val
,
dest
)
?
;
self
.write_
immediate_no_validate
(
src
,
dest
)
?
;
if
M
::
enforce_validity
(
self
)
{
// Data got changed, better make sure it matches the type!
...
...
@@ -649,40 +649,40 @@ pub fn write_value(
Ok
(())
}
/// Write a
valu
e to a place.
/// Write a
n immediat
e to a place.
/// If you use this you are responsible for validating that things got copied at the
/// right type.
fn
write_
valu
e_no_validate
(
fn
write_
immediat
e_no_validate
(
&
mut
self
,
src
_val
:
Valu
e
<
M
::
PointerTag
>
,
src
:
Immediat
e
<
M
::
PointerTag
>
,
dest
:
PlaceTy
<
'tcx
,
M
::
PointerTag
>
,
)
->
EvalResult
<
'tcx
>
{
if
cfg!
(
debug_assertions
)
{
// This is a very common path, avoid some checks in release mode
assert
!
(
!
dest
.layout
.is_unsized
(),
"Cannot write unsized data"
);
match
src
_val
{
Valu
e
::
Scalar
(
ScalarMaybeUndef
::
Scalar
(
Scalar
::
Ptr
(
_
)))
=>
match
src
{
Immediat
e
::
Scalar
(
ScalarMaybeUndef
::
Scalar
(
Scalar
::
Ptr
(
_
)))
=>
assert_eq!
(
self
.pointer_size
(),
dest
.layout.size
,
"Size mismatch when writing pointer"
),
Valu
e
::
Scalar
(
ScalarMaybeUndef
::
Scalar
(
Scalar
::
Bits
{
size
,
..
}))
=>
Immediat
e
::
Scalar
(
ScalarMaybeUndef
::
Scalar
(
Scalar
::
Bits
{
size
,
..
}))
=>
assert_eq!
(
Size
::
from_bytes
(
size
.into
()),
dest
.layout.size
,
"Size mismatch when writing bits"
),
Valu
e
::
Scalar
(
ScalarMaybeUndef
::
Undef
)
=>
{},
// undef can have any size
Valu
e
::
ScalarPair
(
_
,
_
)
=>
{
Immediat
e
::
Scalar
(
ScalarMaybeUndef
::
Undef
)
=>
{},
// undef can have any size
Immediat
e
::
ScalarPair
(
_
,
_
)
=>
{
// FIXME: Can we check anything here?
}
}
}
trace!
(
"write_
value: {:?} <- {:?}: {}"
,
*
dest
,
src_val
,
dest
.layout.ty
);
trace!
(
"write_
immediate: {:?} <- {:?}: {}"
,
*
dest
,
src
,
dest
.layout.ty
);
// See if we can avoid an allocation. This is the counterpart to `try_read_
valu
e`,
// See if we can avoid an allocation. This is the counterpart to `try_read_
immediat
e`,
// but not factored as a separate function.
let
mplace
=
match
dest
.place
{
Place
::
Local
{
frame
,
local
}
=>
{
match
*
self
.stack
[
frame
]
.locals
[
local
]
.access_mut
()
?
{
Operand
::
Immediate
(
ref
mut
dest_val
)
=>
{
// Yay, we can just change the local directly.
*
dest_val
=
src
_val
;
*
dest_val
=
src
;
return
Ok
(());
},
Operand
::
Indirect
(
mplace
)
=>
mplace
,
// already in memory
...
...
@@ -693,15 +693,15 @@ fn write_value_no_validate(
let
dest
=
MPlaceTy
{
mplace
,
layout
:
dest
.layout
};
// This is already in memory, write there.
self
.write_
value_to_mplace_no_validate
(
src_val
,
dest
)
self
.write_
immediate_to_mplace_no_validate
(
src
,
dest
)
}
/// Write a
valu
e to memory.
/// Write a
n immediat
e to memory.
/// If you use this you are responsible for validating that things git copied at the
/// right type.
fn
write_
valu
e_to_mplace_no_validate
(
fn
write_
immediat
e_to_mplace_no_validate
(
&
mut
self
,
value
:
Valu
e
<
M
::
PointerTag
>
,
value
:
Immediat
e
<
M
::
PointerTag
>
,
dest
:
MPlaceTy
<
'tcx
,
M
::
PointerTag
>
,
)
->
EvalResult
<
'tcx
>
{
let
(
ptr
,
ptr_align
)
=
dest
.to_scalar_ptr_align
();
...
...
@@ -721,10 +721,10 @@ fn write_value_to_mplace_no_validate(
// memory. The code below is not sufficient, with enough padding it might not
// cover all the bytes!
match
value
{
Valu
e
::
Scalar
(
scalar
)
=>
{
Immediat
e
::
Scalar
(
scalar
)
=>
{
match
dest
.layout.abi
{
layout
::
Abi
::
Scalar
(
_
)
=>
{},
// fine
_
=>
bug!
(
"write_
valu
e_to_mplace: invalid Scalar layout: {:#?}"
,
_
=>
bug!
(
"write_
immediat
e_to_mplace: invalid Scalar layout: {:#?}"
,
dest
.layout
)
}
...
...
@@ -732,10 +732,10 @@ fn write_value_to_mplace_no_validate(
ptr
,
ptr_align
.min
(
dest
.layout.align
),
scalar
,
dest
.layout.size
)
}
Valu
e
::
ScalarPair
(
a_val
,
b_val
)
=>
{
Immediat
e
::
ScalarPair
(
a_val
,
b_val
)
=>
{
let
(
a
,
b
)
=
match
dest
.layout.abi
{
layout
::
Abi
::
ScalarPair
(
ref
a
,
ref
b
)
=>
(
&
a
.value
,
&
b
.value
),
_
=>
bug!
(
"write_
valu
e_to_mplace: invalid ScalarPair layout: {:#?}"
,
_
=>
bug!
(
"write_
immediat
e_to_mplace: invalid ScalarPair layout: {:#?}"
,
dest
.layout
)
};
let
(
a_size
,
b_size
)
=
(
a
.size
(
&
self
),
b
.size
(
&
self
));
...
...
@@ -788,10 +788,10 @@ fn copy_op_no_validate(
"Layout mismatch when copying!
\n
src: {:#?}
\n
dest: {:#?}"
,
src
,
dest
);
// Let us see if the layout is simple so we take a shortcut, avoid force_allocation.
let
src
=
match
self
.try_read_
valu
e
(
src
)
?
{
let
src
=
match
self
.try_read_
immediat
e
(
src
)
?
{
Ok
(
src_val
)
=>
{
// Yay, we got a value that we can write directly.
return
self
.write_
valu
e_no_validate
(
src_val
,
dest
);
return
self
.write_
immediat
e_no_validate
(
src_val
,
dest
);
}
Err
(
mplace
)
=>
mplace
,
};
...
...
@@ -873,7 +873,7 @@ pub fn force_allocation(
let
ptr
=
self
.allocate
(
local_layout
,
MemoryKind
::
Stack
)
?
;
// We don't have to validate as we can assume the local
// was already valid for its type.
self
.write_
valu
e_to_mplace_no_validate
(
value
,
ptr
)
?
;
self
.write_
immediat
e_to_mplace_no_validate
(
value
,
ptr
)
?
;
let
mplace
=
ptr
.mplace
;
// Update the local
*
self
.stack
[
frame
]
.locals
[
local
]
.access_mut
()
?
=
...
...
src/librustc_mir/interpret/snapshot.rs
浏览文件 @
e8a22b69
...
...
@@ -24,7 +24,7 @@
use
syntax
::
source_map
::
Span
;
use
super
::
eval_context
::{
LocalValue
,
StackPopCleanup
};
use
super
::{
Frame
,
Memory
,
Operand
,
MemPlace
,
Place
,
Valu
e
,
ScalarMaybeUndef
};
use
super
::{
Frame
,
Memory
,
Operand
,
MemPlace
,
Place
,
Immediat
e
,
ScalarMaybeUndef
};
use
const_eval
::
CompileTimeInterpreter
;
#[derive(Default)]
...
...
@@ -237,11 +237,11 @@ fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
}
}
impl_stable_hash_for!
(
enum
::
interpret
::
Valu
e
{
impl_stable_hash_for!
(
enum
::
interpret
::
Immediat
e
{
Scalar
(
x
),
ScalarPair
(
x
,
y
),
});
impl_snapshot_for!
(
enum
Valu
e
{
impl_snapshot_for!
(
enum
Immediat
e
{
Scalar
(
s
),
ScalarPair
(
s
,
t
),
});
...
...
src/librustc_mir/interpret/step.rs
浏览文件 @
e8a22b69
...
...
@@ -159,9 +159,9 @@ fn eval_rvalue_into_place(
BinaryOp
(
bin_op
,
ref
left
,
ref
right
)
=>
{
let
layout
=
if
binop_left_homogeneous
(
bin_op
)
{
Some
(
dest
.layout
)
}
else
{
None
};
let
left
=
self
.read_
valu
e
(
self
.eval_operand
(
left
,
layout
)
?
)
?
;
let
left
=
self
.read_
immediat
e
(
self
.eval_operand
(
left
,
layout
)
?
)
?
;
let
layout
=
if
binop_right_homogeneous
(
bin_op
)
{
Some
(
left
.layout
)
}
else
{
None
};
let
right
=
self
.read_
valu
e
(
self
.eval_operand
(
right
,
layout
)
?
)
?
;
let
right
=
self
.read_
immediat
e
(
self
.eval_operand
(
right
,
layout
)
?
)
?
;
self
.binop_ignore_overflow
(
bin_op
,
left
,
...
...
@@ -172,9 +172,9 @@ fn eval_rvalue_into_place(
CheckedBinaryOp
(
bin_op
,
ref
left
,
ref
right
)
=>
{
// Due to the extra boolean in the result, we can never reuse the `dest.layout`.
let
left
=
self
.read_
valu
e
(
self
.eval_operand
(
left
,
None
)
?
)
?
;
let
left
=
self
.read_
immediat
e
(
self
.eval_operand
(
left
,
None
)
?
)
?
;
let
layout
=
if
binop_right_homogeneous
(
bin_op
)
{
Some
(
left
.layout
)
}
else
{
None
};
let
right
=
self
.read_
valu
e
(
self
.eval_operand
(
right
,
layout
)
?
)
?
;
let
right
=
self
.read_
immediat
e
(
self
.eval_operand
(
right
,
layout
)
?
)
?
;
self
.binop_with_overflow
(
bin_op
,
left
,
...
...
@@ -185,7 +185,7 @@ fn eval_rvalue_into_place(
UnaryOp
(
un_op
,
ref
operand
)
=>
{
// The operand always has the same type as the result.
let
val
=
self
.read_
valu
e
(
self
.eval_operand
(
operand
,
Some
(
dest
.layout
))
?
)
?
;
let
val
=
self
.read_
immediat
e
(
self
.eval_operand
(
operand
,
Some
(
dest
.layout
))
?
)
?
;
let
val
=
self
.unary_op
(
un_op
,
val
.to_scalar
()
?
,
dest
.layout
)
?
;
self
.write_scalar
(
val
,
dest
)
?
;
}
...
...
@@ -259,7 +259,7 @@ fn eval_rvalue_into_place(
hir
::
MutImmutable
,
};
let
val
=
self
.create_ref
(
val
,
Some
(
mutbl
))
?
;
self
.write_
valu
e
(
val
,
dest
)
?
;
self
.write_
immediat
e
(
val
,
dest
)
?
;
}
NullaryOp
(
mir
::
NullOp
::
Box
,
_
)
=>
{
...
...
src/librustc_mir/interpret/terminator.rs
浏览文件 @
e8a22b69
...
...
@@ -17,7 +17,7 @@
use
rustc
::
mir
::
interpret
::{
EvalResult
,
PointerArithmetic
,
EvalErrorKind
,
Scalar
};
use
super
::{
EvalContext
,
Machine
,
Valu
e
,
OpTy
,
PlaceTy
,
MPlaceTy
,
Operand
,
StackPopCleanup
EvalContext
,
Machine
,
Immediat
e
,
OpTy
,
PlaceTy
,
MPlaceTy
,
Operand
,
StackPopCleanup
};
impl
<
'a
,
'mir
,
'tcx
,
M
:
Machine
<
'a
,
'mir
,
'tcx
>>
EvalContext
<
'a
,
'mir
,
'tcx
,
M
>
{
...
...
@@ -51,7 +51,7 @@ pub(super) fn eval_terminator(
ref
targets
,
..
}
=>
{
let
discr
=
self
.read_
valu
e
(
self
.eval_operand
(
discr
,
None
)
?
)
?
;
let
discr
=
self
.read_
immediat
e
(
self
.eval_operand
(
discr
,
None
)
?
)
?
;
trace!
(
"SwitchInt({:?})"
,
*
discr
);
// Branch to the `otherwise` case by default, if no match is found.
...
...
@@ -138,7 +138,7 @@ pub(super) fn eval_terminator(
target
,
..
}
=>
{
let
cond_val
=
self
.read_
valu
e
(
self
.eval_operand
(
cond
,
None
)
?
)
?
let
cond_val
=
self
.read_
immediat
e
(
self
.eval_operand
(
cond
,
None
)
?
)
?
.to_scalar
()
?
.to_bool
()
?
;
if
expected
==
cond_val
{
self
.goto_block
(
Some
(
target
))
?
;
...
...
@@ -147,10 +147,10 @@ pub(super) fn eval_terminator(
use
rustc
::
mir
::
interpret
::
EvalErrorKind
::
*
;
return
match
*
msg
{
BoundsCheck
{
ref
len
,
ref
index
}
=>
{
let
len
=
self
.read_
valu
e
(
self
.eval_operand
(
len
,
None
)
?
)
let
len
=
self
.read_
immediat
e
(
self
.eval_operand
(
len
,
None
)
?
)
.expect
(
"can't eval len"
)
.to_scalar
()
?
.to_bits
(
self
.memory
()
.pointer_size
())
?
as
u64
;
let
index
=
self
.read_
valu
e
(
self
.eval_operand
(
index
,
None
)
?
)
let
index
=
self
.read_
immediat
e
(
self
.eval_operand
(
index
,
None
)
?
)
.expect
(
"can't eval index"
)
.to_scalar
()
?
.to_bits
(
self
.memory
()
.pointer_size
())
?
as
u64
;
err!
(
BoundsCheck
{
len
,
index
})
...
...
@@ -402,7 +402,7 @@ fn eval_fn_call(
ty
::
InstanceDef
::
Virtual
(
_
,
idx
)
=>
{
let
ptr_size
=
self
.pointer_size
();
let
ptr_align
=
self
.tcx.data_layout.pointer_align
;
let
ptr
=
self
.ref_to_mplace
(
self
.read_
valu
e
(
args
[
0
])
?
)
?
;
let
ptr
=
self
.ref_to_mplace
(
self
.read_
immediat
e
(
args
[
0
])
?
)
?
;
let
vtable
=
ptr
.vtable
()
?
;
let
fn_ptr
=
self
.memory
.read_ptr_sized
(
vtable
.offset
(
ptr_size
*
(
idx
as
u64
+
3
),
&
self
)
?
,
...
...
@@ -417,7 +417,7 @@ fn eval_fn_call(
let
pointee
=
args
[
0
]
.layout.ty
.builtin_deref
(
true
)
.unwrap
()
.ty
;
let
fake_fat_ptr_ty
=
self
.tcx
.mk_mut_ptr
(
pointee
);
args
[
0
]
.layout
=
self
.layout_of
(
fake_fat_ptr_ty
)
?
.field
(
&
self
,
0
)
?
;
args
[
0
]
.op
=
Operand
::
Immediate
(
Valu
e
::
Scalar
(
ptr
.ptr
.into
()));
// strip vtable
args
[
0
]
.op
=
Operand
::
Immediate
(
Immediat
e
::
Scalar
(
ptr
.ptr
.into
()));
// strip vtable
trace!
(
"Patched self operand to {:#?}"
,
args
[
0
]);
// recurse with concrete function
self
.eval_fn_call
(
instance
,
span
,
caller_abi
,
&
args
,
dest
,
ret
)
...
...
src/librustc_mir/interpret/validity.rs
浏览文件 @
e8a22b69
...
...
@@ -20,7 +20,7 @@
};
use
super
::{
Val
Ty
,
OpTy
,
MPlaceTy
,
Machine
,
EvalContext
,
ScalarMaybeUndef
Imm
Ty
,
OpTy
,
MPlaceTy
,
Machine
,
EvalContext
,
ScalarMaybeUndef
};
macro_rules!
validation_failure
{
...
...
@@ -144,7 +144,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
/// Make sure that `value` is valid for `ty`, *assuming* `ty` is a primitive type.
fn
validate_primitive_type
(
&
self
,
value
:
Val
Ty
<
'tcx
,
M
::
PointerTag
>
,
value
:
Imm
Ty
<
'tcx
,
M
::
PointerTag
>
,
path
:
&
Vec
<
PathElem
>
,
ref_tracking
:
Option
<&
mut
RefTracking
<
'tcx
,
M
::
PointerTag
>>
,
const_mode
:
bool
,
...
...
@@ -465,7 +465,7 @@ pub fn validate_operand(
_
=>
dest
.layout.ty
.builtin_deref
(
true
)
.is_some
(),
};
if
primitive
{
let
value
=
try_validation!
(
self
.read_
valu
e
(
dest
),
let
value
=
try_validation!
(
self
.read_
immediat
e
(
dest
),
"uninitialized or unrepresentable data"
,
path
);
return
self
.validate_primitive_type
(
value
,
...
...
src/librustc_mir/transform/const_prop.rs
浏览文件 @
e8a22b69
...
...
@@ -28,7 +28,7 @@
HasTyCtxt
,
TargetDataLayout
,
HasDataLayout
,
};
use
interpret
::{
self
,
EvalContext
,
ScalarMaybeUndef
,
Valu
e
,
OpTy
,
MemoryKind
};
use
interpret
::{
self
,
EvalContext
,
ScalarMaybeUndef
,
Immediat
e
,
OpTy
,
MemoryKind
};
use
const_eval
::{
CompileTimeInterpreter
,
error_to_const_error
,
eval_promoted
,
mk_borrowck_eval_cx
};
use
transform
::{
MirPass
,
MirSource
};
...
...
@@ -354,7 +354,7 @@ fn const_prop(
Rvalue
::
NullaryOp
(
NullOp
::
SizeOf
,
ty
)
=>
{
type_size_of
(
self
.tcx
,
self
.param_env
,
ty
)
.and_then
(|
n
|
Some
((
OpTy
{
op
:
interpret
::
Operand
::
Immediate
(
Valu
e
::
Scalar
(
op
:
interpret
::
Operand
::
Immediate
(
Immediat
e
::
Scalar
(
Scalar
::
Bits
{
bits
:
n
as
u128
,
size
:
self
.tcx.data_layout.pointer_size
.bytes
()
as
u8
,
...
...
@@ -397,7 +397,7 @@ fn const_prop(
this
.ecx
.unary_op
(
op
,
prim
,
arg
.layout
)
})
?
;
let
res
=
OpTy
{
op
:
interpret
::
Operand
::
Immediate
(
Valu
e
::
Scalar
(
val
.into
())),
op
:
interpret
::
Operand
::
Immediate
(
Immediat
e
::
Scalar
(
val
.into
())),
layout
:
place_layout
,
};
Some
((
res
,
span
))
...
...
@@ -418,7 +418,7 @@ fn const_prop(
}
let
r
=
self
.use_ecx
(
source_info
,
|
this
|
{
this
.ecx
.read_
valu
e
(
right
.0
)
this
.ecx
.read_
immediat
e
(
right
.0
)
})
?
;
if
op
==
BinOp
::
Shr
||
op
==
BinOp
::
Shl
{
let
left_ty
=
left
.ty
(
self
.mir
,
self
.tcx
);
...
...
@@ -451,14 +451,14 @@ fn const_prop(
}
let
left
=
self
.eval_operand
(
left
,
source_info
)
?
;
let
l
=
self
.use_ecx
(
source_info
,
|
this
|
{
this
.ecx
.read_
valu
e
(
left
.0
)
this
.ecx
.read_
immediat
e
(
left
.0
)
})
?
;
trace!
(
"const evaluating {:?} for {:?} and {:?}"
,
op
,
left
,
right
);
let
(
val
,
overflow
)
=
self
.use_ecx
(
source_info
,
|
this
|
{
this
.ecx
.binary_op_val
(
op
,
l
,
r
)
})
?
;
let
val
=
if
let
Rvalue
::
CheckedBinaryOp
(
..
)
=
*
rvalue
{
Valu
e
::
ScalarPair
(
Immediat
e
::
ScalarPair
(
val
.into
(),
Scalar
::
from_bool
(
overflow
)
.into
(),
)
...
...
@@ -468,7 +468,7 @@ fn const_prop(
let
_
:
Option
<
()
>
=
self
.use_ecx
(
source_info
,
|
_
|
Err
(
err
));
return
None
;
}
Valu
e
::
Scalar
(
val
.into
())
Immediat
e
::
Scalar
(
val
.into
())
};
let
res
=
OpTy
{
op
:
interpret
::
Operand
::
Immediate
(
val
),
...
...
@@ -591,7 +591,7 @@ fn visit_terminator_kind(
if
let
TerminatorKind
::
Assert
{
expected
,
msg
,
cond
,
..
}
=
kind
{
if
let
Some
(
value
)
=
self
.eval_operand
(
cond
,
source_info
)
{
trace!
(
"assertion on {:?} should be {:?}"
,
value
,
expected
);
let
expected
=
Valu
e
::
Scalar
(
Scalar
::
from_bool
(
*
expected
)
.into
());
let
expected
=
Immediat
e
::
Scalar
(
Scalar
::
from_bool
(
*
expected
)
.into
());
if
expected
!=
value
.0
.to_immediate
()
{
// poison all places this operand references so that further code
// doesn't use the invalid value
...
...
@@ -629,7 +629,7 @@ fn visit_terminator_kind(
.eval_operand
(
len
,
source_info
)
.expect
(
"len must be const"
);
let
len
=
match
len
.0
.to_immediate
()
{
Valu
e
::
Scalar
(
ScalarMaybeUndef
::
Scalar
(
Scalar
::
Bits
{
Immediat
e
::
Scalar
(
ScalarMaybeUndef
::
Scalar
(
Scalar
::
Bits
{
bits
,
..
}))
=>
bits
,
_
=>
bug!
(
"const len not primitive: {:?}"
,
len
),
...
...
@@ -638,7 +638,7 @@ fn visit_terminator_kind(
.eval_operand
(
index
,
source_info
)
.expect
(
"index must be const"
);
let
index
=
match
index
.0
.to_immediate
()
{
Valu
e
::
Scalar
(
ScalarMaybeUndef
::
Scalar
(
Scalar
::
Bits
{
Immediat
e
::
Scalar
(
ScalarMaybeUndef
::
Scalar
(
Scalar
::
Bits
{
bits
,
..
}))
=>
bits
,
_
=>
bug!
(
"const index not primitive: {:?}"
,
index
),
...
...
src/tools/linkchecker/main.rs
浏览文件 @
e8a22b69
...
...
@@ -133,7 +133,7 @@ fn check(cache: &mut Cache,
// whitelists to get this past `make check` today.
// FIXME(#32129)
if
file
.ends_with
(
"std/string/struct.String.html"
)
||
file
.ends_with
(
"interpret/struct.
Val
Ty.html"
)
||
file
.ends_with
(
"interpret/struct.
Imm
Ty.html"
)
||
file
.ends_with
(
"symbol/struct.InternedString.html"
)
||
file
.ends_with
(
"ast/struct.ThinVec.html"
)
||
file
.ends_with
(
"util/struct.ThinVec.html"
)
||
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录