Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
f036fe0d
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,发现更多精彩内容 >>
提交
f036fe0d
编写于
8月 25, 2017
作者:
R
Ralf Jung
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
refactor memory read API: provide only size-based, no type-based methods
上级
85397286
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
164 addition
and
184 deletion
+164
-184
src/librustc_mir/interpret/cast.rs
src/librustc_mir/interpret/cast.rs
+1
-0
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/eval_context.rs
+108
-35
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/memory.rs
+29
-32
src/librustc_mir/interpret/terminator/mod.rs
src/librustc_mir/interpret/terminator/mod.rs
+7
-102
src/librustc_mir/interpret/traits.rs
src/librustc_mir/interpret/traits.rs
+4
-4
src/librustc_mir/interpret/value.rs
src/librustc_mir/interpret/value.rs
+11
-11
tests/run-pass-fullmir/integer-ops.rs
tests/run-pass-fullmir/integer-ops.rs
+4
-0
未找到文件。
src/librustc_mir/interpret/cast.rs
浏览文件 @
f036fe0d
...
...
@@ -10,6 +10,7 @@ pub(super) fn cast_primval(
src_ty
:
Ty
<
'tcx
>
,
dest_ty
:
Ty
<
'tcx
>
,
)
->
EvalResult
<
'tcx
,
PrimVal
>
{
trace!
(
"Casting {:?}: {:?} to {:?}"
,
val
,
src_ty
,
dest_ty
);
let
src_kind
=
self
.ty_to_primval_kind
(
src_ty
)
?
;
match
val
{
...
...
src/librustc_mir/interpret/eval_context.rs
浏览文件 @
f036fe0d
...
...
@@ -998,16 +998,17 @@ pub(super) fn eval_rvalue_into_lvalue(
let
ptr
=
self
.force_allocation
(
lval
)
?
.to_ptr
()
?
;
let
discr_val
=
self
.read_discriminant_value
(
ptr
,
ty
)
?
;
if
let
ty
::
TyAdt
(
adt_def
,
_
)
=
ty
.sty
{
trace!
(
"Read discriminant {}, valid discriminants {:?}"
,
discr_val
,
adt_def
.discriminants
(
self
.tcx
)
.collect
::
<
Vec
<
_
>>
());
if
adt_def
.discriminants
(
self
.tcx
)
.all
(|
v
|
{
discr_val
!=
v
.to_u128_unchecked
()
})
{
return
err!
(
InvalidDiscriminant
);
}
self
.write_primval
(
dest
,
PrimVal
::
Bytes
(
discr_val
),
dest_ty
)
?
;
}
else
{
bug!
(
"rustc only generates Rvalue::Discriminant for enums"
);
}
self
.write_primval
(
dest
,
PrimVal
::
Bytes
(
discr_val
),
dest_ty
)
?
;
}
}
...
...
@@ -1295,6 +1296,96 @@ pub fn eval_operand(&mut self, op: &mir::Operand<'tcx>) -> EvalResult<'tcx, ValT
}
}
pub
fn
read_discriminant_value
(
&
self
,
adt_ptr
:
MemoryPointer
,
adt_ty
:
Ty
<
'tcx
>
,
)
->
EvalResult
<
'tcx
,
u128
>
{
use
rustc
::
ty
::
layout
::
Layout
::
*
;
let
adt_layout
=
self
.type_layout
(
adt_ty
)
?
;
//trace!("read_discriminant_value {:#?}", adt_layout);
let
discr_val
=
match
*
adt_layout
{
General
{
discr
,
..
}
=>
{
let
discr_size
=
discr
.size
()
.bytes
();
self
.memory
.read_primval
(
adt_ptr
,
discr_size
,
false
)
?
.to_bytes
()
?
}
CEnum
{
discr
,
signed
,
..
}
=>
{
let
discr_size
=
discr
.size
()
.bytes
();
self
.memory
.read_primval
(
adt_ptr
,
discr_size
,
signed
)
?
.to_bytes
()
?
}
RawNullablePointer
{
nndiscr
,
value
}
=>
{
let
discr_size
=
value
.size
(
&
self
.tcx.data_layout
)
.bytes
();
trace!
(
"rawnullablepointer with size {}"
,
discr_size
);
self
.read_nonnull_discriminant_value
(
adt_ptr
,
nndiscr
as
u128
,
discr_size
,
)
?
}
StructWrappedNullablePointer
{
nndiscr
,
ref
discrfield_source
,
..
}
=>
{
let
(
offset
,
TyAndPacked
{
ty
,
packed
})
=
self
.nonnull_offset_and_ty
(
adt_ty
,
nndiscr
,
discrfield_source
,
)
?
;
let
nonnull
=
adt_ptr
.offset
(
offset
.bytes
(),
&*
self
)
?
;
trace!
(
"struct wrapped nullable pointer type: {}"
,
ty
);
// only the pointer part of a fat pointer is used for this space optimization
let
discr_size
=
self
.type_size
(
ty
)
?
.expect
(
"bad StructWrappedNullablePointer discrfield"
,
);
self
.read_maybe_aligned
(
!
packed
,
|
ectx
|
{
ectx
.read_nonnull_discriminant_value
(
nonnull
,
nndiscr
as
u128
,
discr_size
)
})
?
}
// The discriminant_value intrinsic returns 0 for non-sum types.
Array
{
..
}
|
FatPointer
{
..
}
|
Scalar
{
..
}
|
Univariant
{
..
}
|
Vector
{
..
}
|
UntaggedUnion
{
..
}
=>
0
,
};
Ok
(
discr_val
)
}
fn
read_nonnull_discriminant_value
(
&
self
,
ptr
:
MemoryPointer
,
nndiscr
:
u128
,
discr_size
:
u64
,
)
->
EvalResult
<
'tcx
,
u128
>
{
trace!
(
"read_nonnull_discriminant_value: {:?}, {}, {}"
,
ptr
,
nndiscr
,
discr_size
);
// We are only interested in 0 vs. non-0, the sign does not matter for this
let
null
=
match
self
.memory
.read_primval
(
ptr
,
discr_size
,
false
)
?
{
PrimVal
::
Bytes
(
0
)
=>
true
,
PrimVal
::
Bytes
(
_
)
|
PrimVal
::
Ptr
(
..
)
=>
false
,
PrimVal
::
Undef
=>
return
err!
(
ReadUndefBytes
),
};
assert
!
(
nndiscr
==
0
||
nndiscr
==
1
);
Ok
(
if
!
null
{
nndiscr
}
else
{
1
-
nndiscr
})
}
pub
fn
read_global_as_value
(
&
self
,
gid
:
GlobalId
)
->
Value
{
Value
::
ByRef
(
*
self
.globals
.get
(
&
gid
)
.expect
(
"global not cached"
))
}
...
...
@@ -1676,18 +1767,19 @@ pub(crate) fn read_ptr(
ptr
:
MemoryPointer
,
pointee_ty
:
Ty
<
'tcx
>
,
)
->
EvalResult
<
'tcx
,
Value
>
{
let
p
=
self
.memory
.read_ptr
(
ptr
)
?
;
let
ptr_size
=
self
.memory
.pointer_size
();
let
p
:
Pointer
=
self
.memory
.read_ptr_sized_unsigned
(
ptr
)
?
.into
();
if
self
.type_is_sized
(
pointee_ty
)
{
Ok
(
p
.to_value
())
}
else
{
trace!
(
"reading fat pointer extra of type {}"
,
pointee_ty
);
let
extra
=
ptr
.offset
(
self
.memory
.pointer_size
()
,
self
)
?
;
let
extra
=
ptr
.offset
(
ptr_size
,
self
)
?
;
match
self
.tcx
.struct_tail
(
pointee_ty
)
.sty
{
ty
::
TyDynamic
(
..
)
=>
Ok
(
p
.to_value_with_vtable
(
self
.memory
.read_ptr
(
extra
)
?
.to_ptr
()
?
,
self
.memory
.read_ptr
_sized_unsigned
(
extra
)
?
.to_ptr
()
?
,
)),
ty
::
TySlice
(
..
)
|
ty
::
TyStr
=>
Ok
(
p
.to_value_with_len
(
self
.memory
.read_
usize
(
extra
)
?
),
p
.to_value_with_len
(
self
.memory
.read_
ptr_sized_unsigned
(
extra
)
?
.to_bytes
()
?
as
u64
),
),
_
=>
bug!
(
"unsized primval ptr read from {:?}"
,
pointee_ty
),
}
...
...
@@ -1697,10 +1789,11 @@ pub(crate) fn read_ptr(
fn
try_read_value
(
&
self
,
ptr
:
Pointer
,
ty
:
Ty
<
'tcx
>
)
->
EvalResult
<
'tcx
,
Option
<
Value
>>
{
use
syntax
::
ast
::
FloatTy
;
let
ptr
=
ptr
.to_ptr
()
?
;
let
val
=
match
ty
.sty
{
ty
::
TyBool
=>
PrimVal
::
from_bool
(
self
.memory
.read_bool
(
ptr
.to_ptr
()
?
)
?
),
ty
::
TyBool
=>
PrimVal
::
from_bool
(
self
.memory
.read_bool
(
ptr
)
?
),
ty
::
TyChar
=>
{
let
c
=
self
.memory
.read_
uint
(
ptr
.to_ptr
()
?
,
4
)
?
as
u32
;
let
c
=
self
.memory
.read_
primval
(
ptr
,
4
,
false
)
?
.to_bytes
(
)
?
as
u32
;
match
::
std
::
char
::
from_u32
(
c
)
{
Some
(
ch
)
=>
PrimVal
::
from_char
(
ch
),
None
=>
return
err!
(
InvalidChar
(
c
as
u128
)),
...
...
@@ -1717,15 +1810,7 @@ fn try_read_value(&self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<
I128
=>
16
,
Is
=>
self
.memory
.pointer_size
(),
};
// if we transmute a ptr to an isize, reading it back into a primval shouldn't panic
// Due to read_ptr ignoring the sign, we need to jump around some hoops
match
self
.memory
.read_int
(
ptr
.to_ptr
()
?
,
size
)
{
Err
(
EvalError
{
kind
:
EvalErrorKind
::
ReadPointerAsBytes
,
..
})
if
size
==
self
.memory
.pointer_size
()
=>
// Reading as an int failed because we are seeing ptr bytes *and* we are actually reading at ptr size.
// Let's try again, reading a ptr this time.
self
.memory
.read_ptr
(
ptr
.to_ptr
()
?
)
?
.into_inner_primval
(),
other
=>
PrimVal
::
from_i128
(
other
?
),
}
self
.memory
.read_primval
(
ptr
,
size
,
true
)
?
}
ty
::
TyUint
(
uint_ty
)
=>
{
...
...
@@ -1738,36 +1823,24 @@ fn try_read_value(&self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<
U128
=>
16
,
Us
=>
self
.memory
.pointer_size
(),
};
// if we transmute a ptr to an usize, reading it back into a primval shouldn't panic
// for consistency's sake, we use the same code as above
match
self
.memory
.read_uint
(
ptr
.to_ptr
()
?
,
size
)
{
Err
(
EvalError
{
kind
:
EvalErrorKind
::
ReadPointerAsBytes
,
..
})
if
size
==
self
.memory
.pointer_size
()
=>
{
self
.memory
.read_ptr
(
ptr
.to_ptr
()
?
)
?
.into_inner_primval
()
}
other
=>
PrimVal
::
from_u128
(
other
?
),
}
self
.memory
.read_primval
(
ptr
,
size
,
false
)
?
}
ty
::
TyFloat
(
FloatTy
::
F32
)
=>
PrimVal
::
from_f32
(
self
.memory
.read_f32
(
ptr
.to_ptr
()
?
)
?
),
ty
::
TyFloat
(
FloatTy
::
F64
)
=>
PrimVal
::
from_f64
(
self
.memory
.read_f64
(
ptr
.to_ptr
()
?
)
?
),
ty
::
TyFloat
(
FloatTy
::
F32
)
=>
PrimVal
::
from_f32
(
self
.memory
.read_f32
(
ptr
)
?
),
ty
::
TyFloat
(
FloatTy
::
F64
)
=>
PrimVal
::
from_f64
(
self
.memory
.read_f64
(
ptr
)
?
),
ty
::
TyFnPtr
(
_
)
=>
self
.memory
.read_ptr
(
ptr
.to_ptr
()
?
)
?
.into_inner_primval
()
,
ty
::
TyFnPtr
(
_
)
=>
self
.memory
.read_ptr
_sized_unsigned
(
ptr
)
?
,
ty
::
TyRef
(
_
,
ref
tam
)
|
ty
::
TyRawPtr
(
ref
tam
)
=>
return
self
.read_ptr
(
ptr
.to_ptr
()
?
,
tam
.ty
)
.map
(
Some
),
ty
::
TyRawPtr
(
ref
tam
)
=>
return
self
.read_ptr
(
ptr
,
tam
.ty
)
.map
(
Some
),
ty
::
TyAdt
(
def
,
_
)
=>
{
if
def
.is_box
()
{
return
self
.read_ptr
(
ptr
.to_ptr
()
?
,
ty
.boxed_ty
())
.map
(
Some
);
return
self
.read_ptr
(
ptr
,
ty
.boxed_ty
())
.map
(
Some
);
}
use
rustc
::
ty
::
layout
::
Layout
::
*
;
if
let
CEnum
{
discr
,
signed
,
..
}
=
*
self
.type_layout
(
ty
)
?
{
let
size
=
discr
.size
()
.bytes
();
if
signed
{
PrimVal
::
from_i128
(
self
.memory
.read_int
(
ptr
.to_ptr
()
?
,
size
)
?
)
}
else
{
PrimVal
::
from_u128
(
self
.memory
.read_uint
(
ptr
.to_ptr
()
?
,
size
)
?
)
}
self
.memory
.read_primval
(
ptr
,
size
,
signed
)
?
}
else
{
return
Ok
(
None
);
}
...
...
src/librustc_mir/interpret/memory.rs
浏览文件 @
f036fe0d
...
...
@@ -1171,24 +1171,39 @@ pub fn write_repeat(&mut self, ptr: Pointer, val: u8, count: u64) -> EvalResult<
Ok
(())
}
pub
fn
read_ptr
(
&
self
,
ptr
:
MemoryPointer
)
->
EvalResult
<
'tcx
,
Pointer
>
{
let
size
=
self
.pointer_size
();
pub
fn
read_primval
(
&
self
,
ptr
:
MemoryPointer
,
size
:
u64
,
signed
:
bool
)
->
EvalResult
<
'tcx
,
PrimVal
>
{
self
.check_relocation_edges
(
ptr
,
size
)
?
;
// Make sure we don't read part of a pointer as a pointer
let
endianess
=
self
.endianess
();
let
bytes
=
self
.get_bytes_unchecked
(
ptr
,
size
,
s
ize
)
?
;
let
bytes
=
self
.get_bytes_unchecked
(
ptr
,
size
,
s
elf
.int_align
(
size
)
?
)
?
;
// 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
(
PrimVal
::
Undef
.into
());
}
let
offset
=
read_target_uint
(
endianess
,
bytes
)
.unwrap
();
assert_eq!
(
offset
as
u64
as
u128
,
offset
);
let
offset
=
offset
as
u64
;
let
alloc
=
self
.get
(
ptr
.alloc_id
)
?
;
match
alloc
.relocations
.get
(
&
ptr
.offset
)
{
Some
(
&
alloc_id
)
=>
Ok
(
PrimVal
::
Ptr
(
MemoryPointer
::
new
(
alloc_id
,
offset
))
.into
()),
None
=>
Ok
(
PrimVal
::
Bytes
(
offset
as
u128
)
.into
()),
// Now we do the actual reading
let
bytes
=
if
signed
{
read_target_int
(
endianess
,
bytes
)
.unwrap
()
as
u128
}
else
{
read_target_uint
(
endianess
,
bytes
)
.unwrap
()
};
// See if we got a pointer
if
size
!=
self
.pointer_size
()
{
if
self
.relocations
(
ptr
,
size
)
?
.count
()
!=
0
{
return
err!
(
ReadPointerAsBytes
);
}
}
else
{
let
alloc
=
self
.get
(
ptr
.alloc_id
)
?
;
match
alloc
.relocations
.get
(
&
ptr
.offset
)
{
Some
(
&
alloc_id
)
=>
return
Ok
(
PrimVal
::
Ptr
(
MemoryPointer
::
new
(
alloc_id
,
bytes
as
u64
))),
None
=>
{},
}
}
// We don't. Just return the bytes.
Ok
(
PrimVal
::
Bytes
(
bytes
))
}
pub
fn
read_ptr_sized_unsigned
(
&
self
,
ptr
:
MemoryPointer
)
->
EvalResult
<
'tcx
,
PrimVal
>
{
self
.read_primval
(
ptr
,
self
.pointer_size
(),
false
)
}
pub
fn
write_ptr
(
&
mut
self
,
dest
:
MemoryPointer
,
ptr
:
MemoryPointer
)
->
EvalResult
<
'tcx
>
{
...
...
@@ -1242,6 +1257,8 @@ pub fn write_bool(&mut self, ptr: MemoryPointer, b: bool) -> EvalResult<'tcx> {
}
fn
int_align
(
&
self
,
size
:
u64
)
->
EvalResult
<
'tcx
,
u64
>
{
// We assume pointer-sized integers have the same alignment as pointers.
// We also assume singed and unsigned integers of the same size have the same alignment.
match
size
{
1
=>
Ok
(
self
.layout.i8_align
.abi
()),
2
=>
Ok
(
self
.layout.i16_align
.abi
()),
...
...
@@ -1252,13 +1269,6 @@ fn int_align(&self, size: u64) -> EvalResult<'tcx, u64> {
}
}
pub
fn
read_int
(
&
self
,
ptr
:
MemoryPointer
,
size
:
u64
)
->
EvalResult
<
'tcx
,
i128
>
{
let
align
=
self
.int_align
(
size
)
?
;
self
.get_bytes
(
ptr
,
size
,
align
)
.map
(|
b
|
{
read_target_int
(
self
.endianess
(),
b
)
.unwrap
()
})
}
pub
fn
write_int
(
&
mut
self
,
ptr
:
MemoryPointer
,
n
:
i128
,
size
:
u64
)
->
EvalResult
<
'tcx
>
{
let
align
=
self
.int_align
(
size
)
?
;
let
endianess
=
self
.endianess
();
...
...
@@ -1267,13 +1277,6 @@ pub fn write_int(&mut self, ptr: MemoryPointer, n: i128, size: u64) -> EvalResul
Ok
(())
}
pub
fn
read_uint
(
&
self
,
ptr
:
MemoryPointer
,
size
:
u64
)
->
EvalResult
<
'tcx
,
u128
>
{
let
align
=
self
.int_align
(
size
)
?
;
self
.get_bytes
(
ptr
,
size
,
align
)
.map
(|
b
|
{
read_target_uint
(
self
.endianess
(),
b
)
.unwrap
()
})
}
pub
fn
write_uint
(
&
mut
self
,
ptr
:
MemoryPointer
,
n
:
u128
,
size
:
u64
)
->
EvalResult
<
'tcx
>
{
let
align
=
self
.int_align
(
size
)
?
;
let
endianess
=
self
.endianess
();
...
...
@@ -1282,19 +1285,11 @@ pub fn write_uint(&mut self, ptr: MemoryPointer, n: u128, size: u64) -> EvalResu
Ok
(())
}
pub
fn
read_isize
(
&
self
,
ptr
:
MemoryPointer
)
->
EvalResult
<
'tcx
,
i64
>
{
self
.read_int
(
ptr
,
self
.pointer_size
())
.map
(|
i
|
i
as
i64
)
}
pub
fn
write_isize
(
&
mut
self
,
ptr
:
MemoryPointer
,
n
:
i64
)
->
EvalResult
<
'tcx
>
{
let
size
=
self
.pointer_size
();
self
.write_int
(
ptr
,
n
as
i128
,
size
)
}
pub
fn
read_usize
(
&
self
,
ptr
:
MemoryPointer
)
->
EvalResult
<
'tcx
,
u64
>
{
self
.read_uint
(
ptr
,
self
.pointer_size
())
.map
(|
i
|
i
as
u64
)
}
pub
fn
write_usize
(
&
mut
self
,
ptr
:
MemoryPointer
,
n
:
u64
)
->
EvalResult
<
'tcx
>
{
let
size
=
self
.pointer_size
();
self
.write_uint
(
ptr
,
n
as
u128
,
size
)
...
...
@@ -1494,6 +1489,7 @@ fn read_target_uint(endianess: layout::Endian, mut source: &[u8]) -> Result<u128
layout
::
Endian
::
Big
=>
source
.read_uint128
::
<
BigEndian
>
(
source
.len
()),
}
}
fn
read_target_int
(
endianess
:
layout
::
Endian
,
mut
source
:
&
[
u8
])
->
Result
<
i128
,
io
::
Error
>
{
match
endianess
{
layout
::
Endian
::
Little
=>
source
.read_int128
::
<
LittleEndian
>
(
source
.len
()),
...
...
@@ -1501,6 +1497,7 @@ fn read_target_int(endianess: layout::Endian, mut source: &[u8]) -> Result<i128,
}
}
////////////////////////////////////////////////////////////////////////////////
// Methods to access floats in the target endianess
////////////////////////////////////////////////////////////////////////////////
...
...
src/librustc_mir/interpret/terminator/mod.rs
浏览文件 @
f036fe0d
use
rustc
::
mir
;
use
rustc
::
ty
::{
self
,
TypeVariants
,
Ty
};
use
rustc
::
ty
::{
self
,
TypeVariants
};
use
rustc
::
ty
::
layout
::
Layout
;
use
syntax
::
codemap
::
Span
;
use
syntax
::
abi
::
Abi
;
use
super
::{
EvalError
,
EvalResult
,
EvalErrorKind
,
EvalContext
,
eval_context
,
TyAndPacked
,
PtrAndAlign
,
Lvalue
,
MemoryPointer
,
PrimVal
,
Value
,
Machine
,
HasMemory
,
ValTy
};
use
super
::
eval_context
::
IntegerExt
;
use
super
::{
EvalResult
,
EvalContext
,
eval_context
,
PtrAndAlign
,
Lvalue
,
PrimVal
,
Value
,
Machine
,
ValTy
};
use
rustc_data_structures
::
indexed_vec
::
Idx
;
...
...
@@ -395,10 +394,10 @@ fn eval_fn_call(
ty
::
InstanceDef
::
Virtual
(
_
,
idx
)
=>
{
let
ptr_size
=
self
.memory
.pointer_size
();
let
(
ptr
,
vtable
)
=
args
[
0
]
.into_ptr_vtable_pair
(
&
self
.memory
)
?
;
let
fn_ptr
=
self
.memory
.read_ptr
(
vtable
.offset
(
ptr_size
*
(
idx
as
u64
+
3
),
&
self
)
?
,
)
?
;
let
instance
=
self
.memory
.get_fn
(
fn_ptr
.to_ptr
()
?
)
?
;
let
fn_ptr
=
self
.memory
.read_ptr
_sized_unsigned
(
vtable
.offset
(
ptr_size
*
(
idx
as
u64
+
3
),
&
self
)
?
)
?
.to_ptr
()
?
;
let
instance
=
self
.memory
.get_fn
(
fn_ptr
)
?
;
let
mut
args
=
args
.to_vec
();
let
ty
=
self
.get_field_ty
(
args
[
0
]
.ty
,
0
)
?
.ty
;
// TODO: packed flag is ignored
args
[
0
]
.ty
=
ty
;
...
...
@@ -408,98 +407,4 @@ fn eval_fn_call(
}
}
}
pub
fn
read_discriminant_value
(
&
self
,
adt_ptr
:
MemoryPointer
,
adt_ty
:
Ty
<
'tcx
>
,
)
->
EvalResult
<
'tcx
,
u128
>
{
use
rustc
::
ty
::
layout
::
Layout
::
*
;
let
adt_layout
=
self
.type_layout
(
adt_ty
)
?
;
//trace!("read_discriminant_value {:#?}", adt_layout);
let
discr_val
=
match
*
adt_layout
{
General
{
discr
,
..
}
|
CEnum
{
discr
,
signed
:
false
,
..
}
=>
{
let
discr_size
=
discr
.size
()
.bytes
();
self
.memory
.read_uint
(
adt_ptr
,
discr_size
)
?
}
CEnum
{
discr
,
signed
:
true
,
..
}
=>
{
let
discr_size
=
discr
.size
()
.bytes
();
self
.memory
.read_int
(
adt_ptr
,
discr_size
)
?
as
u128
}
RawNullablePointer
{
nndiscr
,
value
}
=>
{
let
discr_size
=
value
.size
(
&
self
.tcx.data_layout
)
.bytes
();
trace!
(
"rawnullablepointer with size {}"
,
discr_size
);
self
.read_nonnull_discriminant_value
(
adt_ptr
,
nndiscr
as
u128
,
discr_size
,
)
?
}
StructWrappedNullablePointer
{
nndiscr
,
ref
discrfield_source
,
..
}
=>
{
let
(
offset
,
TyAndPacked
{
ty
,
packed
})
=
self
.nonnull_offset_and_ty
(
adt_ty
,
nndiscr
,
discrfield_source
,
)
?
;
let
nonnull
=
adt_ptr
.offset
(
offset
.bytes
(),
&*
self
)
?
;
trace!
(
"struct wrapped nullable pointer type: {}"
,
ty
);
// only the pointer part of a fat pointer is used for this space optimization
let
discr_size
=
self
.type_size
(
ty
)
?
.expect
(
"bad StructWrappedNullablePointer discrfield"
,
);
self
.read_maybe_aligned
(
!
packed
,
|
ectx
|
{
ectx
.read_nonnull_discriminant_value
(
nonnull
,
nndiscr
as
u128
,
discr_size
)
})
?
}
// The discriminant_value intrinsic returns 0 for non-sum types.
Array
{
..
}
|
FatPointer
{
..
}
|
Scalar
{
..
}
|
Univariant
{
..
}
|
Vector
{
..
}
|
UntaggedUnion
{
..
}
=>
0
,
};
Ok
(
discr_val
)
}
fn
read_nonnull_discriminant_value
(
&
self
,
ptr
:
MemoryPointer
,
nndiscr
:
u128
,
discr_size
:
u64
,
)
->
EvalResult
<
'tcx
,
u128
>
{
trace!
(
"read_nonnull_discriminant_value: {:?}, {}, {}"
,
ptr
,
nndiscr
,
discr_size
);
let
not_null
=
match
self
.memory
.read_uint
(
ptr
,
discr_size
)
{
Ok
(
0
)
=>
false
,
Ok
(
_
)
|
Err
(
EvalError
{
kind
:
EvalErrorKind
::
ReadPointerAsBytes
,
..
})
=>
true
,
Err
(
e
)
=>
return
Err
(
e
),
};
assert
!
(
nndiscr
==
0
||
nndiscr
==
1
);
Ok
(
if
not_null
{
nndiscr
}
else
{
1
-
nndiscr
})
}
}
src/librustc_mir/interpret/traits.rs
浏览文件 @
f036fe0d
...
...
@@ -105,10 +105,10 @@ pub fn read_size_and_align_from_vtable(
vtable
:
MemoryPointer
,
)
->
EvalResult
<
'tcx
,
(
u64
,
u64
)
>
{
let
pointer_size
=
self
.memory
.pointer_size
();
let
size
=
self
.memory
.read_
usize
(
vtable
.offset
(
pointer_size
,
self
)
?
)
?
;
let
align
=
self
.memory
.read_
usize
(
vtable
.offset
(
pointer_size
*
2
,
self
)
?
,
)
?
;
let
size
=
self
.memory
.read_
ptr_sized_unsigned
(
vtable
.offset
(
pointer_size
,
self
)
?
)
?
.to_bytes
()
?
as
u64
;
let
align
=
self
.memory
.read_
ptr_sized_unsigned
(
vtable
.offset
(
pointer_size
*
2
,
self
)
?
)
?
.to_bytes
()
?
as
u64
;
Ok
((
size
,
align
))
}
...
...
src/librustc_mir/interpret/value.rs
浏览文件 @
f036fe0d
...
...
@@ -176,13 +176,13 @@ pub fn into_ptr<M: Machine<'tcx>>(
mem
:
&
Memory
<
'a
,
'tcx
,
M
>
,
)
->
EvalResult
<
'tcx
,
Pointer
>
{
use
self
::
Value
::
*
;
match
*
self
{
Ok
(
match
*
self
{
ByRef
(
PtrAndAlign
{
ptr
,
aligned
})
=>
{
mem
.read_maybe_aligned
(
aligned
,
|
mem
|
mem
.read_ptr
(
ptr
.to_ptr
()
?
))
mem
.read_maybe_aligned
(
aligned
,
|
mem
|
mem
.read_ptr
_sized_unsigned
(
ptr
.to_ptr
()
?
))
?
}
ByVal
(
ptr
)
|
ByValPair
(
ptr
,
_
)
=>
Ok
(
ptr
.into
())
,
}
ByValPair
(
ptr
,
_
)
=>
ptr
,
}
.into
())
}
pub
(
super
)
fn
into_ptr_vtable_pair
<
M
:
Machine
<
'tcx
>>
(
...
...
@@ -196,11 +196,11 @@ pub(super) fn into_ptr_vtable_pair<M: Machine<'tcx>>(
aligned
,
})
=>
{
mem
.read_maybe_aligned
(
aligned
,
|
mem
|
{
let
ptr
=
mem
.read_ptr
(
ref_ptr
.to_ptr
()
?
)
?
;
let
vtable
=
mem
.read_ptr
(
let
ptr
=
mem
.read_ptr
_sized_unsigned
(
ref_ptr
.to_ptr
()
?
)
?
.into
()
;
let
vtable
=
mem
.read_ptr
_sized_unsigned
(
ref_ptr
.offset
(
mem
.pointer_size
(),
mem
.layout
)
?
.to_ptr
()
?
,
)
?
;
Ok
((
ptr
,
vtable
.to_ptr
()
?
))
)
?
.to_ptr
()
?
;
Ok
((
ptr
,
vtable
))
})
}
...
...
@@ -222,10 +222,10 @@ pub(super) fn into_slice<M: Machine<'tcx>>(
aligned
,
})
=>
{
mem
.read_maybe_aligned
(
aligned
,
|
mem
|
{
let
ptr
=
mem
.read_ptr
(
ref_ptr
.to_ptr
()
?
)
?
;
let
len
=
mem
.read_
usize
(
let
ptr
=
mem
.read_ptr
_sized_unsigned
(
ref_ptr
.to_ptr
()
?
)
?
.into
()
;
let
len
=
mem
.read_
ptr_sized_unsigned
(
ref_ptr
.offset
(
mem
.pointer_size
(),
mem
.layout
)
?
.to_ptr
()
?
,
)
?
;
)
?
.to_bytes
()
?
as
u64
;
Ok
((
ptr
,
len
))
})
}
...
...
tests/run-pass-fullmir/integer-ops.rs
浏览文件 @
f036fe0d
...
...
@@ -14,6 +14,10 @@
use
std
::
i32
;
pub
fn
main
()
{
// This tests that do (not) do sign extension properly when loading integers
assert_eq!
(
u32
::
max_value
()
as
i64
,
4294967295
);
assert_eq!
(
i32
::
min_value
()
as
i64
,
-
2147483648
);
assert_eq!
(
i8
::
min_value
(),
-
128
);
assert_eq!
(
i8
::
max_value
(),
127
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录