Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
64a75ecc
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,发现更多精彩内容 >>
提交
64a75ecc
编写于
5月 22, 2018
作者:
O
Oliver Schneider
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
change `Value::Bytes` to `Value::Bits`
上级
3bbf2fd7
变更
24
隐藏空白更改
内联
并排
Showing
24 changed file
with
436 addition
and
281 deletion
+436
-281
src/librustc/ich/impls_ty.rs
src/librustc/ich/impls_ty.rs
+18
-5
src/librustc/mir/interpret/value.rs
src/librustc/mir/interpret/value.rs
+72
-88
src/librustc/mir/mod.rs
src/librustc/mir/mod.rs
+16
-11
src/librustc/ty/mod.rs
src/librustc/ty/mod.rs
+1
-1
src/librustc/ty/sty.rs
src/librustc/ty/sty.rs
+36
-12
src/librustc_codegen_llvm/mir/constant.rs
src/librustc_codegen_llvm/mir/constant.rs
+6
-4
src/librustc_mir/build/expr/as_rvalue.rs
src/librustc_mir/build/expr/as_rvalue.rs
+2
-2
src/librustc_mir/build/matches/test.rs
src/librustc_mir/build/matches/test.rs
+1
-1
src/librustc_mir/build/misc.rs
src/librustc_mir/build/misc.rs
+0
-9
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/expr.rs
+2
-1
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/hair/cx/mod.rs
+24
-23
src/librustc_mir/hair/pattern/_match.rs
src/librustc_mir/hair/pattern/_match.rs
+1
-1
src/librustc_mir/hair/pattern/mod.rs
src/librustc_mir/hair/pattern/mod.rs
+27
-12
src/librustc_mir/interpret/cast.rs
src/librustc_mir/interpret/cast.rs
+62
-18
src/librustc_mir/interpret/const_eval.rs
src/librustc_mir/interpret/const_eval.rs
+16
-5
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/eval_context.rs
+57
-30
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/memory.rs
+20
-15
src/librustc_mir/interpret/operator.rs
src/librustc_mir/interpret/operator.rs
+42
-22
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/place.rs
+6
-4
src/librustc_mir/interpret/terminator/drop.rs
src/librustc_mir/interpret/terminator/drop.rs
+1
-1
src/librustc_mir/interpret/terminator/mod.rs
src/librustc_mir/interpret/terminator/mod.rs
+4
-4
src/librustc_mir/interpret/traits.rs
src/librustc_mir/interpret/traits.rs
+12
-5
src/librustc_mir/transform/const_prop.rs
src/librustc_mir/transform/const_prop.rs
+9
-6
src/librustc_mir/transform/simplify_branches.rs
src/librustc_mir/transform/simplify_branches.rs
+1
-1
未找到文件。
src/librustc/ich/impls_ty.rs
浏览文件 @
64a75ecc
...
...
@@ -473,11 +473,24 @@ fn hash_stable<W: StableHasherResult>(
Mutable
});
impl_stable_hash_for!
(
enum
mir
::
interpret
::
Scalar
{
Bytes
(
b
),
Ptr
(
p
),
Undef
});
impl
<
'a
>
HashStable
<
StableHashingContext
<
'a
>>
for
::
mir
::
interpret
::
Scalar
{
fn
hash_stable
<
W
:
StableHasherResult
>
(
&
self
,
hcx
:
&
mut
StableHashingContext
<
'a
>
,
hasher
:
&
mut
StableHasher
<
W
>
)
{
use
mir
::
interpret
::
Scalar
::
*
;
mem
::
discriminant
(
self
)
.hash_stable
(
hcx
,
hasher
);
match
*
self
{
Bits
{
bits
,
defined
}
=>
{
bits
.hash_stable
(
hcx
,
hasher
);
defined
.hash_stable
(
hcx
,
hasher
);
},
Ptr
(
ptr
)
=>
ptr
.hash_stable
(
hcx
,
hasher
),
}
}
}
impl_stable_hash_for!
(
struct
ty
::
Const
<
'tcx
>
{
ty
,
...
...
src/librustc/mir/interpret/value.rs
浏览文件 @
64a75ecc
...
...
@@ -51,19 +51,13 @@ pub fn to_primval(&self) -> Option<Scalar> {
}
#[inline]
pub
fn
to_bits
(
&
self
)
->
Option
<
u128
>
{
match
self
.to_primval
()
{
Some
(
Scalar
::
Bytes
(
val
))
=>
Some
(
val
),
_
=>
None
,
}
pub
fn
to_bits
(
&
self
,
size
:
Size
)
->
Option
<
u128
>
{
self
.to_primval
()
?
.to_bits
(
size
)
.ok
()
}
#[inline]
pub
fn
to_ptr
(
&
self
)
->
Option
<
Pointer
>
{
match
self
.to_primval
()
{
Some
(
Scalar
::
Ptr
(
ptr
))
=>
Some
(
ptr
),
_
=>
None
,
}
self
.to_primval
()
?
.to_ptr
()
.ok
()
}
}
...
...
@@ -93,56 +87,85 @@ fn super_visit_with<V: ty::fold::TypeVisitor<'tcx>>(&self, _: &mut V) -> bool {
}
impl
<
'tcx
>
Scalar
{
pub
fn
ptr_null
()
->
Self
{
Scalar
::
Bytes
(
0
)
pub
fn
ptr_null
<
C
:
HasDataLayout
>
(
cx
:
C
)
->
Self
{
Scalar
::
Bits
{
bits
:
0
,
defined
:
cx
.data_layout
()
.pointer_size
.bits
()
as
u8
,
}
}
pub
fn
ptr_signed_offset
<
C
:
HasDataLayout
>
(
self
,
i
:
i64
,
cx
:
C
)
->
EvalResult
<
'tcx
,
Self
>
{
let
layout
=
cx
.data_layout
();
match
self
{
Scalar
::
Bytes
(
b
)
=>
{
assert_eq!
(
b
as
u64
as
u128
,
b
);
Ok
(
Scalar
::
Bytes
(
layout
.signed_offset
(
b
as
u64
,
i
)
?
as
u128
))
Scalar
::
Bits
{
bits
,
defined
}
=>
{
let
pointer_size
=
layout
.pointer_size
.bits
()
as
u8
;
if
defined
<
pointer_size
{
err!
(
ReadUndefBytes
)
}
else
{
Ok
(
Scalar
::
Bits
{
bits
:
layout
.signed_offset
(
bits
as
u64
,
i
)
?
as
u128
,
defined
:
pointer_size
,
})
}
}
Scalar
::
Ptr
(
ptr
)
=>
ptr
.signed_offset
(
i
,
layout
)
.map
(
Scalar
::
Ptr
),
Scalar
::
Undef
=>
err!
(
ReadUndefBytes
),
}
}
pub
fn
ptr_offset
<
C
:
HasDataLayout
>
(
self
,
i
:
Size
,
cx
:
C
)
->
EvalResult
<
'tcx
,
Self
>
{
let
layout
=
cx
.data_layout
();
match
self
{
Scalar
::
Bytes
(
b
)
=>
{
assert_eq!
(
b
as
u64
as
u128
,
b
);
Ok
(
Scalar
::
Bytes
(
layout
.offset
(
b
as
u64
,
i
.bytes
())
?
as
u128
))
Scalar
::
Bits
{
bits
,
defined
}
=>
{
let
pointer_size
=
layout
.pointer_size
.bits
()
as
u8
;
if
defined
<
pointer_size
{
err!
(
ReadUndefBytes
)
}
else
{
Ok
(
Scalar
::
Bits
{
bits
:
layout
.offset
(
bits
as
u64
,
i
.bytes
())
?
as
u128
,
defined
:
pointer_size
,
})
}
}
Scalar
::
Ptr
(
ptr
)
=>
ptr
.offset
(
i
,
layout
)
.map
(
Scalar
::
Ptr
),
Scalar
::
Undef
=>
err!
(
ReadUndefBytes
),
}
}
pub
fn
ptr_wrapping_signed_offset
<
C
:
HasDataLayout
>
(
self
,
i
:
i64
,
cx
:
C
)
->
EvalResult
<
'tcx
,
Self
>
{
let
layout
=
cx
.data_layout
();
match
self
{
Scalar
::
Bytes
(
b
)
=>
{
assert_eq!
(
b
as
u64
as
u128
,
b
);
Ok
(
Scalar
::
Bytes
(
layout
.wrapping_signed_offset
(
b
as
u64
,
i
)
as
u128
))
Scalar
::
Bits
{
bits
,
defined
}
=>
{
let
pointer_size
=
layout
.pointer_size
.bits
()
as
u8
;
if
defined
<
pointer_size
{
err!
(
ReadUndefBytes
)
}
else
{
Ok
(
Scalar
::
Bits
{
bits
:
layout
.wrapping_signed_offset
(
bits
as
u64
,
i
)
as
u128
,
defined
:
pointer_size
,
})
}
}
Scalar
::
Ptr
(
ptr
)
=>
Ok
(
Scalar
::
Ptr
(
ptr
.wrapping_signed_offset
(
i
,
layout
))),
Scalar
::
Undef
=>
err!
(
ReadUndefBytes
),
}
}
pub
fn
is_null
(
self
)
->
EvalResult
<
'tcx
,
bool
>
{
pub
fn
is_null
_ptr
<
C
:
HasDataLayout
>
(
self
,
cx
:
C
)
->
EvalResult
<
'tcx
,
bool
>
{
match
self
{
Scalar
::
Bytes
(
b
)
=>
Ok
(
b
==
0
),
Scalar
::
Bits
{
bits
,
defined
,
}
=>
if
defined
<
cx
.data_layout
()
.pointer_size
.bits
()
as
u8
{
err!
(
ReadUndefBytes
)
}
else
{
Ok
(
bits
==
0
)
},
Scalar
::
Ptr
(
_
)
=>
Ok
(
false
),
Scalar
::
Undef
=>
err!
(
ReadUndefBytes
),
}
}
pub
fn
to_value_with_len
(
self
,
len
:
u64
)
->
Value
{
Value
::
ScalarPair
(
self
,
Scalar
::
from_u128
(
len
as
u128
))
pub
fn
to_value_with_len
<
C
:
HasDataLayout
>
(
self
,
len
:
u64
,
cx
:
C
)
->
Value
{
Value
::
ScalarPair
(
self
,
Scalar
::
Bits
{
bits
:
len
as
u128
,
defined
:
cx
.data_layout
()
.pointer_size
.bits
()
as
u8
,
})
}
pub
fn
to_value_with_vtable
(
self
,
vtable
:
Pointer
)
->
Value
{
...
...
@@ -163,20 +186,20 @@ fn from(ptr: Pointer) -> Self {
/// A `Scalar` represents an immediate, primitive value existing outside of a
/// `memory::Allocation`. It is in many ways like a small chunk of a `Allocation`, up to 8 bytes in
/// size. Like a range of bytes in an `Allocation`, a `Scalar` can either represent the raw bytes
/// of a simple value
, a pointer into another `Allocation`, or be undefined.
/// of a simple value
or a pointer into another `Allocation`
#[derive(Clone,
Copy,
Debug,
Eq,
PartialEq,
Ord,
PartialOrd,
RustcEncodable,
RustcDecodable,
Hash)]
pub
enum
Scalar
{
/// The raw bytes of a simple value.
Bytes
(
u128
),
Bits
{
/// number of bits that are valid and may be read
defined
:
u8
,
bits
:
u128
,
},
/// A pointer into an `Allocation`. An `Allocation` in the `memory` module has a list of
/// relocations, but a `Scalar` is only large enough to contain one, so we just represent the
/// relocation and its associated offset together as a `Pointer` here.
Ptr
(
Pointer
),
/// An undefined `Scalar`, for representing values that aren't safe to examine, but are safe
/// to copy around, just like undefined bytes in an `Allocation`.
Undef
,
}
#[derive(Clone,
Copy,
Debug,
PartialEq)]
...
...
@@ -190,41 +213,38 @@ pub enum ScalarKind {
}
impl
<
'tcx
>
Scalar
{
pub
fn
from_u128
(
n
:
u128
)
->
Self
{
Scalar
::
Bytes
(
n
)
}
pub
fn
from_i128
(
n
:
i128
)
->
Self
{
Scalar
::
Bytes
(
n
as
u128
)
pub
fn
undef
()
->
Self
{
Scalar
::
Bits
{
bits
:
0
,
defined
:
0
}
}
pub
fn
from_bool
(
b
:
bool
)
->
Self
{
Scalar
::
Bytes
(
b
as
u128
)
// FIXME: can we make defined `1`?
Scalar
::
Bits
{
bits
:
b
as
u128
,
defined
:
8
}
}
pub
fn
from_char
(
c
:
char
)
->
Self
{
Scalar
::
B
ytes
(
c
as
u128
)
Scalar
::
B
its
{
bits
:
c
as
u128
,
defined
:
32
}
}
pub
fn
to_b
ytes
(
self
)
->
EvalResult
<
'tcx
,
u128
>
{
pub
fn
to_b
its
(
self
,
size
:
Size
)
->
EvalResult
<
'tcx
,
u128
>
{
match
self
{
Scalar
::
Bytes
(
b
)
=>
Ok
(
b
),
Scalar
::
Bits
{
defined
:
0
,
..
}
=>
err!
(
ReadUndefBytes
),
Scalar
::
Bits
{
bits
,
defined
}
if
size
.bits
()
<=
defined
as
u64
=>
Ok
(
bits
),
Scalar
::
Bits
{
..
}
=>
err!
(
ReadUndefBytes
),
Scalar
::
Ptr
(
_
)
=>
err!
(
ReadPointerAsBytes
),
Scalar
::
Undef
=>
err!
(
ReadUndefBytes
),
}
}
pub
fn
to_ptr
(
self
)
->
EvalResult
<
'tcx
,
Pointer
>
{
match
self
{
Scalar
::
B
ytes
(
_
)
=>
err!
(
ReadBytesAsPointer
),
Scalar
::
B
its
{
..
}
=>
err!
(
ReadBytesAsPointer
),
Scalar
::
Ptr
(
p
)
=>
Ok
(
p
),
Scalar
::
Undef
=>
err!
(
ReadUndefBytes
),
}
}
pub
fn
is_b
yte
s
(
self
)
->
bool
{
pub
fn
is_b
it
s
(
self
)
->
bool
{
match
self
{
Scalar
::
B
ytes
(
_
)
=>
true
,
Scalar
::
B
its
{
..
}
=>
true
,
_
=>
false
,
}
}
...
...
@@ -236,46 +256,10 @@ pub fn is_ptr(self) -> bool {
}
}
pub
fn
is_undef
(
self
)
->
bool
{
match
self
{
Scalar
::
Undef
=>
true
,
_
=>
false
,
}
}
pub
fn
to_u128
(
self
)
->
EvalResult
<
'tcx
,
u128
>
{
self
.to_bytes
()
}
pub
fn
to_u64
(
self
)
->
EvalResult
<
'tcx
,
u64
>
{
self
.to_bytes
()
.map
(|
b
|
{
assert_eq!
(
b
as
u64
as
u128
,
b
);
b
as
u64
})
}
pub
fn
to_i32
(
self
)
->
EvalResult
<
'tcx
,
i32
>
{
self
.to_bytes
()
.map
(|
b
|
{
assert_eq!
(
b
as
i32
as
u128
,
b
);
b
as
i32
})
}
pub
fn
to_i128
(
self
)
->
EvalResult
<
'tcx
,
i128
>
{
self
.to_bytes
()
.map
(|
b
|
b
as
i128
)
}
pub
fn
to_i64
(
self
)
->
EvalResult
<
'tcx
,
i64
>
{
self
.to_bytes
()
.map
(|
b
|
{
assert_eq!
(
b
as
i64
as
u128
,
b
);
b
as
i64
})
}
pub
fn
to_bool
(
self
)
->
EvalResult
<
'tcx
,
bool
>
{
match
self
.to_bytes
()
?
{
0
=>
Ok
(
false
),
1
=>
Ok
(
true
),
match
self
{
Scalar
::
Bits
{
bits
:
0
,
defined
:
8
}
=>
Ok
(
false
),
Scalar
::
Bits
{
bits
:
1
,
defined
:
8
}
=>
Ok
(
true
),
_
=>
err!
(
InvalidBool
),
}
}
...
...
src/librustc/mir/mod.rs
浏览文件 @
64a75ecc
...
...
@@ -1149,11 +1149,13 @@ pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
Return
|
Resume
|
Abort
|
Unreachable
|
GeneratorDrop
=>
vec!
[],
Goto
{
..
}
=>
vec!
[
""
.into
()],
SwitchInt
{
ref
values
,
switch_ty
,
..
}
=>
{
let
size
=
ty
::
tls
::
with
(|
tcx
|
switch_ty
.scalar_size
(
tcx
));
let
size
=
size
.map_or
(
0
,
|
size
|
size
.bytes
())
as
u8
;
values
.iter
()
.map
(|
&
u
|
{
let
mut
s
=
String
::
new
();
print_miri_value
(
Value
::
Scalar
(
Scalar
::
B
ytes
(
u
)
),
Value
::
Scalar
(
Scalar
::
B
its
{
bits
:
u
,
defined
:
size
}
),
switch_ty
,
&
mut
s
,
)
.unwrap
();
...
...
@@ -1893,19 +1895,22 @@ pub fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ty::Const) -> fmt::Resul
pub
fn
print_miri_value
<
W
:
Write
>
(
value
:
Value
,
ty
:
Ty
,
f
:
&
mut
W
)
->
fmt
::
Result
{
use
ty
::
TypeVariants
::
*
;
match
(
value
,
&
ty
.sty
)
{
(
Value
::
Scalar
(
Scalar
::
B
ytes
(
0
)
),
&
TyBool
)
=>
write!
(
f
,
"false"
),
(
Value
::
Scalar
(
Scalar
::
B
ytes
(
1
)
),
&
TyBool
)
=>
write!
(
f
,
"true"
),
(
Value
::
Scalar
(
Scalar
::
B
ytes
(
bits
)
),
&
TyFloat
(
ast
::
FloatTy
::
F32
))
=>
(
Value
::
Scalar
(
Scalar
::
B
its
{
bits
:
0
,
defined
:
8
}
),
&
TyBool
)
=>
write!
(
f
,
"false"
),
(
Value
::
Scalar
(
Scalar
::
B
its
{
bits
:
1
,
defined
:
8
}
),
&
TyBool
)
=>
write!
(
f
,
"true"
),
(
Value
::
Scalar
(
Scalar
::
B
its
{
bits
,
defined
:
32
}
),
&
TyFloat
(
ast
::
FloatTy
::
F32
))
=>
write!
(
f
,
"{}f32"
,
Single
::
from_bits
(
bits
)),
(
Value
::
Scalar
(
Scalar
::
B
ytes
(
bits
)
),
&
TyFloat
(
ast
::
FloatTy
::
F64
))
=>
(
Value
::
Scalar
(
Scalar
::
B
its
{
bits
,
defined
:
64
}
),
&
TyFloat
(
ast
::
FloatTy
::
F64
))
=>
write!
(
f
,
"{}f64"
,
Double
::
from_bits
(
bits
)),
(
Value
::
Scalar
(
Scalar
::
Bytes
(
n
)),
&
TyUint
(
ui
))
=>
write!
(
f
,
"{:?}{}"
,
n
,
ui
),
(
Value
::
Scalar
(
Scalar
::
Bytes
(
n
)),
&
TyInt
(
i
))
=>
write!
(
f
,
"{:?}{}"
,
n
as
i128
,
i
),
(
Value
::
Scalar
(
Scalar
::
Bytes
(
n
)),
&
TyChar
)
=>
write!
(
f
,
"{:?}"
,
::
std
::
char
::
from_u32
(
n
as
u32
)
.unwrap
()),
(
Value
::
Scalar
(
Scalar
::
Undef
),
&
TyFnDef
(
did
,
_
))
=>
(
Value
::
Scalar
(
Scalar
::
Bits
{
bits
,
..
}),
&
TyUint
(
ui
))
=>
write!
(
f
,
"{:?}{}"
,
bits
,
ui
),
(
Value
::
Scalar
(
Scalar
::
Bits
{
bits
,
defined
}),
&
TyInt
(
i
))
=>
{
let
amt
=
128
-
defined
;
write!
(
f
,
"{:?}{}"
,
((
bits
as
i128
)
<<
amt
)
>>
amt
,
i
)
},
(
Value
::
Scalar
(
Scalar
::
Bits
{
bits
,
defined
:
32
}),
&
TyChar
)
=>
write!
(
f
,
"{:?}"
,
::
std
::
char
::
from_u32
(
bits
as
u32
)
.unwrap
()),
(
Value
::
Scalar
(
Scalar
::
Bits
{
defined
:
0
,
..
}),
&
TyFnDef
(
did
,
_
))
=>
write!
(
f
,
"{}"
,
item_path_str
(
did
)),
(
Value
::
ScalarPair
(
Scalar
::
Ptr
(
ptr
),
Scalar
::
B
ytes
(
len
)
),
(
Value
::
ScalarPair
(
Scalar
::
Ptr
(
ptr
),
Scalar
::
B
its
{
bits
:
len
,
..
}
),
&
TyRef
(
_
,
&
ty
::
TyS
{
sty
:
TyStr
,
..
},
_
))
=>
{
ty
::
tls
::
with
(|
tcx
|
{
match
tcx
.alloc_map
.lock
()
.get
(
ptr
.alloc_id
)
{
...
...
src/librustc/ty/mod.rs
浏览文件 @
64a75ecc
...
...
@@ -1982,7 +1982,7 @@ pub fn eval_explicit_discr(
match
tcx
.const_eval
(
param_env
.and
(
cid
))
{
Ok
(
val
)
=>
{
// FIXME: Find the right type and use it instead of `val.ty` here
if
let
Some
(
b
)
=
val
.assert_bits
(
val
.ty
)
{
if
let
Some
(
b
)
=
val
.assert_bits
(
tcx
,
val
.ty
)
{
trace!
(
"discriminants: {} ({:?})"
,
b
,
repr_type
);
Some
(
Discr
{
val
:
b
,
...
...
src/librustc/ty/sty.rs
浏览文件 @
64a75ecc
...
...
@@ -17,15 +17,17 @@
use
rustc_data_structures
::
indexed_vec
::
Idx
;
use
ty
::
subst
::{
Substs
,
Subst
,
Kind
,
UnpackedKind
};
use
ty
::{
self
,
AdtDef
,
TypeFlags
,
Ty
,
TyCtxt
,
TypeFoldable
};
use
ty
::{
Slice
,
TyS
};
use
ty
::{
Slice
,
TyS
,
layout
};
use
util
::
captures
::
Captures
;
use
mir
::
interpret
::{
Scalar
,
Pointer
,
Value
,
ConstValue
};
use
rustc_target
::
abi
::{
Size
,
HasDataLayout
};
use
std
::
iter
;
use
std
::
cmp
::
Ordering
;
use
rustc_target
::
spec
::
abi
;
use
syntax
::
ast
::{
self
,
Name
};
use
syntax
::
symbol
::{
keywords
,
InternedString
};
use
syntax
::
attr
;
use
serialize
;
...
...
@@ -1755,6 +1757,23 @@ pub fn to_opt_closure_kind(&self) -> Option<ty::ClosureKind> {
_
=>
bug!
(
"cannot convert type `{:?}` to a closure kind"
,
self
),
}
}
/// If this type is a scalar, compute its size without
/// going through `tcx.layout_of`
pub
fn
scalar_size
<
C
:
HasDataLayout
>
(
&
self
,
cx
:
C
,
)
->
Option
<
Size
>
{
let
ty
=
match
self
.sty
{
ty
::
TyBool
=>
return
Some
(
Size
::
from_bytes
(
1
)),
ty
::
TyChar
=>
return
Some
(
Size
::
from_bytes
(
4
)),
ty
::
TyInt
(
ity
)
=>
attr
::
IntType
::
SignedInt
(
ity
),
ty
::
TyUint
(
uty
)
=>
attr
::
IntType
::
UnsignedInt
(
uty
),
_
=>
return
None
,
};
use
ty
::
layout
::
IntegerExt
;
Some
(
layout
::
Integer
::
from_attr
(
cx
,
ty
)
.size
())
}
}
/// Typed constant value.
...
...
@@ -1820,15 +1839,18 @@ pub fn from_primval(
#[inline]
pub
fn
from_bits
(
tcx
:
TyCtxt
<
'_
,
'_
,
'tcx
>
,
val
:
u128
,
bits
:
u128
,
ty
:
Ty
<
'tcx
>
,
)
->
&
'tcx
Self
{
Self
::
from_primval
(
tcx
,
Scalar
::
Bytes
(
val
),
ty
)
let
defined
=
ty
.scalar_size
(
tcx
)
.unwrap_or_else
(||
{
panic!
(
"non-scalar type in from_bits: {:?}"
,
ty
)
})
.bits
()
as
u8
;
Self
::
from_primval
(
tcx
,
Scalar
::
Bits
{
bits
,
defined
},
ty
)
}
#[inline]
pub
fn
zero_sized
(
tcx
:
TyCtxt
<
'_
,
'_
,
'tcx
>
,
ty
:
Ty
<
'tcx
>
)
->
&
'tcx
Self
{
Self
::
from_primval
(
tcx
,
Scalar
::
Undef
,
ty
)
Self
::
from_primval
(
tcx
,
Scalar
::
undef
()
,
ty
)
}
#[inline]
...
...
@@ -1842,12 +1864,13 @@ pub fn from_usize(tcx: TyCtxt<'_, '_, 'tcx>, n: u64) -> &'tcx Self {
}
#[inline]
pub
fn
to_bits
(
&
self
,
ty
:
Ty
<
'_
>
)
->
Option
<
u128
>
{
pub
fn
to_bits
<
C
:
HasDataLayout
>
(
&
self
,
cx
:
C
,
ty
:
Ty
<
'tcx
>
)
->
Option
<
u128
>
{
if
self
.ty
!=
ty
{
return
None
;
}
let
size
=
ty
.scalar_size
(
cx
)
?
;
match
self
.val
{
ConstVal
::
Value
(
val
)
=>
val
.to_bits
(),
ConstVal
::
Value
(
val
)
=>
val
.to_bits
(
size
),
_
=>
None
,
}
}
...
...
@@ -1877,17 +1900,18 @@ pub fn to_primval(&self) -> Option<Scalar> {
}
#[inline]
pub
fn
assert_bits
(
&
self
,
ty
:
Ty
<
'_
>
)
->
Option
<
u128
>
{
pub
fn
assert_bits
<
C
:
HasDataLayout
>
(
&
self
,
cx
:
C
,
ty
:
Ty
<
'tcx
>
)
->
Option
<
u128
>
{
assert_eq!
(
self
.ty
,
ty
);
let
size
=
ty
.scalar_size
(
cx
)
?
;
match
self
.val
{
ConstVal
::
Value
(
val
)
=>
val
.to_bits
(),
ConstVal
::
Value
(
val
)
=>
val
.to_bits
(
size
),
_
=>
None
,
}
}
#[inline]
pub
fn
assert_bool
(
&
self
,
tcx
:
TyCtxt
<
'_
,
'_
,
'_
>
)
->
Option
<
bool
>
{
self
.assert_bits
(
tcx
.types.bool
)
.and_then
(|
v
|
match
v
{
self
.assert_bits
(
tcx
,
tcx
.types.bool
)
.and_then
(|
v
|
match
v
{
0
=>
Some
(
false
),
1
=>
Some
(
true
),
_
=>
None
,
...
...
@@ -1896,12 +1920,12 @@ pub fn assert_bool(&self, tcx: TyCtxt<'_, '_, '_>) -> Option<bool> {
#[inline]
pub
fn
assert_usize
(
&
self
,
tcx
:
TyCtxt
<
'_
,
'_
,
'_
>
)
->
Option
<
u64
>
{
self
.assert_bits
(
tcx
.types.usize
)
.map
(|
v
|
v
as
u64
)
self
.assert_bits
(
tcx
,
tcx
.types.usize
)
.map
(|
v
|
v
as
u64
)
}
#[inline]
pub
fn
unwrap_bits
(
&
self
,
t
y
:
Ty
<
'_
>
)
->
u128
{
match
self
.assert_bits
(
ty
)
{
pub
fn
unwrap_bits
(
&
self
,
t
cx
:
TyCtxt
<
'_
,
'_
,
'_
>
,
ty
:
Ty
<
'tcx
>
)
->
u128
{
match
self
.assert_bits
(
t
cx
,
t
y
)
{
Some
(
val
)
=>
val
,
None
=>
bug!
(
"expected bits of {}, got {:#?}"
,
ty
,
self
),
}
...
...
src/librustc_codegen_llvm/mir/constant.rs
浏览文件 @
64a75ecc
...
...
@@ -32,11 +32,13 @@ pub fn primval_to_llvm(cx: &CodegenCx,
cv
:
Scalar
,
layout
:
&
layout
::
Scalar
,
llty
:
Type
)
->
ValueRef
{
let
bits
=
if
layout
.is_bool
()
{
1
}
else
{
layout
.value
.size
(
cx
)
.bits
()
};
let
bits
ize
=
if
layout
.is_bool
()
{
1
}
else
{
layout
.value
.size
(
cx
)
.bits
()
};
match
cv
{
Scalar
::
Undef
=>
C_undef
(
Type
::
ix
(
cx
,
bits
)),
Scalar
::
Bytes
(
b
)
=>
{
let
llval
=
C_uint_big
(
Type
::
ix
(
cx
,
bits
),
b
);
Scalar
::
Bits
{
defined
,
..
}
if
(
defined
as
u64
)
<
bitsize
||
defined
==
0
=>
{
C_undef
(
Type
::
ix
(
cx
,
bitsize
))
},
Scalar
::
Bits
{
bits
,
..
}
=>
{
let
llval
=
C_uint_big
(
Type
::
ix
(
cx
,
bitsize
),
bits
);
if
layout
.value
==
layout
::
Pointer
{
unsafe
{
llvm
::
LLVMConstIntToPtr
(
llval
,
llty
.to_ref
())
}
}
else
{
...
...
src/librustc_mir/build/expr/as_rvalue.rs
浏览文件 @
64a75ecc
...
...
@@ -374,7 +374,7 @@ pub fn build_binary_op(&mut self, mut block: BasicBlock,
// Helper to get a `-1` value of the appropriate type
fn
neg_1_literal
(
&
mut
self
,
span
:
Span
,
ty
:
Ty
<
'tcx
>
)
->
Operand
<
'tcx
>
{
let
bits
=
self
.hir
.integer_bit_width
(
ty
);
let
bits
=
ty
.scalar_size
(
self
.hir
.tcx
())
.expect
(
"neg_1_literal expects integers"
)
.bits
(
);
let
n
=
(
!
0u128
)
>>
(
128
-
bits
);
let
literal
=
Literal
::
Value
{
value
:
ty
::
Const
::
from_bits
(
self
.hir
.tcx
(),
n
,
ty
)
...
...
@@ -386,7 +386,7 @@ fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
// Helper to get the minimum value of the appropriate type
fn
minval_literal
(
&
mut
self
,
span
:
Span
,
ty
:
Ty
<
'tcx
>
)
->
Operand
<
'tcx
>
{
assert
!
(
ty
.is_signed
());
let
bits
=
self
.hir
.integer_bit_width
(
ty
);
let
bits
=
ty
.scalar_size
(
self
.hir
.tcx
())
.expect
(
"minval_literal expects integers"
)
.bits
(
);
let
n
=
1
<<
(
bits
-
1
);
let
literal
=
Literal
::
Value
{
value
:
ty
::
Const
::
from_bits
(
self
.hir
.tcx
(),
n
,
ty
)
...
...
src/librustc_mir/build/matches/test.rs
浏览文件 @
64a75ecc
...
...
@@ -124,7 +124,7 @@ pub fn add_cases_to_switch<'pat>(&mut self,
PatternKind
::
Constant
{
value
}
=>
{
indices
.entry
(
value
)
.or_insert_with
(||
{
options
.push
(
value
.unwrap_bits
(
switch_ty
));
options
.push
(
value
.unwrap_bits
(
s
elf
.hir
.tcx
(),
s
witch_ty
));
options
.len
()
-
1
});
true
...
...
src/librustc_mir/build/misc.rs
浏览文件 @
64a75ecc
...
...
@@ -52,15 +52,6 @@ pub fn unit_rvalue(&mut self) -> Rvalue<'tcx> {
// Returns a zero literal operand for the appropriate type, works for
// bool, char and integers.
pub
fn
zero_literal
(
&
mut
self
,
span
:
Span
,
ty
:
Ty
<
'tcx
>
)
->
Operand
<
'tcx
>
{
match
ty
.sty
{
ty
::
TyBool
|
ty
::
TyChar
|
ty
::
TyUint
(
_
)
|
ty
::
TyInt
(
_
)
=>
{}
_
=>
{
span_bug!
(
span
,
"Invalid type for zero_literal: `{:?}`"
,
ty
)
}
}
let
literal
=
Literal
::
Value
{
value
:
ty
::
Const
::
from_bits
(
self
.hir
.tcx
(),
0
,
ty
)
};
...
...
src/librustc_mir/hair/cx/expr.rs
浏览文件 @
64a75ecc
...
...
@@ -614,7 +614,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
let
idx
=
adt_def
.variant_index_with_id
(
variant_id
);
let
(
d
,
o
)
=
adt_def
.discriminant_def_for_variant
(
idx
);
use
rustc
::
ty
::
util
::
IntTypeExt
;
let
ty
=
adt_def
.repr
.discr_type
()
.to_ty
(
cx
.tcx
());
let
ty
=
adt_def
.repr
.discr_type
();
let
ty
=
ty
.to_ty
(
cx
.tcx
());
Some
((
d
,
o
,
ty
))
}
_
=>
None
,
...
...
src/librustc_mir/hair/cx/mod.rs
浏览文件 @
64a75ecc
...
...
@@ -21,9 +21,8 @@
use
rustc
::
hir
::
map
::
blocks
::
FnLikeNode
;
use
rustc
::
middle
::
region
;
use
rustc
::
infer
::
InferCtxt
;
use
rustc
::
ty
::
layout
::
IntegerExt
;
use
rustc
::
ty
::
subst
::
Subst
;
use
rustc
::
ty
::{
self
,
Ty
,
TyCtxt
,
layout
};
use
rustc
::
ty
::{
self
,
Ty
,
TyCtxt
};
use
rustc
::
ty
::
subst
::{
Kind
,
Substs
};
use
syntax
::
ast
::{
self
,
LitKind
};
use
syntax
::
attr
;
...
...
@@ -139,18 +138,6 @@ pub fn false_literal(&mut self) -> Literal<'tcx> {
}
}
pub
fn
integer_bit_width
(
&
self
,
ty
:
Ty
,
)
->
u64
{
let
ty
=
match
ty
.sty
{
ty
::
TyInt
(
ity
)
=>
attr
::
IntType
::
SignedInt
(
ity
),
ty
::
TyUint
(
uty
)
=>
attr
::
IntType
::
UnsignedInt
(
uty
),
_
=>
bug!
(
"{} is not an integer"
,
ty
),
};
layout
::
Integer
::
from_attr
(
self
.tcx
,
ty
)
.size
()
.bits
()
}
// FIXME: Combine with rustc_mir::hair::pattern::lit_to_const
pub
fn
const_eval_literal
(
&
mut
self
,
...
...
@@ -169,12 +156,15 @@ pub fn const_eval_literal(
};
let
clamp
=
|
n
|
{
let
size
=
self
.integer_bit_width
(
ty
);
let
size
=
ty
.scalar_size
(
self
.tcx
)
.expect
(
"const_eval_lit::clamp expects ints"
)
.bits
(
);
trace!
(
"clamp {} with size {} and amt {}"
,
n
,
size
,
128
-
size
);
let
amt
=
128
-
size
;
let
result
=
(
n
<<
amt
)
>>
amt
;
trace!
(
"clamp result: {}"
,
result
);
result
ConstValue
::
Scalar
(
Scalar
::
Bits
{
bits
:
result
,
defined
:
size
as
u8
,
})
};
use
rustc
::
mir
::
interpret
::
*
;
...
...
@@ -184,21 +174,26 @@ pub fn const_eval_literal(
let
id
=
self
.tcx
.allocate_bytes
(
s
.as_bytes
());
ConstValue
::
ScalarPair
(
Scalar
::
Ptr
(
id
.into
()),
Scalar
::
from_u128
(
s
.len
()
as
u128
),
Scalar
::
Bits
{
bits
:
s
.len
()
as
u128
,
defined
:
self
.tcx.data_layout.pointer_size
.bits
()
as
u8
,
}
)
},
LitKind
::
ByteStr
(
ref
data
)
=>
{
let
id
=
self
.tcx
.allocate_bytes
(
data
);
ConstValue
::
Scalar
(
Scalar
::
Ptr
(
id
.into
()))
},
LitKind
::
Byte
(
n
)
=>
ConstValue
::
Scalar
(
Scalar
::
Bytes
(
n
as
u128
)),
LitKind
::
Byte
(
n
)
=>
ConstValue
::
Scalar
(
Scalar
::
Bits
{
bits
:
n
as
u128
,
defined
:
8
,
}),
LitKind
::
Int
(
n
,
_
)
if
neg
=>
{
let
n
=
n
as
i128
;
let
n
=
n
.overflowing_neg
()
.0
;
let
n
=
clamp
(
n
as
u128
);
ConstValue
::
Scalar
(
Scalar
::
Bytes
(
n
))
clamp
(
n
as
u128
)
},
LitKind
::
Int
(
n
,
_
)
=>
ConstValue
::
Scalar
(
Scalar
::
Bytes
(
clamp
(
n
))
),
LitKind
::
Int
(
n
,
_
)
=>
clamp
(
n
),
LitKind
::
Float
(
n
,
fty
)
=>
{
parse_float
(
n
,
fty
)
}
...
...
@@ -209,8 +204,14 @@ pub fn const_eval_literal(
};
parse_float
(
n
,
fty
)
}
LitKind
::
Bool
(
b
)
=>
ConstValue
::
Scalar
(
Scalar
::
Bytes
(
b
as
u128
)),
LitKind
::
Char
(
c
)
=>
ConstValue
::
Scalar
(
Scalar
::
Bytes
(
c
as
u128
)),
LitKind
::
Bool
(
b
)
=>
ConstValue
::
Scalar
(
Scalar
::
Bits
{
bits
:
b
as
u128
,
defined
:
8
,
}),
LitKind
::
Char
(
c
)
=>
ConstValue
::
Scalar
(
Scalar
::
Bits
{
bits
:
c
as
u128
,
defined
:
32
,
}),
};
Literal
::
Value
{
value
:
ty
::
Const
::
from_const_value
(
self
.tcx
,
lit
,
ty
)
...
...
src/librustc_mir/hair/pattern/_match.rs
浏览文件 @
64a75ecc
...
...
@@ -958,7 +958,7 @@ fn slice_pat_covered_by_constructor<'tcx>(
{
match
pat
.kind
{
box
PatternKind
::
Constant
{
value
}
=>
{
let
b
=
value
.unwrap_bits
(
pat
.ty
);
let
b
=
value
.unwrap_bits
(
tcx
,
pat
.ty
);
assert_eq!
(
b
as
u8
as
u128
,
b
);
if
b
as
u8
!=
*
ch
{
return
Ok
(
false
);
...
...
src/librustc_mir/hair/pattern/mod.rs
浏览文件 @
64a75ecc
...
...
@@ -1057,7 +1057,7 @@ pub fn compare_const_vals<'a, 'tcx>(
// FIXME: This should use assert_bits(ty) instead of use_bits
// but triggers possibly bugs due to mismatching of arrays and slices
if
let
(
Some
(
a
),
Some
(
b
))
=
(
a
.to_bits
(
t
y
),
b
.to_bits
(
ty
))
{
if
let
(
Some
(
a
),
Some
(
b
))
=
(
a
.to_bits
(
t
cx
,
ty
),
b
.to_bits
(
tcx
,
ty
))
{
use
::
rustc_apfloat
::
Float
;
return
match
ty
.sty
{
ty
::
TyFloat
(
ast
::
FloatTy
::
F32
)
=>
{
...
...
@@ -1130,20 +1130,26 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
let
id
=
tcx
.allocate_bytes
(
s
.as_bytes
());
ConstValue
::
ScalarPair
(
Scalar
::
Ptr
(
id
.into
()),
Scalar
::
from_u128
(
s
.len
()
as
u128
),
Scalar
::
Bits
{
bits
:
s
.len
()
as
u128
,
defined
:
tcx
.data_layout.pointer_size
.bits
()
as
u8
,
},
)
},
LitKind
::
ByteStr
(
ref
data
)
=>
{
let
id
=
tcx
.allocate_bytes
(
data
);
ConstValue
::
Scalar
(
Scalar
::
Ptr
(
id
.into
()))
},
LitKind
::
Byte
(
n
)
=>
ConstValue
::
Scalar
(
Scalar
::
Bytes
(
n
as
u128
)),
LitKind
::
Byte
(
n
)
=>
ConstValue
::
Scalar
(
Scalar
::
Bits
{
bits
:
n
as
u128
,
defined
:
8
,
}),
LitKind
::
Int
(
n
,
_
)
=>
{
enum
Int
{
Signed
(
IntTy
),
Unsigned
(
UintTy
),
}
let
ty
=
match
ty
.sty
{
let
i
ty
=
match
ty
.sty
{
ty
::
TyInt
(
IntTy
::
Isize
)
=>
Int
::
Signed
(
tcx
.sess.target.isize_ty
),
ty
::
TyInt
(
other
)
=>
Int
::
Signed
(
other
),
ty
::
TyUint
(
UintTy
::
Usize
)
=>
Int
::
Unsigned
(
tcx
.sess.target.usize_ty
),
...
...
@@ -1152,7 +1158,7 @@ enum Int {
};
// This converts from LitKind::Int (which is sign extended) to
// Scalar::Bytes (which is zero extended)
let
n
=
match
ty
{
let
n
=
match
i
ty
{
// FIXME(oli-obk): are these casts correct?
Int
::
Signed
(
IntTy
::
I8
)
if
neg
=>
(
n
as
i8
)
.overflowing_neg
()
.0
as
u8
as
u128
,
...
...
@@ -1171,7 +1177,10 @@ enum Int {
Int
::
Signed
(
IntTy
::
I128
)|
Int
::
Unsigned
(
UintTy
::
U128
)
=>
n
,
_
=>
bug!
(),
};
ConstValue
::
Scalar
(
Scalar
::
Bytes
(
n
))
ConstValue
::
Scalar
(
Scalar
::
Bits
{
bits
:
n
,
defined
:
ty
.scalar_size
(
tcx
)
.unwrap
()
.bits
()
as
u8
,
})
},
LitKind
::
Float
(
n
,
fty
)
=>
{
parse_float
(
n
,
fty
,
neg
)
?
...
...
@@ -1183,8 +1192,14 @@ enum Int {
};
parse_float
(
n
,
fty
,
neg
)
?
}
LitKind
::
Bool
(
b
)
=>
ConstValue
::
Scalar
(
Scalar
::
Bytes
(
b
as
u128
)),
LitKind
::
Char
(
c
)
=>
ConstValue
::
Scalar
(
Scalar
::
Bytes
(
c
as
u128
)),
LitKind
::
Bool
(
b
)
=>
ConstValue
::
Scalar
(
Scalar
::
Bits
{
bits
:
b
as
u128
,
defined
:
8
,
}),
LitKind
::
Char
(
c
)
=>
ConstValue
::
Scalar
(
Scalar
::
Bits
{
bits
:
c
as
u128
,
defined
:
32
,
}),
};
Ok
(
ty
::
Const
::
from_const_value
(
tcx
,
lit
,
ty
))
}
...
...
@@ -1197,7 +1212,7 @@ pub fn parse_float<'tcx>(
let
num
=
num
.as_str
();
use
rustc_apfloat
::
ieee
::{
Single
,
Double
};
use
rustc_apfloat
::
Float
;
let
bits
=
match
fty
{
let
(
bits
,
defined
)
=
match
fty
{
ast
::
FloatTy
::
F32
=>
{
num
.parse
::
<
f32
>
()
.map_err
(|
_
|
())
?
;
let
mut
f
=
num
.parse
::
<
Single
>
()
.unwrap_or_else
(|
e
|
{
...
...
@@ -1206,7 +1221,7 @@ pub fn parse_float<'tcx>(
if
neg
{
f
=
-
f
;
}
f
.to_bits
(
)
(
f
.to_bits
(),
32
)
}
ast
::
FloatTy
::
F64
=>
{
num
.parse
::
<
f64
>
()
.map_err
(|
_
|
())
?
;
...
...
@@ -1216,9 +1231,9 @@ pub fn parse_float<'tcx>(
if
neg
{
f
=
-
f
;
}
f
.to_bits
(
)
(
f
.to_bits
(),
64
)
}
};
Ok
(
ConstValue
::
Scalar
(
Scalar
::
B
ytes
(
bits
)
))
Ok
(
ConstValue
::
Scalar
(
Scalar
::
B
its
{
bits
,
defined
}
))
}
src/librustc_mir/interpret/cast.rs
浏览文件 @
64a75ecc
...
...
@@ -18,12 +18,13 @@ pub(super) fn cast_primval(
trace!
(
"Casting {:?}: {:?} to {:?}"
,
val
,
src_ty
,
dest_ty
);
match
val
{
Scalar
::
Undef
=>
Ok
(
Scalar
::
Undef
),
Scalar
::
Bits
{
defined
:
0
,
..
}
=>
Ok
(
val
),
Scalar
::
Ptr
(
ptr
)
=>
self
.cast_from_ptr
(
ptr
,
dest_ty
),
Scalar
::
Bytes
(
b
)
=>
{
Scalar
::
Bits
{
bits
,
..
}
=>
{
// TODO(oli-obk): impl scalar_size for floats and check defined bits here
match
src_ty
.sty
{
TyFloat
(
fty
)
=>
self
.cast_from_float
(
b
,
fty
,
dest_ty
),
_
=>
self
.cast_from_int
(
b
,
src_ty
,
dest_ty
),
TyFloat
(
fty
)
=>
self
.cast_from_float
(
b
its
,
fty
,
dest_ty
),
_
=>
self
.cast_from_int
(
b
its
,
src_ty
,
dest_ty
),
}
}
}
...
...
@@ -46,20 +47,38 @@ fn cast_from_int(
match
dest_ty
.sty
{
TyInt
(
_
)
|
TyUint
(
_
)
=>
{
let
v
=
self
.truncate
(
v
,
dest_ty
)
?
;
Ok
(
Scalar
::
Bytes
(
v
))
Ok
(
Scalar
::
Bits
{
bits
:
v
,
defined
:
dest_ty
.scalar_size
(
self
.tcx.tcx
)
.unwrap
()
.bits
()
as
u8
,
})
}
TyFloat
(
FloatTy
::
F32
)
if
signed
=>
Ok
(
Scalar
::
Bytes
(
Single
::
from_i128
(
v
as
i128
)
.value
.to_bits
())),
TyFloat
(
FloatTy
::
F64
)
if
signed
=>
Ok
(
Scalar
::
Bytes
(
Double
::
from_i128
(
v
as
i128
)
.value
.to_bits
())),
TyFloat
(
FloatTy
::
F32
)
=>
Ok
(
Scalar
::
Bytes
(
Single
::
from_u128
(
v
)
.value
.to_bits
())),
TyFloat
(
FloatTy
::
F64
)
=>
Ok
(
Scalar
::
Bytes
(
Double
::
from_u128
(
v
)
.value
.to_bits
())),
TyFloat
(
FloatTy
::
F32
)
if
signed
=>
Ok
(
Scalar
::
Bits
{
bits
:
Single
::
from_i128
(
v
as
i128
)
.value
.to_bits
(),
defined
:
32
,
}),
TyFloat
(
FloatTy
::
F64
)
if
signed
=>
Ok
(
Scalar
::
Bits
{
bits
:
Double
::
from_i128
(
v
as
i128
)
.value
.to_bits
(),
defined
:
64
,
}),
TyFloat
(
FloatTy
::
F32
)
=>
Ok
(
Scalar
::
Bits
{
bits
:
Single
::
from_u128
(
v
)
.value
.to_bits
(),
defined
:
32
,
}),
TyFloat
(
FloatTy
::
F64
)
=>
Ok
(
Scalar
::
Bits
{
bits
:
Double
::
from_u128
(
v
)
.value
.to_bits
(),
defined
:
64
,
}),
TyChar
if
v
as
u8
as
u128
==
v
=>
Ok
(
Scalar
::
B
ytes
(
v
)
),
TyChar
if
v
as
u8
as
u128
==
v
=>
Ok
(
Scalar
::
B
its
{
bits
:
v
,
defined
:
32
}
),
TyChar
=>
err!
(
InvalidChar
(
v
)),
// No alignment check needed for raw pointers. But we have to truncate to target ptr size.
TyRawPtr
(
_
)
=>
{
Ok
(
Scalar
::
Bytes
(
self
.memory
.truncate_to_ptr
(
v
)
.0
as
u128
))
Ok
(
Scalar
::
Bits
{
bits
:
self
.memory
.truncate_to_ptr
(
v
)
.0
as
u128
,
defined
:
self
.memory
.pointer_size
()
.bits
()
as
u8
,
})
},
// Casts to bool are not permitted by rustc, no need to handle them here.
...
...
@@ -75,28 +94,53 @@ fn cast_from_float(&self, bits: u128, fty: FloatTy, dest_ty: Ty<'tcx>) -> EvalRe
TyUint
(
t
)
=>
{
let
width
=
t
.bit_width
()
.unwrap_or
(
self
.memory
.pointer_size
()
.bytes
()
as
usize
*
8
);
match
fty
{
FloatTy
::
F32
=>
Ok
(
Scalar
::
Bytes
(
Single
::
from_bits
(
bits
)
.to_u128
(
width
)
.value
)),
FloatTy
::
F64
=>
Ok
(
Scalar
::
Bytes
(
Double
::
from_bits
(
bits
)
.to_u128
(
width
)
.value
)),
FloatTy
::
F32
=>
Ok
(
Scalar
::
Bits
{
bits
:
Single
::
from_bits
(
bits
)
.to_u128
(
width
)
.value
,
defined
:
32
,
}),
FloatTy
::
F64
=>
Ok
(
Scalar
::
Bits
{
bits
:
Double
::
from_bits
(
bits
)
.to_u128
(
width
)
.value
,
defined
:
64
,
}),
}
},
// float -> int
TyInt
(
t
)
=>
{
let
width
=
t
.bit_width
()
.unwrap_or
(
self
.memory
.pointer_size
()
.bytes
()
as
usize
*
8
);
match
fty
{
FloatTy
::
F32
=>
Ok
(
Scalar
::
from_i128
(
Single
::
from_bits
(
bits
)
.to_i128
(
width
)
.value
)),
FloatTy
::
F64
=>
Ok
(
Scalar
::
from_i128
(
Double
::
from_bits
(
bits
)
.to_i128
(
width
)
.value
)),
FloatTy
::
F32
=>
Ok
(
Scalar
::
Bits
{
bits
:
Single
::
from_bits
(
bits
)
.to_i128
(
width
)
.value
as
u128
,
defined
:
32
,
}),
FloatTy
::
F64
=>
Ok
(
Scalar
::
Bits
{
bits
:
Double
::
from_bits
(
bits
)
.to_i128
(
width
)
.value
as
u128
,
defined
:
64
,
}),
}
},
// f64 -> f32
TyFloat
(
FloatTy
::
F32
)
if
fty
==
FloatTy
::
F64
=>
{
Ok
(
Scalar
::
Bytes
(
Single
::
to_bits
(
Double
::
from_bits
(
bits
)
.convert
(
&
mut
false
)
.value
)))
Ok
(
Scalar
::
Bits
{
bits
:
Single
::
to_bits
(
Double
::
from_bits
(
bits
)
.convert
(
&
mut
false
)
.value
),
defined
:
32
,
})
},
// f32 -> f64
TyFloat
(
FloatTy
::
F64
)
if
fty
==
FloatTy
::
F32
=>
{
Ok
(
Scalar
::
Bytes
(
Double
::
to_bits
(
Single
::
from_bits
(
bits
)
.convert
(
&
mut
false
)
.value
)))
Ok
(
Scalar
::
Bits
{
bits
:
Double
::
to_bits
(
Single
::
from_bits
(
bits
)
.convert
(
&
mut
false
)
.value
),
defined
:
64
,
})
},
// identity cast
TyFloat
(
_
)
=>
Ok
(
Scalar
::
Bytes
(
bits
)),
TyFloat
(
FloatTy
::
F64
)
=>
Ok
(
Scalar
::
Bits
{
bits
,
defined
:
64
,
}),
TyFloat
(
FloatTy
::
F32
)
=>
Ok
(
Scalar
::
Bits
{
bits
,
defined
:
32
,
}),
_
=>
err!
(
Unimplemented
(
format!
(
"float to {:?} cast"
,
dest_ty
))),
}
}
...
...
src/librustc_mir/interpret/const_eval.rs
浏览文件 @
64a75ecc
...
...
@@ -100,7 +100,7 @@ pub fn value_to_const_value<'tcx>(
)
->
&
'tcx
ty
::
Const
<
'tcx
>
{
let
layout
=
ecx
.tcx
.layout_of
(
ty
::
ParamEnv
::
reveal_all
()
.and
(
ty
))
.unwrap
();
match
(
val
,
&
layout
.abi
)
{
(
Value
::
Scalar
(
Scalar
::
Undef
),
_
)
if
layout
.is_zst
()
=>
{},
(
Value
::
Scalar
(
Scalar
::
Bits
{
defined
:
0
,
..
}
),
_
)
if
layout
.is_zst
()
=>
{},
(
Value
::
ByRef
(
..
),
_
)
|
(
Value
::
Scalar
(
_
),
&
layout
::
Abi
::
Scalar
(
_
))
|
(
Value
::
ScalarPair
(
..
),
&
layout
::
Abi
::
ScalarPair
(
..
))
=>
{},
...
...
@@ -319,20 +319,31 @@ fn call_intrinsic<'a>(
"min_align_of"
=>
{
let
elem_ty
=
substs
.type_at
(
0
);
let
elem_align
=
ecx
.layout_of
(
elem_ty
)
?
.align
.abi
();
let
align_val
=
Scalar
::
from_u128
(
elem_align
as
u128
);
let
align_val
=
Scalar
::
Bits
{
bits
:
elem_align
as
u128
,
defined
:
dest_layout
.size
.bits
()
as
u8
,
};
ecx
.write_primval
(
dest
,
align_val
,
dest_layout
.ty
)
?
;
}
"size_of"
=>
{
let
ty
=
substs
.type_at
(
0
);
let
size
=
ecx
.layout_of
(
ty
)
?
.size
.bytes
()
as
u128
;
ecx
.write_primval
(
dest
,
Scalar
::
from_u128
(
size
),
dest_layout
.ty
)
?
;
let
size_val
=
Scalar
::
Bits
{
bits
:
size
,
defined
:
dest_layout
.size
.bits
()
as
u8
,
};
ecx
.write_primval
(
dest
,
size_val
,
dest_layout
.ty
)
?
;
}
"type_id"
=>
{
let
ty
=
substs
.type_at
(
0
);
let
type_id
=
ecx
.tcx
.type_id_hash
(
ty
)
as
u128
;
ecx
.write_primval
(
dest
,
Scalar
::
from_u128
(
type_id
),
dest_layout
.ty
)
?
;
let
id_val
=
Scalar
::
Bits
{
bits
:
type_id
,
defined
:
dest_layout
.size
.bits
()
as
u8
,
};
ecx
.write_primval
(
dest
,
id_val
,
dest_layout
.ty
)
?
;
}
name
=>
return
Err
(
ConstEvalError
::
NeedsRfc
(
format!
(
"calling intrinsic `{}`"
,
name
))
.into
()),
...
...
@@ -354,7 +365,7 @@ fn try_ptr_op<'a>(
right
:
Scalar
,
_
right_ty
:
Ty
<
'tcx
>
,
)
->
EvalResult
<
'tcx
,
Option
<
(
Scalar
,
bool
)
>>
{
if
left
.is_b
ytes
()
&&
right
.is_byte
s
()
{
if
left
.is_b
its
()
&&
right
.is_bit
s
()
{
Ok
(
None
)
}
else
{
Err
(
...
...
src/librustc_mir/interpret/eval_context.rs
浏览文件 @
64a75ecc
...
...
@@ -232,7 +232,10 @@ pub fn str_to_value(&mut self, s: &str) -> EvalResult<'tcx, Value> {
let
ptr
=
self
.memory
.allocate_bytes
(
s
.as_bytes
());
Ok
(
Value
::
ScalarPair
(
Scalar
::
Ptr
(
ptr
),
Scalar
::
from_u128
(
s
.len
()
as
u128
),
Scalar
::
Bits
{
bits
:
s
.len
()
as
u128
,
defined
:
self
.tcx.data_layout.pointer_size
.bits
()
as
u8
,
},
))
}
...
...
@@ -408,7 +411,7 @@ pub fn push_stack_frame(
::
log_settings
::
settings
()
.indentation
+=
1
;
let
locals
=
if
mir
.local_decls
.len
()
>
1
{
let
mut
locals
=
IndexVec
::
from_elem
(
Some
(
Value
::
Scalar
(
Scalar
::
Undef
)),
&
mir
.local_decls
);
let
mut
locals
=
IndexVec
::
from_elem
(
Some
(
Value
::
Scalar
(
Scalar
::
undef
()
)),
&
mir
.local_decls
);
match
self
.tcx
.describe_def
(
instance
.def_id
())
{
// statics and constants don't have `Storage*` statements, no need to look for them
Some
(
Def
::
Static
(
..
))
|
Some
(
Def
::
Const
(
..
))
|
Some
(
Def
::
AssociatedConst
(
..
))
=>
{},
...
...
@@ -606,9 +609,13 @@ pub(super) fn eval_rvalue_into_place(
let
src
=
self
.eval_place
(
place
)
?
;
let
ty
=
self
.place_ty
(
place
);
let
(
_
,
len
)
=
src
.elem_ty_and_len
(
ty
,
self
.tcx.tcx
);
let
defined
=
self
.memory
.pointer_size
()
.bits
()
as
u8
;
self
.write_primval
(
dest
,
Scalar
::
from_u128
(
len
as
u128
),
Scalar
::
Bits
{
bits
:
len
as
u128
,
defined
,
},
dest_ty
,
)
?
;
}
...
...
@@ -621,7 +628,7 @@ pub(super) fn eval_rvalue_into_place(
let
val
=
match
extra
{
PlaceExtra
::
None
=>
ptr
.to_value
(),
PlaceExtra
::
Length
(
len
)
=>
ptr
.to_value_with_len
(
len
),
PlaceExtra
::
Length
(
len
)
=>
ptr
.to_value_with_len
(
len
,
self
.tcx.tcx
),
PlaceExtra
::
Vtable
(
vtable
)
=>
ptr
.to_value_with_vtable
(
vtable
),
PlaceExtra
::
DowncastVariant
(
..
)
=>
{
bug!
(
"attempted to take a reference to an enum downcast place"
)
...
...
@@ -644,9 +651,13 @@ pub(super) fn eval_rvalue_into_place(
let
layout
=
self
.layout_of
(
ty
)
?
;
assert
!
(
!
layout
.is_unsized
(),
"SizeOf nullary MIR operator called for unsized type"
);
let
defined
=
self
.memory
.pointer_size
()
.bits
()
as
u8
;
self
.write_primval
(
dest
,
Scalar
::
from_u128
(
layout
.size
.bytes
()
as
u128
),
Scalar
::
Bits
{
bits
:
layout
.size
.bytes
()
as
u128
,
defined
,
},
dest_ty
,
)
?
;
}
...
...
@@ -694,9 +705,16 @@ pub(super) fn eval_rvalue_into_place(
let
discr_val
=
def
.discriminant_for_variant
(
*
self
.tcx
,
index
)
.val
;
let
defined
=
dest_ty
.scalar_size
(
self
.tcx.tcx
)
.expect
(
"can only cast variants to ints"
)
.bits
()
as
u8
;
return
self
.write_primval
(
dest
,
Scalar
::
Bytes
(
discr_val
),
Scalar
::
Bits
{
bits
:
discr_val
,
defined
,
},
dest_ty
);
}
}
...
...
@@ -780,7 +798,11 @@ pub(super) fn eval_rvalue_into_place(
let
ty
=
self
.place_ty
(
place
);
let
place
=
self
.eval_place
(
place
)
?
;
let
discr_val
=
self
.read_discriminant_value
(
place
,
ty
)
?
;
self
.write_primval
(
dest
,
Scalar
::
Bytes
(
discr_val
),
dest_ty
)
?
;
let
defined
=
ty
.scalar_size
(
self
.tcx.tcx
)
.expect
(
"discriminant must be scalar"
)
.bits
()
as
u8
;
self
.write_primval
(
dest
,
Scalar
::
Bits
{
bits
:
discr_val
,
defined
,
},
dest_ty
)
?
;
}
}
...
...
@@ -910,7 +932,7 @@ pub fn read_discriminant_value(
// FIXME: should we catch invalid discriminants here?
layout
::
Variants
::
Tagged
{
..
}
=>
{
if
discr
.ty
.is_signed
()
{
let
i
=
raw_discr
.to_b
ytes
(
)
?
as
i128
;
let
i
=
raw_discr
.to_b
its
(
discr
.size
)
?
as
i128
;
// going from layout tag type to typeck discriminant type
// requires first sign extending with the layout discriminant
let
amt
=
128
-
discr
.size
.bits
();
...
...
@@ -925,7 +947,7 @@ pub fn read_discriminant_value(
let
truncatee
=
sexted
as
u128
;
(
truncatee
<<
amt
)
>>
amt
}
else
{
raw_discr
.to_b
ytes
(
)
?
raw_discr
.to_b
its
(
discr
.size
)
?
}
},
layout
::
Variants
::
NicheFilling
{
...
...
@@ -942,7 +964,10 @@ pub fn read_discriminant_value(
assert
!
(
variants_start
==
variants_end
);
dataful_variant
as
u128
},
Scalar
::
Bytes
(
raw_discr
)
=>
{
Scalar
::
Bits
{
bits
:
raw_discr
,
defined
}
=>
{
if
defined
<
discr
.size
.bits
()
as
u8
{
return
err!
(
ReadUndefBytes
);
}
let
discr
=
raw_discr
.wrapping_sub
(
niche_start
)
.wrapping_add
(
variants_start
);
if
variants_start
<=
discr
&&
discr
<=
variants_end
{
...
...
@@ -951,7 +976,6 @@ pub fn read_discriminant_value(
dataful_variant
as
u128
}
},
Scalar
::
Undef
=>
return
err!
(
ReadUndefBytes
),
}
}
};
...
...
@@ -990,7 +1014,10 @@ pub fn write_discriminant_value(
let
discr_val
=
(
discr_val
<<
amt
)
>>
amt
;
let
(
discr_dest
,
tag
)
=
self
.place_field
(
dest
,
mir
::
Field
::
new
(
0
),
layout
)
?
;
self
.write_primval
(
discr_dest
,
Scalar
::
Bytes
(
discr_val
),
tag
.ty
)
?
;
self
.write_primval
(
discr_dest
,
Scalar
::
Bits
{
bits
:
discr_val
,
defined
:
size
as
u8
,
},
tag
.ty
)
?
;
}
layout
::
Variants
::
NicheFilling
{
dataful_variant
,
...
...
@@ -1003,7 +1030,10 @@ pub fn write_discriminant_value(
self
.place_field
(
dest
,
mir
::
Field
::
new
(
0
),
layout
)
?
;
let
niche_value
=
((
variant_index
-
niche_variants
.start
())
as
u128
)
.wrapping_add
(
niche_start
);
self
.write_primval
(
niche_dest
,
Scalar
::
Bytes
(
niche_value
),
niche
.ty
)
?
;
self
.write_primval
(
niche_dest
,
Scalar
::
Bits
{
bits
:
niche_value
,
defined
:
niche
.size
.bits
()
as
u8
,
},
niche
.ty
)
?
;
}
}
}
...
...
@@ -1216,8 +1246,10 @@ pub fn write_value_to_ptr(
layout
::
Primitive
::
Int
(
_
,
signed
)
=>
signed
,
_
=>
false
,
},
_
if
primval
.is_undef
()
=>
false
,
_
=>
bug!
(
"write_value_to_ptr: invalid ByVal layout: {:#?}"
,
layout
)
_
=>
match
primval
{
Scalar
::
Bits
{
defined
:
0
,
..
}
=>
false
,
_
=>
bug!
(
"write_value_to_ptr: invalid ByVal layout: {:#?}"
,
layout
),
}
};
self
.memory
.write_primval
(
dest
,
dest_align
,
primval
,
layout
.size
,
signed
)
}
...
...
@@ -1308,10 +1340,10 @@ pub fn ty_to_primval_kind(&self, ty: Ty<'tcx>) -> EvalResult<'tcx, ScalarKind> {
fn
ensure_valid_value
(
&
self
,
val
:
Scalar
,
ty
:
Ty
<
'tcx
>
)
->
EvalResult
<
'tcx
>
{
match
ty
.sty
{
ty
::
TyBool
if
val
.to_bytes
()
?
>
1
=>
err!
(
InvalidBool
),
ty
::
TyBool
=>
val
.to_bool
()
.map
(|
_
|
()
),
ty
::
TyChar
if
::
std
::
char
::
from_u32
(
val
.to_b
ytes
(
)
?
as
u32
)
.is_none
()
=>
{
err!
(
InvalidChar
(
val
.to_b
ytes
(
)
?
as
u32
as
u128
))
ty
::
TyChar
if
::
std
::
char
::
from_u32
(
val
.to_b
its
(
Size
::
from_bytes
(
4
)
)
?
as
u32
)
.is_none
()
=>
{
err!
(
InvalidChar
(
val
.to_b
its
(
Size
::
from_bytes
(
4
)
)
?
as
u32
as
u128
))
}
_
=>
Ok
(()),
...
...
@@ -1347,8 +1379,8 @@ pub(crate) fn read_ptr(
let
len
=
self
.memory
.read_ptr_sized
(
extra
,
ptr_align
)
?
.to_b
ytes
(
)
?
;
Ok
(
p
.to_value_with_len
(
len
as
u64
))
.to_b
its
(
ptr_size
)
?
;
Ok
(
p
.to_value_with_len
(
len
as
u64
,
self
.tcx.tcx
))
},
_
=>
bug!
(
"unsized primval ptr read from {:?}"
,
pointee_ty
),
}
...
...
@@ -1363,15 +1395,10 @@ pub fn validate_ptr_target(
)
->
EvalResult
<
'tcx
>
{
match
ty
.sty
{
ty
::
TyBool
=>
{
let
val
=
self
.memory
.read_primval
(
ptr
,
ptr_align
,
Size
::
from_bytes
(
1
))
?
;
match
val
{
Scalar
::
Bytes
(
0
)
|
Scalar
::
Bytes
(
1
)
=>
(),
// TODO: This seems a little overeager, should reading at bool type already be insta-UB?
_
=>
return
err!
(
InvalidBool
),
}
self
.memory
.read_primval
(
ptr
,
ptr_align
,
Size
::
from_bytes
(
1
))
?
.to_bool
()
?
;
}
ty
::
TyChar
=>
{
let
c
=
self
.memory
.read_primval
(
ptr
,
ptr_align
,
Size
::
from_bytes
(
4
))
?
.to_b
ytes
(
)
?
as
u32
;
let
c
=
self
.memory
.read_primval
(
ptr
,
ptr_align
,
Size
::
from_bytes
(
4
))
?
.to_b
its
(
Size
::
from_bytes
(
4
)
)
?
as
u32
;
match
::
std
::
char
::
from_u32
(
c
)
{
Some
(
..
)
=>
(),
None
=>
return
err!
(
InvalidChar
(
c
as
u128
)),
...
...
@@ -1418,7 +1445,7 @@ pub fn try_read_value(&self, ptr: Scalar, ptr_align: Align, ty: Ty<'tcx>) -> Eva
self
.memory
.check_align
(
ptr
,
ptr_align
)
?
;
if
layout
.size
.bytes
()
==
0
{
return
Ok
(
Some
(
Value
::
Scalar
(
Scalar
::
Undef
)));
return
Ok
(
Some
(
Value
::
Scalar
(
Scalar
::
undef
()
)));
}
let
ptr
=
ptr
.to_ptr
()
?
;
...
...
@@ -1482,7 +1509,7 @@ fn unsize_into_ptr(
let
ptr
=
self
.into_ptr
(
src
)
?
;
// u64 cast is from usize to u64, which is always good
let
valty
=
ValTy
{
value
:
ptr
.to_value_with_len
(
length
.unwrap_usize
(
self
.tcx.tcx
)),
value
:
ptr
.to_value_with_len
(
length
.unwrap_usize
(
self
.tcx.tcx
)
,
self
.tcx.tcx
),
ty
:
dest_ty
,
};
self
.write_value
(
valty
,
dest
)
...
...
@@ -1796,7 +1823,7 @@ pub fn storage_live(&mut self, local: mir::Local) -> Option<Value> {
trace!
(
"{:?} is now live"
,
local
);
// StorageLive *always* kills the value that's currently stored
mem
::
replace
(
&
mut
self
.locals
[
local
],
Some
(
Value
::
Scalar
(
Scalar
::
Undef
)))
mem
::
replace
(
&
mut
self
.locals
[
local
],
Some
(
Value
::
Scalar
(
Scalar
::
undef
()
)))
}
/// Returns the old value of the local
...
...
src/librustc_mir/interpret/memory.rs
浏览文件 @
64a75ecc
...
...
@@ -232,15 +232,18 @@ pub fn check_align(&self, ptr: Scalar, required_align: Align) -> EvalResult<'tcx
let
alloc
=
self
.get
(
ptr
.alloc_id
)
?
;
(
ptr
.offset
.bytes
(),
alloc
.align
)
}
Scalar
::
Bytes
(
bytes
)
=>
{
let
v
=
((
bytes
as
u128
)
%
(
1
<<
self
.pointer_size
()
.bytes
()))
as
u64
;
Scalar
::
Bits
{
bits
,
defined
}
=>
{
if
defined
<=
self
.pointer_size
()
.bits
()
as
u8
{
return
err!
(
ReadUndefBytes
);
}
// FIXME: what on earth does this line do? docs or fix needed!
let
v
=
((
bits
as
u128
)
%
(
1
<<
self
.pointer_size
()
.bytes
()))
as
u64
;
if
v
==
0
{
return
err!
(
InvalidNullPointerUsage
);
}
// the base address if the "integer allocation" is 0 and hence always aligned
(
v
,
required_align
)
}
Scalar
::
Undef
=>
return
err!
(
ReadUndefBytes
),
};
// Check alignment
if
alloc_align
.abi
()
<
required_align
.abi
()
{
...
...
@@ -711,10 +714,10 @@ pub fn read_primval(&self, ptr: Pointer, ptr_align: Align, size: Size) -> EvalRe
// Undef check happens *after* we established that the alignment is correct.
// We must not return Ok() for unaligned pointers!
if
self
.check_defined
(
ptr
,
size
)
.is_err
()
{
return
Ok
(
Scalar
::
Undef
.into
());
return
Ok
(
Scalar
::
undef
()
.into
());
}
// Now we do the actual reading
let
b
yte
s
=
read_target_uint
(
endianness
,
bytes
)
.unwrap
();
let
b
it
s
=
read_target_uint
(
endianness
,
bytes
)
.unwrap
();
// See if we got a pointer
if
size
!=
self
.pointer_size
()
{
if
self
.relocations
(
ptr
,
size
)
?
.len
()
!=
0
{
...
...
@@ -723,12 +726,15 @@ pub fn read_primval(&self, ptr: Pointer, ptr_align: Align, size: Size) -> EvalRe
}
else
{
let
alloc
=
self
.get
(
ptr
.alloc_id
)
?
;
match
alloc
.relocations
.get
(
&
ptr
.offset
)
{
Some
(
&
alloc_id
)
=>
return
Ok
(
Pointer
::
new
(
alloc_id
,
Size
::
from_bytes
(
b
yte
s
as
u64
))
.into
()),
Some
(
&
alloc_id
)
=>
return
Ok
(
Pointer
::
new
(
alloc_id
,
Size
::
from_bytes
(
b
it
s
as
u64
))
.into
()),
None
=>
{},
}
}
// We don't. Just return the bytes.
Ok
(
Scalar
::
Bytes
(
bytes
))
// We don't. Just return the bits.
Ok
(
Scalar
::
Bits
{
bits
,
defined
:
size
.bits
()
as
u8
,
})
}
pub
fn
read_ptr_sized
(
&
self
,
ptr
:
Pointer
,
ptr_align
:
Align
)
->
EvalResult
<
'tcx
,
Scalar
>
{
...
...
@@ -744,9 +750,9 @@ pub fn write_primval(&mut self, ptr: Scalar, ptr_align: Align, val: Scalar, size
val
.offset
.bytes
()
as
u128
}
Scalar
::
B
ytes
(
bytes
)
=>
byte
s
,
Scalar
::
B
its
{
bits
,
defined
}
if
defined
>=
size
.bits
()
as
u8
&&
defined
!=
0
=>
bit
s
,
Scalar
::
Undef
=>
{
Scalar
::
Bits
{
..
}
=>
{
self
.check_align
(
ptr
.into
(),
ptr_align
)
?
;
self
.mark_definedness
(
ptr
,
size
,
false
)
?
;
return
Ok
(());
...
...
@@ -951,7 +957,7 @@ fn into_ptr_vtable_pair(
Value
::
ScalarPair
(
ptr
,
vtable
)
=>
Ok
((
ptr
.into
(),
vtable
.to_ptr
()
?
)),
Value
::
Scalar
(
Scalar
::
Undef
)
=>
err!
(
ReadUndefBytes
),
Value
::
Scalar
(
Scalar
::
Bits
{
defined
:
0
,
..
}
)
=>
err!
(
ReadUndefBytes
),
_
=>
bug!
(
"expected ptr and vtable, got {:?}"
,
value
),
}
}
...
...
@@ -967,15 +973,14 @@ fn into_slice(
let
len
=
mem
.read_ptr_sized
(
ref_ptr
.ptr_offset
(
mem
.pointer_size
(),
&
mem
.tcx.data_layout
)
?
.to_ptr
()
?
,
align
)
?
.to_b
ytes
(
)
?
as
u64
;
)
?
.to_b
its
(
mem
.pointer_size
()
)
?
as
u64
;
Ok
((
ptr
,
len
))
}
Value
::
ScalarPair
(
ptr
,
val
)
=>
{
let
len
=
val
.to_u128
()
?
;
assert_eq!
(
len
as
u64
as
u128
,
len
);
let
len
=
val
.to_bits
(
self
.memory
()
.pointer_size
())
?
;
Ok
((
ptr
.into
(),
len
as
u64
))
}
Value
::
Scalar
(
Scalar
::
Undef
)
=>
err!
(
ReadUndefBytes
),
Value
::
Scalar
(
Scalar
::
Bits
{
defined
:
0
,
..
}
)
=>
err!
(
ReadUndefBytes
),
Value
::
Scalar
(
_
)
=>
bug!
(
"expected ptr and length, got {:?}"
,
value
),
}
}
...
...
src/librustc_mir/interpret/operator.rs
浏览文件 @
64a75ecc
...
...
@@ -79,11 +79,12 @@ pub fn binary_op(
}
}
// II: From now on, everything must be bytes, no pointers
let
l
=
left
.to_bytes
()
?
;
let
r
=
right
.to_bytes
()
?
;
let
left_layout
=
self
.layout_of
(
left_ty
)
?
;
let
right_layout
=
self
.layout_of
(
right_ty
)
?
;
// II: From now on, everything must be bytes, no pointers
let
l
=
left
.to_bits
(
left_layout
.size
)
?
;
let
r
=
right
.to_bits
(
right_layout
.size
)
?
;
// These ops can have an RHS with a different numeric type.
if
right_kind
.is_int
()
&&
(
bin_op
==
Shl
||
bin_op
==
Shr
)
{
...
...
@@ -110,7 +111,10 @@ pub fn binary_op(
}
};
let
truncated
=
self
.truncate
(
result
,
left_ty
)
?
;
return
Ok
((
Scalar
::
Bytes
(
truncated
),
oflo
));
return
Ok
((
Scalar
::
Bits
{
bits
:
truncated
,
defined
:
size
as
u8
,
},
oflo
));
}
if
left_kind
!=
right_kind
{
...
...
@@ -156,7 +160,7 @@ pub fn binary_op(
Rem
|
Div
=>
{
// int_min / -1
if
r
==
-
1
&&
l
==
(
1
<<
(
size
-
1
))
{
return
Ok
((
Scalar
::
B
ytes
(
l
)
,
true
));
return
Ok
((
Scalar
::
B
its
{
bits
:
l
,
defined
:
size
as
u8
}
,
true
));
}
},
_
=>
{},
...
...
@@ -170,15 +174,22 @@ pub fn binary_op(
}
let
result
=
result
as
u128
;
let
truncated
=
self
.truncate
(
result
,
left_ty
)
?
;
return
Ok
((
Scalar
::
Bytes
(
truncated
),
oflo
));
return
Ok
((
Scalar
::
Bits
{
bits
:
truncated
,
defined
:
size
as
u8
,
},
oflo
));
}
}
if
let
ty
::
TyFloat
(
fty
)
=
left_ty
.sty
{
macro_rules!
float_math
{
(
$ty:path
)
=>
{{
(
$ty:path
,
$bitsize:expr
)
=>
{{
let
l
=
<
$ty
>
::
from_bits
(
l
);
let
r
=
<
$ty
>
::
from_bits
(
r
);
let
bitify
=
|
res
:
::
rustc_apfloat
::
StatusAnd
<
$ty
>
|
Scalar
::
Bits
{
bits
:
res
.value
.to_bits
(),
defined
:
$bitsize
,
};
let
val
=
match
bin_op
{
Eq
=>
Scalar
::
from_bool
(
l
==
r
),
Ne
=>
Scalar
::
from_bool
(
l
!=
r
),
...
...
@@ -186,22 +197,24 @@ pub fn binary_op(
Le
=>
Scalar
::
from_bool
(
l
<=
r
),
Gt
=>
Scalar
::
from_bool
(
l
>
r
),
Ge
=>
Scalar
::
from_bool
(
l
>=
r
),
Add
=>
Scalar
::
Bytes
((
l
+
r
)
.value
.to_bits
()
),
Sub
=>
Scalar
::
Bytes
((
l
-
r
)
.value
.to_bits
()
),
Mul
=>
Scalar
::
Bytes
((
l
*
r
)
.value
.to_bits
()
),
Div
=>
Scalar
::
Bytes
((
l
/
r
)
.value
.to_bits
()
),
Rem
=>
Scalar
::
Bytes
((
l
%
r
)
.value
.to_bits
()
),
Add
=>
bitify
(
l
+
r
),
Sub
=>
bitify
(
l
-
r
),
Mul
=>
bitify
(
l
*
r
),
Div
=>
bitify
(
l
/
r
),
Rem
=>
bitify
(
l
%
r
),
_
=>
bug!
(
"invalid float op: `{:?}`"
,
bin_op
),
};
return
Ok
((
val
,
false
));
}};
}
match
fty
{
FloatTy
::
F32
=>
float_math!
(
Single
),
FloatTy
::
F64
=>
float_math!
(
Double
),
FloatTy
::
F32
=>
float_math!
(
Single
,
32
),
FloatTy
::
F64
=>
float_math!
(
Double
,
64
),
}
}
let
bitsize
=
left_ty
.scalar_size
(
self
)
.expect
(
"operator type must be scalar"
)
.bits
()
as
u8
;
// only ints left
let
val
=
match
bin_op
{
Eq
=>
Scalar
::
from_bool
(
l
==
r
),
...
...
@@ -212,9 +225,9 @@ pub fn binary_op(
Gt
=>
Scalar
::
from_bool
(
l
>
r
),
Ge
=>
Scalar
::
from_bool
(
l
>=
r
),
BitOr
=>
Scalar
::
B
ytes
(
l
|
r
)
,
BitAnd
=>
Scalar
::
B
ytes
(
l
&
r
)
,
BitXor
=>
Scalar
::
B
ytes
(
l
^
r
)
,
BitOr
=>
Scalar
::
B
its
{
bits
:
l
|
r
,
defined
:
bitsize
}
,
BitAnd
=>
Scalar
::
B
its
{
bits
:
l
&
r
,
defined
:
bitsize
}
,
BitXor
=>
Scalar
::
B
its
{
bits
:
l
^
r
,
defined
:
bitsize
}
,
Add
|
Sub
|
Mul
|
Rem
|
Div
=>
{
let
op
:
fn
(
u128
,
u128
)
->
(
u128
,
bool
)
=
match
bin_op
{
...
...
@@ -229,7 +242,10 @@ pub fn binary_op(
};
let
(
result
,
oflo
)
=
op
(
l
,
r
);
let
truncated
=
self
.truncate
(
result
,
left_ty
)
?
;
return
Ok
((
Scalar
::
Bytes
(
truncated
),
oflo
||
truncated
!=
result
));
return
Ok
((
Scalar
::
Bits
{
bits
:
truncated
,
defined
:
bitsize
,
},
oflo
||
truncated
!=
result
));
}
_
=>
{
...
...
@@ -258,8 +274,9 @@ pub fn unary_op(
use
rustc_apfloat
::
ieee
::{
Single
,
Double
};
use
rustc_apfloat
::
Float
;
let
bytes
=
val
.to_bytes
()
?
;
let
size
=
self
.layout_of
(
ty
)
?
.size
.bits
();
let
size
=
self
.layout_of
(
ty
)
?
.size
;
let
bytes
=
val
.to_bits
(
size
)
?
;
let
size
=
size
.bits
();
let
result_bytes
=
match
(
un_op
,
&
ty
.sty
)
{
...
...
@@ -274,6 +291,9 @@ pub fn unary_op(
(
Neg
,
_
)
=>
(
-
(
bytes
as
i128
))
as
u128
,
};
Ok
(
Scalar
::
Bytes
(
self
.truncate
(
result_bytes
,
ty
)
?
))
Ok
(
Scalar
::
Bits
{
bits
:
self
.truncate
(
result_bytes
,
ty
)
?
,
defined
:
size
as
u8
,
})
}
}
src/librustc_mir/interpret/place.rs
浏览文件 @
64a75ecc
...
...
@@ -35,7 +35,7 @@ pub enum PlaceExtra {
impl
<
'tcx
>
Place
{
/// Produces a Place that will error if attempted to be read from
pub
fn
undef
()
->
Self
{
Self
::
from_primval_ptr
(
Scalar
::
Undef
.into
(),
Align
::
from_bytes
(
1
,
1
)
.unwrap
())
Self
::
from_primval_ptr
(
Scalar
::
undef
()
.into
(),
Align
::
from_bytes
(
1
,
1
)
.unwrap
())
}
pub
fn
from_primval_ptr
(
ptr
:
Scalar
,
align
:
Align
)
->
Self
{
...
...
@@ -128,7 +128,7 @@ pub fn read_field(
let
field_index
=
field
.index
();
let
field
=
base_layout
.field
(
self
,
field_index
)
?
;
if
field
.size
.bytes
()
==
0
{
return
Ok
(
Some
((
Value
::
Scalar
(
Scalar
::
Undef
),
field
.ty
)))
return
Ok
(
Some
((
Value
::
Scalar
(
Scalar
::
undef
()
),
field
.ty
)))
}
let
offset
=
base_layout
.fields
.offset
(
field_index
);
match
base
{
...
...
@@ -387,8 +387,10 @@ pub fn eval_place_projection(
Index
(
local
)
=>
{
let
value
=
self
.frame
()
.get_local
(
local
)
?
;
let
ty
=
self
.tcx.types.usize
;
let
n
=
self
.value_to_primval
(
ValTy
{
value
,
ty
})
?
.to_u64
()
?
;
self
.place_index
(
base
,
base_ty
,
n
)
let
n
=
self
.value_to_primval
(
ValTy
{
value
,
ty
})
?
.to_bits
(
self
.tcx.data_layout.pointer_size
)
?
;
self
.place_index
(
base
,
base_ty
,
n
as
u64
)
}
ConstantIndex
{
...
...
src/librustc_mir/interpret/terminator/drop.rs
浏览文件 @
64a75ecc
...
...
@@ -28,7 +28,7 @@ pub(crate) fn drop_place(
ptr
,
align
:
_
,
extra
:
PlaceExtra
::
Length
(
len
),
}
=>
ptr
.to_value_with_len
(
len
),
}
=>
ptr
.to_value_with_len
(
len
,
self
.tcx.tcx
),
Place
::
Ptr
{
ptr
,
align
:
_
,
...
...
src/librustc_mir/interpret/terminator/mod.rs
浏览文件 @
64a75ecc
...
...
@@ -44,7 +44,7 @@ pub(super) fn eval_terminator(
let
mut
target_block
=
targets
[
targets
.len
()
-
1
];
for
(
index
,
&
const_int
)
in
values
.iter
()
.enumerate
()
{
if
discr_prim
.to_b
ytes
(
)
?
==
const_int
{
if
discr_prim
.to_b
its
(
discr_val
.ty
.scalar_size
(
self
.tcx.tcx
)
.expect
(
"discr must be scalar"
)
)
?
==
const_int
{
target_block
=
targets
[
index
];
break
;
}
...
...
@@ -153,10 +153,10 @@ pub(super) fn eval_terminator(
BoundsCheck
{
ref
len
,
ref
index
}
=>
{
let
len
=
self
.eval_operand_to_primval
(
len
)
.expect
(
"can't eval len"
)
.to_
u64
()
?
;
.to_
bits
(
self
.memory
()
.pointer_size
())
?
as
u64
;
let
index
=
self
.eval_operand_to_primval
(
index
)
.expect
(
"can't eval index"
)
.to_
u64
()
?
;
.to_
bits
(
self
.memory
()
.pointer_size
())
?
as
u64
;
err!
(
BoundsCheck
{
len
,
index
})
}
Overflow
(
op
)
=>
Err
(
Overflow
(
op
)
.into
()),
...
...
@@ -359,7 +359,7 @@ fn eval_fn_call(
self
.write_value
(
valty
,
dest
)
?
;
}
}
Value
::
Scalar
(
Scalar
::
Undef
)
=>
{}
Value
::
Scalar
(
Scalar
::
Bits
{
defined
:
0
,
..
}
)
=>
{}
other
=>
{
trace!
(
"{:#?}, {:#?}"
,
other
,
layout
);
let
mut
layout
=
layout
;
...
...
src/librustc_mir/interpret/traits.rs
浏览文件 @
64a75ecc
...
...
@@ -38,9 +38,15 @@ pub fn get_vtable(
self
.memory
.write_ptr_sized_unsigned
(
vtable
,
ptr_align
,
drop
.into
())
?
;
let
size_ptr
=
vtable
.offset
(
ptr_size
,
&
self
)
?
;
self
.memory
.write_ptr_sized_unsigned
(
size_ptr
,
ptr_align
,
Scalar
::
Bytes
(
size
as
u128
))
?
;
self
.memory
.write_ptr_sized_unsigned
(
size_ptr
,
ptr_align
,
Scalar
::
Bits
{
bits
:
size
as
u128
,
defined
:
ptr_size
.bits
()
as
u8
,
})
?
;
let
align_ptr
=
vtable
.offset
(
ptr_size
*
2
,
&
self
)
?
;
self
.memory
.write_ptr_sized_unsigned
(
align_ptr
,
ptr_align
,
Scalar
::
Bytes
(
align
as
u128
))
?
;
self
.memory
.write_ptr_sized_unsigned
(
align_ptr
,
ptr_align
,
Scalar
::
Bits
{
bits
:
align
as
u128
,
defined
:
ptr_size
.bits
()
as
u8
,
})
?
;
for
(
i
,
method
)
in
methods
.iter
()
.enumerate
()
{
if
let
Some
((
def_id
,
substs
))
=
*
method
{
...
...
@@ -65,9 +71,10 @@ pub fn read_drop_type_from_vtable(
)
->
EvalResult
<
'tcx
,
Option
<
ty
::
Instance
<
'tcx
>>>
{
// we don't care about the pointee type, we just want a pointer
let
pointer_align
=
self
.tcx.data_layout.pointer_align
;
let
pointer_size
=
self
.tcx.data_layout.pointer_size
.bits
()
as
u8
;
match
self
.read_ptr
(
vtable
,
pointer_align
,
self
.tcx
.mk_nil_ptr
())
?
{
// some values don't need to call a drop impl, so the value is null
Value
::
Scalar
(
Scalar
::
B
ytes
(
0
))
=>
Ok
(
None
),
Value
::
Scalar
(
Scalar
::
B
its
{
bits
:
0
,
defined
}
)
if
defined
==
pointer_size
=>
Ok
(
None
),
Value
::
Scalar
(
Scalar
::
Ptr
(
drop_fn
))
=>
self
.memory
.get_fn
(
drop_fn
)
.map
(
Some
),
_
=>
err!
(
ReadBytesAsPointer
),
}
...
...
@@ -79,11 +86,11 @@ pub fn read_size_and_align_from_vtable(
)
->
EvalResult
<
'tcx
,
(
Size
,
Align
)
>
{
let
pointer_size
=
self
.memory
.pointer_size
();
let
pointer_align
=
self
.tcx.data_layout.pointer_align
;
let
size
=
self
.memory
.read_ptr_sized
(
vtable
.offset
(
pointer_size
,
self
)
?
,
pointer_align
)
?
.to_b
ytes
(
)
?
as
u64
;
let
size
=
self
.memory
.read_ptr_sized
(
vtable
.offset
(
pointer_size
,
self
)
?
,
pointer_align
)
?
.to_b
its
(
pointer_size
)
?
as
u64
;
let
align
=
self
.memory
.read_ptr_sized
(
vtable
.offset
(
pointer_size
*
2
,
self
)
?
,
pointer_align
)
?
.to_b
ytes
(
)
?
as
u64
;
)
?
.to_b
its
(
pointer_size
)
?
as
u64
;
Ok
((
Size
::
from_bytes
(
size
),
Align
::
from_bytes
(
align
,
align
)
.unwrap
()))
}
}
src/librustc_mir/transform/const_prop.rs
浏览文件 @
64a75ecc
...
...
@@ -283,7 +283,10 @@ fn const_prop(
Rvalue
::
NullaryOp
(
NullOp
::
SizeOf
,
ty
)
=>
{
let
param_env
=
self
.tcx
.param_env
(
self
.source.def_id
);
type_size_of
(
self
.tcx
,
param_env
,
ty
)
.map
(|
n
|
(
Value
::
Scalar
(
Scalar
::
Bytes
(
n
as
u128
)),
Value
::
Scalar
(
Scalar
::
Bits
{
bits
:
n
as
u128
,
defined
:
self
.tcx.data_layout.pointer_size
.bits
()
as
u8
,
}),
self
.tcx.types.usize
,
span
,
))
...
...
@@ -326,10 +329,10 @@ fn const_prop(
this
.ecx
.value_to_primval
(
ValTy
{
value
:
right
.0
,
ty
:
right
.1
})
})
?
;
if
op
==
BinOp
::
Shr
||
op
==
BinOp
::
Shl
{
let
param_env
=
self
.tcx
.param_env
(
self
.source.def_id
);
let
left_ty
=
left
.ty
(
self
.mir
,
self
.tcx
);
let
bits
=
self
.tcx
.layout_of
(
param_env
.and
(
left_ty
))
.unwrap
()
.size
.bits
();
if
r
.to_bytes
()
.ok
()
.map_or
(
false
,
|
b
|
b
>=
bits
as
u128
)
{
let
left_bits
=
left_ty
.scalar_size
(
self
.tcx
)
.unwrap
()
.bits
();
let
right_size
=
right
.1
.scalar_size
(
self
.tcx
)
.unwrap
();
if
r
.to_bits
(
right_size
)
.ok
()
.map_or
(
false
,
|
b
|
b
>=
left_bits
as
u128
)
{
let
scope_info
=
match
self
.mir.visibility_scope_info
{
ClearCrossCrate
::
Set
(
ref
data
)
=>
data
,
ClearCrossCrate
::
Clear
=>
return
None
,
...
...
@@ -520,14 +523,14 @@ fn visit_terminator_kind(
BoundsCheck
{
ref
len
,
ref
index
}
=>
{
let
len
=
self
.eval_operand
(
len
)
.expect
(
"len must be const"
);
let
len
=
match
len
.0
{
Value
::
Scalar
(
Scalar
::
B
ytes
(
n
))
=>
n
,
Value
::
Scalar
(
Scalar
::
B
its
{
bits
,
..
})
=>
bits
,
_
=>
bug!
(
"const len not primitive: {:?}"
,
len
),
};
let
index
=
self
.eval_operand
(
index
)
.expect
(
"index must be const"
);
let
index
=
match
index
.0
{
Value
::
Scalar
(
Scalar
::
B
ytes
(
n
))
=>
n
,
Value
::
Scalar
(
Scalar
::
B
its
{
bits
,
..
})
=>
bits
,
_
=>
bug!
(
"const index not primitive: {:?}"
,
index
),
};
format!
(
...
...
src/librustc_mir/transform/simplify_branches.rs
浏览文件 @
64a75ecc
...
...
@@ -39,7 +39,7 @@ fn run_pass<'a, 'tcx>(&self,
TerminatorKind
::
SwitchInt
{
discr
:
Operand
::
Constant
(
box
Constant
{
literal
:
Literal
::
Value
{
ref
value
},
..
}),
switch_ty
,
ref
values
,
ref
targets
,
..
}
=>
{
if
let
Some
(
constint
)
=
value
.assert_bits
(
switch_ty
)
{
if
let
Some
(
constint
)
=
value
.assert_bits
(
tcx
,
switch_ty
)
{
let
(
otherwise
,
targets
)
=
targets
.split_last
()
.unwrap
();
let
mut
ret
=
TerminatorKind
::
Goto
{
target
:
*
otherwise
};
for
(
&
v
,
t
)
in
values
.iter
()
.zip
(
targets
.iter
())
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录