Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
49f784a3
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,发现更多精彩内容 >>
提交
49f784a3
编写于
11月 26, 2016
作者:
S
Scott Olson
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Remove PrimValKind field from PrimVal.
上级
16f3b590
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
246 addition
and
291 deletion
+246
-291
src/interpreter/cast.rs
src/interpreter/cast.rs
+24
-19
src/interpreter/mod.rs
src/interpreter/mod.rs
+55
-74
src/interpreter/terminator/intrinsics.rs
src/interpreter/terminator/intrinsics.rs
+72
-87
src/interpreter/terminator/mod.rs
src/interpreter/terminator/mod.rs
+20
-21
src/memory.rs
src/memory.rs
+8
-3
src/primval.rs
src/primval.rs
+67
-87
未找到文件。
src/interpreter/cast.rs
浏览文件 @
49f784a3
...
...
@@ -11,17 +11,24 @@
use
syntax
::
ast
::{
FloatTy
,
IntTy
,
UintTy
};
impl
<
'a
,
'tcx
>
EvalContext
<
'a
,
'tcx
>
{
pub
(
super
)
fn
cast_primval
(
&
self
,
val
:
PrimVal
,
ty
:
Ty
<
'tcx
>
)
->
EvalResult
<
'tcx
,
PrimVal
>
{
pub
(
super
)
fn
cast_primval
(
&
self
,
val
:
PrimVal
,
src_ty
:
Ty
<
'tcx
>
,
dest_ty
:
Ty
<
'tcx
>
)
->
EvalResult
<
'tcx
,
PrimVal
>
{
let
kind
=
self
.ty_to_primval_kind
(
src_ty
)
?
;
use
primval
::
PrimValKind
::
*
;
match
val
.
kind
{
F32
=>
self
.cast_float
(
val
.to_f32
()
as
f64
,
ty
),
F64
=>
self
.cast_float
(
val
.to_f64
(),
ty
),
match
kind
{
F32
=>
self
.cast_float
(
val
.to_f32
()
as
f64
,
dest_
ty
),
F64
=>
self
.cast_float
(
val
.to_f64
(),
dest_
ty
),
I8
|
I16
|
I32
|
I64
=>
self
.cast_signed_int
(
val
.bits
as
i64
,
ty
),
I8
|
I16
|
I32
|
I64
=>
self
.cast_signed_int
(
val
.bits
as
i64
,
dest_
ty
),
Bool
|
Char
|
U8
|
U16
|
U32
|
U64
=>
self
.cast_int
(
val
.bits
,
ty
,
false
),
Bool
|
Char
|
U8
|
U16
|
U32
|
U64
=>
self
.cast_int
(
val
.bits
,
dest_
ty
,
false
),
FnPtr
|
Ptr
=>
self
.cast_ptr
(
val
.to_ptr
(),
ty
),
FnPtr
|
Ptr
=>
self
.cast_ptr
(
val
.to_ptr
(),
dest_
ty
),
}
}
...
...
@@ -30,22 +37,21 @@ fn cast_signed_int(&self, val: i64, ty: ty::Ty<'tcx>) -> EvalResult<'tcx, PrimVa
}
fn
cast_int
(
&
self
,
v
:
u64
,
ty
:
ty
::
Ty
<
'tcx
>
,
negative
:
bool
)
->
EvalResult
<
'tcx
,
PrimVal
>
{
use
primval
::
PrimValKind
::
*
;
use
rustc
::
ty
::
TypeVariants
::
*
;
match
ty
.sty
{
TyBool
if
v
==
0
=>
Ok
(
PrimVal
::
from_bool
(
false
)),
TyBool
if
v
==
1
=>
Ok
(
PrimVal
::
from_bool
(
true
)),
TyBool
=>
Err
(
EvalError
::
InvalidBool
),
TyInt
(
IntTy
::
I8
)
=>
Ok
(
PrimVal
::
new
(
v
as
i64
as
i8
as
u64
,
I8
)),
TyInt
(
IntTy
::
I16
)
=>
Ok
(
PrimVal
::
new
(
v
as
i64
as
i16
as
u64
,
I16
)),
TyInt
(
IntTy
::
I32
)
=>
Ok
(
PrimVal
::
new
(
v
as
i64
as
i32
as
u64
,
I32
)),
TyInt
(
IntTy
::
I64
)
=>
Ok
(
PrimVal
::
new
(
v
as
i64
as
i64
as
u64
,
I64
)),
TyInt
(
IntTy
::
I8
)
=>
Ok
(
PrimVal
::
new
(
v
as
i64
as
i8
as
u64
)),
TyInt
(
IntTy
::
I16
)
=>
Ok
(
PrimVal
::
new
(
v
as
i64
as
i16
as
u64
)),
TyInt
(
IntTy
::
I32
)
=>
Ok
(
PrimVal
::
new
(
v
as
i64
as
i32
as
u64
)),
TyInt
(
IntTy
::
I64
)
=>
Ok
(
PrimVal
::
new
(
v
as
i64
as
i64
as
u64
)),
TyUint
(
UintTy
::
U8
)
=>
Ok
(
PrimVal
::
new
(
v
as
u8
as
u64
,
U8
)),
TyUint
(
UintTy
::
U16
)
=>
Ok
(
PrimVal
::
new
(
v
as
u16
as
u64
,
U16
)),
TyUint
(
UintTy
::
U32
)
=>
Ok
(
PrimVal
::
new
(
v
as
u32
as
u64
,
U32
)),
TyUint
(
UintTy
::
U64
)
=>
Ok
(
PrimVal
::
new
(
v
,
U64
)),
TyUint
(
UintTy
::
U8
)
=>
Ok
(
PrimVal
::
new
(
v
as
u8
as
u64
)),
TyUint
(
UintTy
::
U16
)
=>
Ok
(
PrimVal
::
new
(
v
as
u16
as
u64
)),
TyUint
(
UintTy
::
U32
)
=>
Ok
(
PrimVal
::
new
(
v
as
u32
as
u64
)),
TyUint
(
UintTy
::
U64
)
=>
Ok
(
PrimVal
::
new
(
v
)),
TyInt
(
IntTy
::
Is
)
=>
{
let
int_ty
=
self
.tcx.sess.target.int_type
;
...
...
@@ -64,7 +70,7 @@ fn cast_int(&self, v: u64, ty: ty::Ty<'tcx>, negative: bool) -> EvalResult<'tcx,
TyFloat
(
FloatTy
::
F32
)
if
negative
=>
Ok
(
PrimVal
::
from_f32
(
v
as
i64
as
f32
)),
TyFloat
(
FloatTy
::
F32
)
=>
Ok
(
PrimVal
::
from_f32
(
v
as
f32
)),
TyChar
if
v
as
u8
as
u64
==
v
=>
Ok
(
PrimVal
::
new
(
v
,
Char
)),
TyChar
if
v
as
u8
as
u64
==
v
=>
Ok
(
PrimVal
::
new
(
v
)),
TyChar
=>
Err
(
EvalError
::
InvalidChar
(
v
)),
TyRawPtr
(
_
)
=>
Ok
(
PrimVal
::
from_ptr
(
Pointer
::
from_int
(
v
))),
...
...
@@ -91,8 +97,7 @@ fn cast_float(&self, val: f64, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
fn
cast_ptr
(
&
self
,
ptr
:
Pointer
,
ty
:
Ty
<
'tcx
>
)
->
EvalResult
<
'tcx
,
PrimVal
>
{
use
rustc
::
ty
::
TypeVariants
::
*
;
match
ty
.sty
{
TyRef
(
..
)
|
TyRawPtr
(
_
)
=>
Ok
(
PrimVal
::
from_ptr
(
ptr
)),
TyFnPtr
(
_
)
=>
Ok
(
PrimVal
::
from_fn_ptr
(
ptr
)),
TyRef
(
..
)
|
TyRawPtr
(
_
)
|
TyFnPtr
(
_
)
=>
Ok
(
PrimVal
::
from_ptr
(
ptr
)),
TyInt
(
_
)
|
TyUint
(
_
)
=>
self
.transmute_primval
(
PrimVal
::
from_ptr
(
ptr
),
ty
),
_
=>
Err
(
EvalError
::
Unimplemented
(
format!
(
"ptr to {:?} cast"
,
ty
))),
}
...
...
src/interpreter/mod.rs
浏览文件 @
49f784a3
...
...
@@ -222,16 +222,12 @@ pub fn stack(&self) -> &[Frame<'tcx>] {
&
self
.stack
}
fn
usize_primval
(
&
self
,
n
:
u64
)
->
PrimVal
{
PrimVal
::
from_uint_with_size
(
n
,
self
.memory
.pointer_size
())
}
fn
str_to_value
(
&
mut
self
,
s
:
&
str
)
->
EvalResult
<
'tcx
,
Value
>
{
// FIXME: cache these allocs
let
ptr
=
self
.memory
.allocate
(
s
.len
()
as
u64
,
1
)
?
;
self
.memory
.write_bytes
(
ptr
,
s
.as_bytes
())
?
;
self
.memory
.freeze
(
ptr
.alloc_id
)
?
;
Ok
(
Value
::
ByValPair
(
PrimVal
::
from_ptr
(
ptr
),
self
.usize_primval
(
s
.len
()
as
u64
)))
Ok
(
Value
::
ByValPair
(
PrimVal
::
from_ptr
(
ptr
),
PrimVal
::
from_uint
(
s
.len
()
as
u64
)))
}
fn
const_to_value
(
&
mut
self
,
const_val
:
&
ConstVal
)
->
EvalResult
<
'tcx
,
Value
>
{
...
...
@@ -239,27 +235,7 @@ fn const_to_value(&mut self, const_val: &ConstVal) -> EvalResult<'tcx, Value> {
use
rustc_const_math
::
ConstFloat
;
let
primval
=
match
*
const_val
{
Integral
(
const_int
)
=>
{
use
rustc_const_math
::
ConstInt
::
*
;
use
rustc_const_math
::
ConstIsize
::
*
;
use
rustc_const_math
::
ConstUsize
::
*
;
let
kind
=
match
const_int
{
I8
(
_
)
=>
PrimValKind
::
I8
,
I16
(
_
)
|
Isize
(
Is16
(
_
))
=>
PrimValKind
::
I16
,
I32
(
_
)
|
Isize
(
Is32
(
_
))
=>
PrimValKind
::
I32
,
I64
(
_
)
|
Isize
(
Is64
(
_
))
=>
PrimValKind
::
I64
,
U8
(
_
)
=>
PrimValKind
::
U8
,
U16
(
_
)
|
Usize
(
Us16
(
_
))
=>
PrimValKind
::
U16
,
U32
(
_
)
|
Usize
(
Us32
(
_
))
=>
PrimValKind
::
U32
,
U64
(
_
)
|
Usize
(
Us64
(
_
))
=>
PrimValKind
::
U64
,
Infer
(
_
)
|
InferSigned
(
_
)
=>
bug!
(
"uninferred constants only exist before typeck"
),
};
PrimVal
::
new
(
const_int
.to_u64_unchecked
(),
kind
)
}
Integral
(
const_int
)
=>
PrimVal
::
new
(
const_int
.to_u64_unchecked
()),
Float
(
ConstFloat
::
F32
(
f
))
=>
PrimVal
::
from_f32
(
f
),
Float
(
ConstFloat
::
F64
(
f
))
=>
PrimVal
::
from_f64
(
f
),
...
...
@@ -306,7 +282,8 @@ pub fn load_mir(&self, def_id: DefId) -> EvalResult<'tcx, MirRef<'tcx>> {
pub
fn
monomorphize
(
&
self
,
ty
:
Ty
<
'tcx
>
,
substs
:
&
'tcx
Substs
<
'tcx
>
)
->
Ty
<
'tcx
>
{
let
substituted
=
ty
.subst
(
self
.tcx
,
substs
);
self
.tcx
.normalize_associated_type
(
&
substituted
)
let
new
=
self
.tcx
.normalize_associated_type
(
&
substituted
);
new
}
fn
type_size
(
&
self
,
ty
:
Ty
<
'tcx
>
)
->
EvalResult
<
'tcx
,
Option
<
u64
>>
{
...
...
@@ -432,9 +409,13 @@ fn binop_with_overflow(
left
:
&
mir
::
Operand
<
'tcx
>
,
right
:
&
mir
::
Operand
<
'tcx
>
,
)
->
EvalResult
<
'tcx
,
(
PrimVal
,
bool
)
>
{
let
left_primval
=
self
.eval_operand_to_primval
(
left
)
?
;
let
right_primval
=
self
.eval_operand_to_primval
(
right
)
?
;
primval
::
binary_op
(
op
,
left_primval
,
right_primval
)
let
left_ty
=
self
.operand_ty
(
left
);
let
right_ty
=
self
.operand_ty
(
right
);
let
left_kind
=
self
.ty_to_primval_kind
(
left_ty
)
?
;
let
right_kind
=
self
.ty_to_primval_kind
(
right_ty
)
?
;
let
left_val
=
self
.eval_operand_to_primval
(
left
)
?
;
let
right_val
=
self
.eval_operand_to_primval
(
right
)
?
;
primval
::
binary_op
(
op
,
left_val
,
left_kind
,
right_val
,
right_kind
)
}
/// Applies the binary operation `op` to the two operands and writes a tuple of the result
...
...
@@ -460,9 +441,10 @@ fn intrinsic_overflowing(
left
:
&
mir
::
Operand
<
'tcx
>
,
right
:
&
mir
::
Operand
<
'tcx
>
,
dest
:
Lvalue
<
'tcx
>
,
dest_ty
:
Ty
<
'tcx
>
,
)
->
EvalResult
<
'tcx
,
bool
>
{
let
(
val
,
overflowed
)
=
self
.binop_with_overflow
(
op
,
left
,
right
)
?
;
self
.write_primval
(
dest
,
val
)
?
;
self
.write_primval
(
dest
,
val
,
dest_ty
)
?
;
Ok
(
overflowed
)
}
...
...
@@ -506,7 +488,7 @@ fn eval_rvalue_into_lvalue(
BinaryOp
(
bin_op
,
ref
left
,
ref
right
)
=>
{
// ignore overflow bit, rustc inserts check branches for us
self
.intrinsic_overflowing
(
bin_op
,
left
,
right
,
dest
)
?
;
self
.intrinsic_overflowing
(
bin_op
,
left
,
right
,
dest
,
dest_ty
)
?
;
}
CheckedBinaryOp
(
bin_op
,
ref
left
,
ref
right
)
=>
{
...
...
@@ -515,7 +497,8 @@ fn eval_rvalue_into_lvalue(
UnaryOp
(
un_op
,
ref
operand
)
=>
{
let
val
=
self
.eval_operand_to_primval
(
operand
)
?
;
self
.write_primval
(
dest
,
primval
::
unary_op
(
un_op
,
val
)
?
)
?
;
let
kind
=
self
.ty_to_primval_kind
(
dest_ty
)
?
;
self
.write_primval
(
dest
,
primval
::
unary_op
(
un_op
,
val
,
kind
)
?
,
dest_ty
)
?
;
}
Aggregate
(
ref
kind
,
ref
operands
)
=>
{
...
...
@@ -571,9 +554,7 @@ fn eval_rvalue_into_lvalue(
let
operand_ty
=
self
.operand_ty
(
operand
);
assert_eq!
(
self
.type_size
(
operand_ty
)
?
,
Some
(
0
));
}
let
value_size
=
self
.type_size
(
dest_ty
)
?
.expect
(
"pointer types are sized"
);
let
zero
=
PrimVal
::
from_int_with_size
(
0
,
value_size
);
self
.write_primval
(
dest
,
zero
)
?
;
self
.write_primval
(
dest
,
PrimVal
::
from_int
(
0
),
dest_ty
)
?
;
}
}
else
{
bug!
(
"tried to assign {:?} to Layout::RawNullablePointer"
,
kind
);
...
...
@@ -604,19 +585,11 @@ fn eval_rvalue_into_lvalue(
}
}
CEnum
{
discr
,
signed
,
..
}
=>
{
CEnum
{
..
}
=>
{
assert_eq!
(
operands
.len
(),
0
);
if
let
mir
::
AggregateKind
::
Adt
(
adt_def
,
variant
,
_
,
_
)
=
*
kind
{
let
n
=
adt_def
.variants
[
variant
]
.disr_val
.to_u64_unchecked
();
let
size
=
discr
.size
()
.bytes
();
let
val
=
if
signed
{
PrimVal
::
from_int_with_size
(
n
as
i64
,
size
)
}
else
{
PrimVal
::
from_uint_with_size
(
n
,
size
)
};
self
.write_primval
(
dest
,
val
)
?
;
self
.write_primval
(
dest
,
PrimVal
::
new
(
n
),
dest_ty
)
?
;
}
else
{
bug!
(
"tried to assign {:?} to Layout::CEnum"
,
kind
);
}
...
...
@@ -655,8 +628,7 @@ fn eval_rvalue_into_lvalue(
let
src
=
self
.eval_lvalue
(
lvalue
)
?
;
let
ty
=
self
.lvalue_ty
(
lvalue
);
let
(
_
,
len
)
=
src
.elem_ty_and_len
(
ty
);
let
len_val
=
self
.usize_primval
(
len
);
self
.write_primval
(
dest
,
len_val
)
?
;
self
.write_primval
(
dest
,
PrimVal
::
from_uint
(
len
),
dest_ty
)
?
;
}
Ref
(
_
,
_
,
ref
lvalue
)
=>
{
...
...
@@ -666,7 +638,7 @@ fn eval_rvalue_into_lvalue(
let
val
=
match
extra
{
LvalueExtra
::
None
=>
Value
::
ByVal
(
ptr
),
LvalueExtra
::
Length
(
len
)
=>
Value
::
ByValPair
(
ptr
,
self
.usize_primval
(
len
)),
LvalueExtra
::
Length
(
len
)
=>
Value
::
ByValPair
(
ptr
,
PrimVal
::
from_uint
(
len
)),
LvalueExtra
::
Vtable
(
vtable
)
=>
Value
::
ByValPair
(
ptr
,
PrimVal
::
from_ptr
(
vtable
)),
LvalueExtra
::
DowncastVariant
(
..
)
=>
bug!
(
"attempted to take a reference to an enum downcast lvalue"
),
...
...
@@ -677,7 +649,7 @@ fn eval_rvalue_into_lvalue(
Box
(
ty
)
=>
{
let
ptr
=
self
.alloc_ptr
(
ty
)
?
;
self
.write_primval
(
dest
,
PrimVal
::
from_ptr
(
ptr
))
?
;
self
.write_primval
(
dest
,
PrimVal
::
from_ptr
(
ptr
)
,
dest_ty
)
?
;
}
Cast
(
kind
,
ref
operand
,
cast_ty
)
=>
{
...
...
@@ -707,7 +679,7 @@ fn eval_rvalue_into_lvalue(
}
}
else
{
let
src_val
=
self
.value_to_primval
(
src
,
src_ty
)
?
;
let
dest_val
=
self
.cast_primval
(
src_val
,
dest_ty
)
?
;
let
dest_val
=
self
.cast_primval
(
src_val
,
src_ty
,
dest_ty
)
?
;
self
.write_value
(
Value
::
ByVal
(
dest_val
),
dest
,
dest_ty
)
?
;
}
}
...
...
@@ -716,7 +688,7 @@ fn eval_rvalue_into_lvalue(
ty
::
TyFnDef
(
def_id
,
substs
,
fn_ty
)
=>
{
let
fn_ty
=
self
.tcx
.erase_regions
(
&
fn_ty
);
let
fn_ptr
=
self
.memory
.create_fn_ptr
(
self
.tcx
,
def_id
,
substs
,
fn_ty
);
self
.write_value
(
Value
::
ByVal
(
PrimVal
::
from_
fn_
ptr
(
fn_ptr
)),
dest
,
dest_ty
)
?
;
self
.write_value
(
Value
::
ByVal
(
PrimVal
::
from_ptr
(
fn_ptr
)),
dest
,
dest_ty
)
?
;
},
ref
other
=>
bug!
(
"reify fn pointer on {:?}"
,
other
),
},
...
...
@@ -728,7 +700,7 @@ fn eval_rvalue_into_lvalue(
let
(
def_id
,
substs
,
_
,
_
)
=
self
.memory
.get_fn
(
ptr
.alloc_id
)
?
;
let
unsafe_fn_ty
=
self
.tcx
.erase_regions
(
&
unsafe_fn_ty
);
let
fn_ptr
=
self
.memory
.create_fn_ptr
(
self
.tcx
,
def_id
,
substs
,
unsafe_fn_ty
);
self
.write_value
(
Value
::
ByVal
(
PrimVal
::
from_
fn_
ptr
(
fn_ptr
)),
dest
,
dest_ty
)
?
;
self
.write_value
(
Value
::
ByVal
(
PrimVal
::
from_ptr
(
fn_ptr
)),
dest
,
dest_ty
)
?
;
},
ref
other
=>
bug!
(
"fn to unsafe fn cast on {:?}"
,
other
),
},
...
...
@@ -1059,8 +1031,7 @@ fn eval_lvalue_projection(
let
elem_size
=
self
.type_size
(
elem_ty
)
?
.expect
(
"slice element must be sized"
);
let
n_ptr
=
self
.eval_operand
(
operand
)
?
;
let
usize
=
self
.tcx.types.usize
;
let
n
=
self
.value_to_primval
(
n_ptr
,
usize
)
?
.expect_uint
(
"Projection::Index expected usize"
);
let
n
=
self
.value_to_primval
(
n_ptr
,
usize
)
?
.to_u64
();
assert
!
(
n
<
len
);
let
ptr
=
base_ptr
.offset
(
n
*
elem_size
);
(
ptr
,
LvalueExtra
::
None
)
...
...
@@ -1124,6 +1095,7 @@ fn force_allocation(&mut self, lvalue: Lvalue<'tcx>) -> EvalResult<'tcx, Lvalue<
Some
(
Value
::
ByRef
(
ptr
))
=>
Lvalue
::
from_ptr
(
ptr
),
opt_val
=>
{
let
ty
=
self
.stack
[
frame
]
.mir.local_decls
[
local
]
.ty
;
let
ty
=
self
.monomorphize
(
ty
,
self
.stack
[
frame
]
.substs
);
let
substs
=
self
.stack
[
frame
]
.substs
;
let
ptr
=
self
.alloc_ptr_with_substs
(
ty
,
substs
)
?
;
self
.stack
[
frame
]
.set_local
(
local
,
Value
::
ByRef
(
ptr
));
...
...
@@ -1168,7 +1140,8 @@ fn value_to_ptr_dont_use(&mut self, value: Value, ty: Ty<'tcx>) -> EvalResult<'t
Value
::
ByVal
(
primval
)
=>
{
let
ptr
=
self
.alloc_ptr
(
ty
)
?
;
self
.memory
.write_primval
(
ptr
,
primval
)
?
;
let
kind
=
self
.ty_to_primval_kind
(
ty
)
?
;
self
.memory
.write_primval
(
ptr
,
primval
,
kind
)
?
;
Ok
(
ptr
)
}
...
...
@@ -1202,19 +1175,22 @@ fn value_to_primval(&mut self, value: Value, ty: Ty<'tcx>) -> EvalResult<'tcx, P
}
}
fn
transmute_primval
(
&
self
,
val
:
PrimVal
,
ty
:
Ty
<
'tcx
>
)
->
EvalResult
<
'tcx
,
PrimVal
>
{
Ok
(
PrimVal
{
kind
:
self
.ty_to_primval_kind
(
ty
)
?
,
..
val
})
// FIXME(solson): Delete this.
fn
transmute_primval
(
&
self
,
val
:
PrimVal
,
_
ty
:
Ty
<
'tcx
>
)
->
EvalResult
<
'tcx
,
PrimVal
>
{
Ok
(
val
)
}
fn
write_primval
(
&
mut
self
,
dest
:
Lvalue
<
'tcx
>
,
val
:
PrimVal
,
dest_ty
:
Ty
<
'tcx
>
,
)
->
EvalResult
<
'tcx
,
()
>
{
match
dest
{
Lvalue
::
Ptr
{
ptr
,
extra
}
=>
{
assert_eq!
(
extra
,
LvalueExtra
::
None
);
self
.memory
.write_primval
(
ptr
,
val
)
let
kind
=
self
.ty_to_primval_kind
(
dest_ty
)
?
;
self
.memory
.write_primval
(
ptr
,
val
,
kind
)
}
Lvalue
::
Local
{
frame
,
local
}
=>
{
self
.stack
[
frame
]
.set_local
(
local
,
Value
::
ByVal
(
val
));
...
...
@@ -1319,7 +1295,10 @@ fn write_value_to_ptr(
)
->
EvalResult
<
'tcx
,
()
>
{
match
value
{
Value
::
ByRef
(
ptr
)
=>
self
.copy
(
ptr
,
dest
,
dest_ty
),
Value
::
ByVal
(
primval
)
=>
self
.memory
.write_primval
(
dest
,
primval
),
Value
::
ByVal
(
primval
)
=>
{
let
kind
=
self
.ty_to_primval_kind
(
dest_ty
)
?
;
self
.memory
.write_primval
(
dest
,
primval
,
kind
)
}
Value
::
ByValPair
(
a
,
b
)
=>
self
.write_pair_to_ptr
(
a
,
b
,
dest
,
dest_ty
),
}
}
...
...
@@ -1334,8 +1313,12 @@ fn write_pair_to_ptr(
assert_eq!
(
self
.get_field_count
(
ty
)
?
,
2
);
let
field_0
=
self
.get_field_offset
(
ty
,
0
)
?
.bytes
();
let
field_1
=
self
.get_field_offset
(
ty
,
1
)
?
.bytes
();
self
.memory
.write_primval
(
ptr
.offset
(
field_0
),
a
)
?
;
self
.memory
.write_primval
(
ptr
.offset
(
field_1
),
b
)
?
;
let
field_0_ty
=
self
.get_field_ty
(
ty
,
0
)
?
;
let
field_1_ty
=
self
.get_field_ty
(
ty
,
1
)
?
;
let
field_0_kind
=
self
.ty_to_primval_kind
(
field_0_ty
)
?
;
let
field_1_kind
=
self
.ty_to_primval_kind
(
field_1_ty
)
?
;
self
.memory
.write_primval
(
ptr
.offset
(
field_0
),
a
,
field_0_kind
)
?
;
self
.memory
.write_primval
(
ptr
.offset
(
field_1
),
b
,
field_1_kind
)
?
;
Ok
(())
}
...
...
@@ -1432,8 +1415,7 @@ fn read_value(&mut self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Value>
I64
=>
8
,
Is
=>
self
.memory
.pointer_size
(),
};
let
n
=
self
.memory
.read_int
(
ptr
,
size
)
?
;
PrimVal
::
from_int_with_size
(
n
,
size
)
PrimVal
::
from_int
(
self
.memory
.read_int
(
ptr
,
size
)
?
)
}
ty
::
TyUint
(
uint_ty
)
=>
{
...
...
@@ -1445,17 +1427,18 @@ fn read_value(&mut self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Value>
U64
=>
8
,
Us
=>
self
.memory
.pointer_size
(),
};
let
n
=
self
.memory
.read_uint
(
ptr
,
size
)
?
;
PrimVal
::
from_uint_with_size
(
n
,
size
)
PrimVal
::
from_uint
(
self
.memory
.read_uint
(
ptr
,
size
)
?
)
}
ty
::
TyFloat
(
FloatTy
::
F32
)
=>
PrimVal
::
from_f32
(
self
.memory
.read_f32
(
ptr
)
?
),
ty
::
TyFloat
(
FloatTy
::
F64
)
=>
PrimVal
::
from_f64
(
self
.memory
.read_f64
(
ptr
)
?
),
// TODO(solson): Should this even be here? Fn items aren't primvals, are they?
ty
::
TyFnDef
(
def_id
,
substs
,
fn_ty
)
=>
{
PrimVal
::
from_
fn_
ptr
(
self
.memory
.create_fn_ptr
(
self
.tcx
,
def_id
,
substs
,
fn_ty
))
PrimVal
::
from_ptr
(
self
.memory
.create_fn_ptr
(
self
.tcx
,
def_id
,
substs
,
fn_ty
))
},
ty
::
TyFnPtr
(
_
)
=>
self
.memory
.read_ptr
(
ptr
)
.map
(
PrimVal
::
from_fn_ptr
)
?
,
ty
::
TyFnPtr
(
_
)
=>
self
.memory
.read_ptr
(
ptr
)
.map
(
PrimVal
::
from_ptr
)
?
,
ty
::
TyBox
(
ty
)
|
ty
::
TyRef
(
_
,
ty
::
TypeAndMut
{
ty
,
..
})
|
ty
::
TyRawPtr
(
ty
::
TypeAndMut
{
ty
,
..
})
=>
{
...
...
@@ -1468,7 +1451,7 @@ fn read_value(&mut self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Value>
let
extra
=
match
self
.tcx
.struct_tail
(
ty
)
.sty
{
ty
::
TyTrait
(
..
)
=>
PrimVal
::
from_ptr
(
self
.memory
.read_ptr
(
extra
)
?
),
ty
::
TySlice
(
..
)
|
ty
::
TyStr
=>
self
.usize_primval
(
self
.memory
.read_usize
(
extra
)
?
),
ty
::
TyStr
=>
PrimVal
::
from_uint
(
self
.memory
.read_usize
(
extra
)
?
),
_
=>
bug!
(
"unsized primval ptr read from {:?}"
,
ty
),
};
return
Ok
(
Value
::
ByValPair
(
PrimVal
::
from_ptr
(
p
),
extra
));
...
...
@@ -1480,11 +1463,9 @@ fn read_value(&mut self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Value>
if
let
CEnum
{
discr
,
signed
,
..
}
=
*
self
.type_layout
(
ty
)
?
{
let
size
=
discr
.size
()
.bytes
();
if
signed
{
let
n
=
self
.memory
.read_int
(
ptr
,
size
)
?
;
PrimVal
::
from_int_with_size
(
n
,
size
)
PrimVal
::
from_int
(
self
.memory
.read_int
(
ptr
,
size
)
?
)
}
else
{
let
n
=
self
.memory
.read_uint
(
ptr
,
size
)
?
;
PrimVal
::
from_uint_with_size
(
n
,
size
)
PrimVal
::
from_uint
(
self
.memory
.read_uint
(
ptr
,
size
)
?
)
}
}
else
{
bug!
(
"primitive read of non-clike enum: {:?}"
,
ty
);
...
...
@@ -1531,7 +1512,7 @@ fn unsize_into(
match
(
&
src_pointee_ty
.sty
,
&
dest_pointee_ty
.sty
)
{
(
&
ty
::
TyArray
(
_
,
length
),
&
ty
::
TySlice
(
_
))
=>
{
let
ptr
=
src
.read_ptr
(
&
self
.memory
)
?
;
let
len
=
self
.usize_primval
(
length
as
u64
);
let
len
=
PrimVal
::
from_uint
(
length
as
u64
);
let
ptr
=
PrimVal
::
from_ptr
(
ptr
);
self
.write_value
(
Value
::
ByValPair
(
ptr
,
len
),
dest
,
dest_ty
)
?
;
}
...
...
src/interpreter/terminator/intrinsics.rs
浏览文件 @
49f784a3
...
...
@@ -44,10 +44,9 @@ pub(super) fn call_intrinsic(
"arith_offset"
=>
{
let
ptr
=
arg_vals
[
0
]
.read_ptr
(
&
self
.memory
)
?
;
let
offset
=
self
.value_to_primval
(
arg_vals
[
1
],
isize
)
?
.expect_int
(
"arith_offset second arg not isize"
);
let
offset
=
self
.value_to_primval
(
arg_vals
[
1
],
isize
)
?
.to_i64
();
let
new_ptr
=
ptr
.signed_offset
(
offset
);
self
.write_primval
(
dest
,
PrimVal
::
from_ptr
(
new_ptr
))
?
;
self
.write_primval
(
dest
,
PrimVal
::
from_ptr
(
new_ptr
)
,
dest_ty
)
?
;
}
"assume"
=>
{
...
...
@@ -85,8 +84,8 @@ pub(super) fn call_intrinsic(
Value
::
ByRef
(
_
)
=>
bug!
(
"just read the value, can't be byref"
),
Value
::
ByValPair
(
..
)
=>
bug!
(
"atomic_xchg doesn't work with nonprimitives"
),
};
self
.write_primval
(
dest
,
old
)
?
;
self
.write_primval
(
Lvalue
::
from_ptr
(
ptr
),
change
)
?
;
self
.write_primval
(
dest
,
old
,
ty
)
?
;
self
.write_primval
(
Lvalue
::
from_ptr
(
ptr
),
change
,
ty
)
?
;
}
"atomic_cxchg"
=>
{
...
...
@@ -100,10 +99,11 @@ pub(super) fn call_intrinsic(
Value
::
ByRef
(
_
)
=>
bug!
(
"just read the value, can't be byref"
),
Value
::
ByValPair
(
..
)
=>
bug!
(
"atomic_cxchg doesn't work with nonprimitives"
),
};
let
(
val
,
_
)
=
primval
::
binary_op
(
mir
::
BinOp
::
Eq
,
old
,
expect_old
)
?
;
let
kind
=
self
.ty_to_primval_kind
(
ty
)
?
;
let
(
val
,
_
)
=
primval
::
binary_op
(
mir
::
BinOp
::
Eq
,
old
,
kind
,
expect_old
,
kind
)
?
;
let
dest
=
self
.force_allocation
(
dest
)
?
.to_ptr
();
self
.write_pair_to_ptr
(
old
,
val
,
dest
,
dest_ty
)
?
;
self
.write_primval
(
Lvalue
::
from_ptr
(
ptr
),
change
)
?
;
self
.write_primval
(
Lvalue
::
from_ptr
(
ptr
),
change
,
ty
)
?
;
}
"atomic_xadd_relaxed"
=>
{
...
...
@@ -116,10 +116,11 @@ pub(super) fn call_intrinsic(
Value
::
ByRef
(
_
)
=>
bug!
(
"just read the value, can't be byref"
),
Value
::
ByValPair
(
..
)
=>
bug!
(
"atomic_xadd_relaxed doesn't work with nonprimitives"
),
};
self
.write_primval
(
dest
,
old
)
?
;
self
.write_primval
(
dest
,
old
,
ty
)
?
;
let
kind
=
self
.ty_to_primval_kind
(
ty
)
?
;
// FIXME: what do atomics do on overflow?
let
(
val
,
_
)
=
primval
::
binary_op
(
mir
::
BinOp
::
Add
,
old
,
change
)
?
;
self
.write_primval
(
Lvalue
::
from_ptr
(
ptr
),
val
)
?
;
let
(
val
,
_
)
=
primval
::
binary_op
(
mir
::
BinOp
::
Add
,
old
,
kind
,
change
,
kind
)
?
;
self
.write_primval
(
Lvalue
::
from_ptr
(
ptr
),
val
,
ty
)
?
;
},
"atomic_xsub_rel"
=>
{
...
...
@@ -132,10 +133,11 @@ pub(super) fn call_intrinsic(
Value
::
ByRef
(
_
)
=>
bug!
(
"just read the value, can't be byref"
),
Value
::
ByValPair
(
..
)
=>
bug!
(
"atomic_xsub_rel doesn't work with nonprimitives"
),
};
self
.write_primval
(
dest
,
old
)
?
;
self
.write_primval
(
dest
,
old
,
ty
)
?
;
let
kind
=
self
.ty_to_primval_kind
(
ty
)
?
;
// FIXME: what do atomics do on overflow?
let
(
val
,
_
)
=
primval
::
binary_op
(
mir
::
BinOp
::
Sub
,
old
,
change
)
?
;
self
.write_primval
(
Lvalue
::
from_ptr
(
ptr
),
val
)
?
;
let
(
val
,
_
)
=
primval
::
binary_op
(
mir
::
BinOp
::
Sub
,
old
,
kind
,
change
,
kind
)
?
;
self
.write_primval
(
Lvalue
::
from_ptr
(
ptr
),
val
,
ty
)
?
;
}
"breakpoint"
=>
unimplemented!
(),
// halt miri
...
...
@@ -148,8 +150,7 @@ pub(super) fn call_intrinsic(
let
elem_align
=
self
.type_align
(
elem_ty
)
?
;
let
src
=
arg_vals
[
0
]
.read_ptr
(
&
self
.memory
)
?
;
let
dest
=
arg_vals
[
1
]
.read_ptr
(
&
self
.memory
)
?
;
let
count
=
self
.value_to_primval
(
arg_vals
[
2
],
usize
)
?
.expect_uint
(
"arith_offset second arg not isize"
);
let
count
=
self
.value_to_primval
(
arg_vals
[
2
],
usize
)
?
.to_u64
();
self
.memory
.copy
(
src
,
dest
,
count
*
elem_size
,
elem_align
)
?
;
}
...
...
@@ -157,17 +158,18 @@ pub(super) fn call_intrinsic(
"cttz"
|
"ctlz"
|
"bswap"
=>
{
let
elem_ty
=
substs
.type_at
(
0
);
let
num
=
self
.value_to_primval
(
arg_vals
[
0
],
elem_ty
)
?
;
let
num
=
numeric_intrinsic
(
intrinsic_name
,
num
);
self
.write_primval
(
dest
,
num
)
?
;
let
ty
=
substs
.type_at
(
0
);
let
num
=
self
.value_to_primval
(
arg_vals
[
0
],
ty
)
?
;
let
kind
=
self
.ty_to_primval_kind
(
ty
)
?
;
let
num
=
numeric_intrinsic
(
intrinsic_name
,
num
,
kind
);
self
.write_primval
(
dest
,
num
,
ty
)
?
;
}
"discriminant_value"
=>
{
let
ty
=
substs
.type_at
(
0
);
let
adt_ptr
=
arg_vals
[
0
]
.read_ptr
(
&
self
.memory
)
?
;
let
discr_val
=
self
.read_discriminant_value
(
adt_ptr
,
ty
)
?
;
self
.write_primval
(
dest
,
PrimVal
::
new
(
discr_val
,
PrimValKind
::
U64
)
)
?
;
self
.write_primval
(
dest
,
PrimVal
::
new
(
discr_val
),
dest_ty
)
?
;
}
"drop_in_place"
=>
{
...
...
@@ -196,23 +198,22 @@ pub(super) fn call_intrinsic(
}
"fabsf32"
=>
{
let
f
=
self
.value_to_primval
(
arg_vals
[
2
],
f32
)
?
.expect_f32
(
"fabsf32 read non f32"
);
self
.write_primval
(
dest
,
PrimVal
::
from_f32
(
f
.abs
()))
?
;
let
f
=
self
.value_to_primval
(
arg_vals
[
2
],
f32
)
?
.to_f32
();
self
.write_primval
(
dest
,
PrimVal
::
from_f32
(
f
.abs
()),
dest_ty
)
?
;
}
"fabsf64"
=>
{
let
f
=
self
.value_to_primval
(
arg_vals
[
2
],
f64
)
?
.expect_f64
(
"fabsf64 read non f64"
);
self
.write_primval
(
dest
,
PrimVal
::
from_f64
(
f
.abs
()))
?
;
let
f
=
self
.value_to_primval
(
arg_vals
[
2
],
f64
)
?
.to_f64
();
self
.write_primval
(
dest
,
PrimVal
::
from_f64
(
f
.abs
()),
dest_ty
)
?
;
}
"fadd_fast"
=>
{
let
ty
=
substs
.type_at
(
0
);
let
kind
=
self
.ty_to_primval_kind
(
ty
)
?
;
let
a
=
self
.value_to_primval
(
arg_vals
[
0
],
ty
)
?
;
let
b
=
self
.value_to_primval
(
arg_vals
[
0
],
ty
)
?
;
let
result
=
primval
::
binary_op
(
mir
::
BinOp
::
Add
,
a
,
b
)
?
;
self
.write_primval
(
dest
,
result
.0
)
?
;
let
result
=
primval
::
binary_op
(
mir
::
BinOp
::
Add
,
a
,
kind
,
b
,
kind
)
?
;
self
.write_primval
(
dest
,
result
.0
,
dest_ty
)
?
;
}
"likely"
|
...
...
@@ -220,27 +221,26 @@ pub(super) fn call_intrinsic(
"forget"
=>
{}
"init"
=>
{
let
size
=
dest_layout
.size
(
&
self
.tcx.data_layout
)
.bytes
()
;
let
size
=
self
.type_size
(
dest_ty
)
?
.expect
(
"cannot init unsized value"
);
;
let
init
=
|
this
:
&
mut
Self
,
val
:
Option
<
Value
>
|
{
match
val
{
let
zero_val
=
match
val
{
Some
(
Value
::
ByRef
(
ptr
))
=>
{
this
.memory
.write_repeat
(
ptr
,
0
,
size
)
?
;
Ok
(
Some
(
Value
::
ByRef
(
ptr
))
)
Value
::
ByRef
(
ptr
)
},
None
=>
match
this
.ty_to_primval_kind
(
dest_ty
)
{
Ok
(
kind
)
=>
Ok
(
Some
(
Value
::
ByVal
(
PrimVal
::
new
(
0
,
kind
))
)),
Ok
(
_
)
=>
Value
::
ByVal
(
PrimVal
::
new
(
0
)),
Err
(
_
)
=>
{
let
ptr
=
this
.alloc_ptr_with_substs
(
dest_ty
,
substs
)
?
;
this
.memory
.write_repeat
(
ptr
,
0
,
size
)
?
;
Ok
(
Some
(
Value
::
ByRef
(
ptr
))
)
Value
::
ByRef
(
ptr
)
}
},
Some
(
Value
::
ByVal
(
value
))
=>
Ok
(
Some
(
Value
::
ByVal
(
PrimVal
::
new
(
0
,
value
.kind
)))),
Some
(
Value
::
ByValPair
(
a
,
b
))
=>
Ok
(
Some
(
Value
::
ByValPair
(
PrimVal
::
new
(
0
,
a
.kind
),
PrimVal
::
new
(
0
,
b
.kind
),
))),
}
Some
(
Value
::
ByVal
(
_
))
=>
Value
::
ByVal
(
PrimVal
::
new
(
0
)),
Some
(
Value
::
ByValPair
(
..
))
=>
Value
::
ByValPair
(
PrimVal
::
new
(
0
),
PrimVal
::
new
(
0
)),
};
Ok
(
Some
(
zero_val
))
};
match
dest
{
Lvalue
::
Local
{
frame
,
local
}
=>
self
.modify_local
(
frame
,
local
,
init
)
?
,
...
...
@@ -253,16 +253,16 @@ pub(super) fn call_intrinsic(
"min_align_of"
=>
{
let
elem_ty
=
substs
.type_at
(
0
);
let
elem_align
=
self
.type_align
(
elem_ty
)
?
;
let
align_val
=
self
.usize_primval
(
elem_align
as
u64
);
self
.write_primval
(
dest
,
align_val
)
?
;
let
align_val
=
PrimVal
::
from_uint
(
elem_align
as
u64
);
self
.write_primval
(
dest
,
align_val
,
dest_ty
)
?
;
}
"pref_align_of"
=>
{
let
ty
=
substs
.type_at
(
0
);
let
layout
=
self
.type_layout
(
ty
)
?
;
let
align
=
layout
.align
(
&
self
.tcx.data_layout
)
.pref
();
let
align_val
=
self
.usize_primval
(
align
);
self
.write_primval
(
dest
,
align_val
)
?
;
let
align_val
=
PrimVal
::
from_uint
(
align
);
self
.write_primval
(
dest
,
align_val
,
dest_ty
)
?
;
}
"move_val_init"
=>
{
...
...
@@ -275,59 +275,52 @@ pub(super) fn call_intrinsic(
let
ty
=
substs
.type_at
(
0
);
let
env
=
self
.tcx
.empty_parameter_environment
();
let
needs_drop
=
self
.tcx
.type_needs_drop_given_env
(
ty
,
&
env
);
self
.write_primval
(
dest
,
PrimVal
::
from_bool
(
needs_drop
))
?
;
self
.write_primval
(
dest
,
PrimVal
::
from_bool
(
needs_drop
)
,
dest_ty
)
?
;
}
"offset"
=>
{
let
pointee_ty
=
substs
.type_at
(
0
);
// FIXME: assuming here that type size is < i64::max_value()
let
pointee_size
=
self
.type_size
(
pointee_ty
)
?
.expect
(
"cannot offset a pointer to an unsized type"
)
as
i64
;
let
offset
=
self
.value_to_primval
(
arg_vals
[
1
],
isize
)
?
.expect_int
(
"offset second arg not isize"
);
let
offset
=
self
.value_to_primval
(
arg_vals
[
1
],
isize
)
?
.to_i64
();
let
ptr
=
arg_vals
[
0
]
.read_ptr
(
&
self
.memory
)
?
;
let
result_ptr
=
ptr
.signed_offset
(
offset
*
pointee_size
);
self
.write_primval
(
dest
,
PrimVal
::
from_ptr
(
result_ptr
))
?
;
self
.write_primval
(
dest
,
PrimVal
::
from_ptr
(
result_ptr
)
,
dest_ty
)
?
;
}
"overflowing_sub"
=>
{
self
.intrinsic_overflowing
(
mir
::
BinOp
::
Sub
,
&
args
[
0
],
&
args
[
1
],
dest
)
?
;
self
.intrinsic_overflowing
(
mir
::
BinOp
::
Sub
,
&
args
[
0
],
&
args
[
1
],
dest
,
dest_ty
)
?
;
}
"overflowing_mul"
=>
{
self
.intrinsic_overflowing
(
mir
::
BinOp
::
Mul
,
&
args
[
0
],
&
args
[
1
],
dest
)
?
;
self
.intrinsic_overflowing
(
mir
::
BinOp
::
Mul
,
&
args
[
0
],
&
args
[
1
],
dest
,
dest_ty
)
?
;
}
"overflowing_add"
=>
{
self
.intrinsic_overflowing
(
mir
::
BinOp
::
Add
,
&
args
[
0
],
&
args
[
1
],
dest
)
?
;
self
.intrinsic_overflowing
(
mir
::
BinOp
::
Add
,
&
args
[
0
],
&
args
[
1
],
dest
,
dest_ty
)
?
;
}
"powif32"
=>
{
let
f
=
self
.value_to_primval
(
arg_vals
[
0
],
f32
)
?
.expect_f32
(
"powif32 first arg not f32"
);
let
i
=
self
.value_to_primval
(
arg_vals
[
1
],
i32
)
?
.expect_int
(
"powif32 second arg not i32"
);
self
.write_primval
(
dest
,
PrimVal
::
from_f32
(
f
.powi
(
i
as
i32
)))
?
;
let
f
=
self
.value_to_primval
(
arg_vals
[
0
],
f32
)
?
.to_f32
();
let
i
=
self
.value_to_primval
(
arg_vals
[
1
],
i32
)
?
.to_i64
();
self
.write_primval
(
dest
,
PrimVal
::
from_f32
(
f
.powi
(
i
as
i32
)),
dest_ty
)
?
;
}
"powif64"
=>
{
let
f
=
self
.value_to_primval
(
arg_vals
[
0
],
f64
)
?
.expect_f64
(
"powif64 first arg not f64"
);
let
i
=
self
.value_to_primval
(
arg_vals
[
1
],
i32
)
?
.expect_int
(
"powif64 second arg not i32"
);
self
.write_primval
(
dest
,
PrimVal
::
from_f64
(
f
.powi
(
i
as
i32
)))
?
;
let
f
=
self
.value_to_primval
(
arg_vals
[
0
],
f64
)
?
.to_f64
();
let
i
=
self
.value_to_primval
(
arg_vals
[
1
],
i32
)
?
.to_i64
();
self
.write_primval
(
dest
,
PrimVal
::
from_f64
(
f
.powi
(
i
as
i32
)),
dest_ty
)
?
;
}
"sqrtf32"
=>
{
let
f
=
self
.value_to_primval
(
arg_vals
[
0
],
f32
)
?
.expect_f32
(
"sqrtf32 first arg not f32"
);
self
.write_primval
(
dest
,
PrimVal
::
from_f32
(
f
.sqrt
()))
?
;
let
f
=
self
.value_to_primval
(
arg_vals
[
0
],
f32
)
?
.to_f32
();
self
.write_primval
(
dest
,
PrimVal
::
from_f32
(
f
.sqrt
()),
dest_ty
)
?
;
}
"sqrtf64"
=>
{
let
f
=
self
.value_to_primval
(
arg_vals
[
0
],
f64
)
?
.expect_f64
(
"sqrtf64 first arg not f64"
);
self
.write_primval
(
dest
,
PrimVal
::
from_f64
(
f
.sqrt
()))
?
;
let
f
=
self
.value_to_primval
(
arg_vals
[
0
],
f64
)
?
.to_f64
();
self
.write_primval
(
dest
,
PrimVal
::
from_f64
(
f
.sqrt
()),
dest_ty
)
?
;
}
"size_of"
=>
{
...
...
@@ -337,23 +330,20 @@ pub(super) fn call_intrinsic(
// .expect("size_of intrinsic called on unsized value")
// see https://github.com/rust-lang/rust/pull/37708
let
size
=
self
.type_size
(
ty
)
?
.unwrap_or
(
!
0
)
as
u64
;
let
size_val
=
self
.usize_primval
(
size
);
self
.write_primval
(
dest
,
size_val
)
?
;
self
.write_primval
(
dest
,
PrimVal
::
from_uint
(
size
),
dest_ty
)
?
;
}
"size_of_val"
=>
{
let
ty
=
substs
.type_at
(
0
);
let
(
size
,
_
)
=
self
.size_and_align_of_dst
(
ty
,
arg_vals
[
0
])
?
;
let
size_val
=
self
.usize_primval
(
size
);
self
.write_primval
(
dest
,
size_val
)
?
;
self
.write_primval
(
dest
,
PrimVal
::
from_uint
(
size
),
dest_ty
)
?
;
}
"min_align_of_val"
|
"align_of_val"
=>
{
let
ty
=
substs
.type_at
(
0
);
let
(
_
,
align
)
=
self
.size_and_align_of_dst
(
ty
,
arg_vals
[
0
])
?
;
let
align_val
=
self
.usize_primval
(
align
);
self
.write_primval
(
dest
,
align_val
)
?
;
self
.write_primval
(
dest
,
PrimVal
::
from_uint
(
align
),
dest_ty
)
?
;
}
"type_name"
=>
{
...
...
@@ -365,17 +355,12 @@ pub(super) fn call_intrinsic(
"type_id"
=>
{
let
ty
=
substs
.type_at
(
0
);
let
n
=
self
.tcx
.type_id_hash
(
ty
);
self
.write_primval
(
dest
,
PrimVal
::
new
(
n
,
PrimValKind
::
U64
)
)
?
;
self
.write_primval
(
dest
,
PrimVal
::
new
(
n
),
dest_ty
)
?
;
}
"transmute"
=>
{
let
dest_ty
=
substs
.type_at
(
1
);
let
val
=
match
arg_vals
[
0
]
{
Value
::
ByVal
(
primval
)
=>
Value
::
ByVal
(
self
.transmute_primval
(
primval
,
dest_ty
)
?
),
v
=>
v
,
};
self
.write_value
(
val
,
dest
,
dest_ty
)
?
;
self
.write_value
(
arg_vals
[
0
],
dest
,
dest_ty
)
?
;
}
"uninit"
=>
{
...
...
@@ -511,11 +496,11 @@ fn field_ty(
}
macro_rules!
integer_intrinsic
{
(
$name:expr
,
$val:expr
,
$method:ident
)
=>
({
(
$name:expr
,
$val:expr
,
$
kind:expr
,
$
method:ident
)
=>
({
let
val
=
$val
;
use
primval
::
PrimValKind
::
*
;
let
bits
=
match
val
.
kind
{
let
bits
=
match
$
kind
{
I8
=>
(
val
.bits
as
i8
)
.
$method
()
as
u64
,
U8
=>
(
val
.bits
as
u8
)
.
$method
()
as
u64
,
I16
=>
(
val
.bits
as
i16
)
.
$method
()
as
u64
,
...
...
@@ -527,16 +512,16 @@ fn field_ty(
_
=>
bug!
(
"invalid `{}` argument: {:?}"
,
$name
,
val
),
};
PrimVal
::
new
(
bits
,
val
.kind
)
PrimVal
::
new
(
bits
)
});
}
fn
numeric_intrinsic
(
name
:
&
str
,
val
:
PrimVal
)
->
PrimVal
{
fn
numeric_intrinsic
(
name
:
&
str
,
val
:
PrimVal
,
kind
:
PrimValKind
)
->
PrimVal
{
match
name
{
"bswap"
=>
integer_intrinsic!
(
"bswap"
,
val
,
swap_bytes
),
"ctlz"
=>
integer_intrinsic!
(
"ctlz"
,
val
,
leading_zeros
),
"ctpop"
=>
integer_intrinsic!
(
"ctpop"
,
val
,
count_ones
),
"cttz"
=>
integer_intrinsic!
(
"cttz"
,
val
,
trailing_zeros
),
"bswap"
=>
integer_intrinsic!
(
"bswap"
,
val
,
kind
,
swap_bytes
),
"ctlz"
=>
integer_intrinsic!
(
"ctlz"
,
val
,
kind
,
leading_zeros
),
"ctpop"
=>
integer_intrinsic!
(
"ctpop"
,
val
,
kind
,
count_ones
),
"cttz"
=>
integer_intrinsic!
(
"cttz"
,
val
,
kind
,
trailing_zeros
),
_
=>
bug!
(
"not a numeric intrinsic: {}"
,
name
),
}
}
src/interpreter/terminator/mod.rs
浏览文件 @
49f784a3
...
...
@@ -100,7 +100,10 @@ pub(super) fn eval_terminator(
terminator
.source_info.span
)
?
}
_
=>
return
Err
(
EvalError
::
Unimplemented
(
format!
(
"can't handle callee of type {:?}"
,
func_ty
))),
_
=>
{
let
msg
=
format!
(
"can't handle callee of type {:?}"
,
func_ty
);
return
Err
(
EvalError
::
Unimplemented
(
msg
));
}
}
}
...
...
@@ -126,11 +129,12 @@ pub(super) fn eval_terminator(
return
match
*
msg
{
mir
::
AssertMessage
::
BoundsCheck
{
ref
len
,
ref
index
}
=>
{
let
span
=
terminator
.source_info.span
;
let
len
=
self
.eval_operand_to_primval
(
len
)
.expect
(
"can't eval len"
)
.expect_uint
(
"BoundsCheck len wasn't a uint"
);
let
len
=
self
.eval_operand_to_primval
(
len
)
.expect
(
"can't eval len"
)
.to_u64
();
let
index
=
self
.eval_operand_to_primval
(
index
)
.expect
(
"can't eval index"
)
.
expect_uint
(
"BoundsCheck index wasn't a uint"
);
.
to_u64
(
);
Err
(
EvalError
::
ArrayIndexOutOfBounds
(
span
,
len
,
index
))
},
mir
::
AssertMessage
::
Math
(
ref
err
)
=>
...
...
@@ -194,9 +198,8 @@ fn eval_fn_call(
Abi
::
C
=>
{
let
ty
=
fn_ty
.sig
.0
.output
;
let
size
=
self
.type_size
(
ty
)
?
.expect
(
"function return type cannot be unsized"
);
let
(
ret
,
target
)
=
destination
.unwrap
();
self
.call_c_abi
(
def_id
,
arg_operands
,
ret
,
size
)
?
;
self
.call_c_abi
(
def_id
,
arg_operands
,
ret
,
ty
)
?
;
self
.goto_block
(
target
);
Ok
(())
}
...
...
@@ -303,7 +306,7 @@ fn call_c_abi(
def_id
:
DefId
,
args
:
&
[
mir
::
Operand
<
'tcx
>
],
dest
:
Lvalue
<
'tcx
>
,
dest_
size
:
u64
,
dest_
ty
:
Ty
<
'tcx
>
,
)
->
EvalResult
<
'tcx
,
()
>
{
let
name
=
self
.tcx
.item_name
(
def_id
);
let
attrs
=
self
.tcx
.get_attrs
(
def_id
);
...
...
@@ -325,36 +328,32 @@ fn call_c_abi(
match
&
link_name
[
..
]
{
"__rust_allocate"
=>
{
let
size
=
self
.value_to_primval
(
args
[
0
],
usize
)
?
.expect_uint
(
"__rust_allocate first arg not usize"
);
let
align
=
self
.value_to_primval
(
args
[
1
],
usize
)
?
.expect_uint
(
"__rust_allocate second arg not usize"
);
let
size
=
self
.value_to_primval
(
args
[
0
],
usize
)
?
.to_u64
();
let
align
=
self
.value_to_primval
(
args
[
1
],
usize
)
?
.to_u64
();
let
ptr
=
self
.memory
.allocate
(
size
,
align
)
?
;
self
.write_primval
(
dest
,
PrimVal
::
from_ptr
(
ptr
))
?
;
self
.write_primval
(
dest
,
PrimVal
::
from_ptr
(
ptr
)
,
dest_ty
)
?
;
}
"__rust_deallocate"
=>
{
let
ptr
=
args
[
0
]
.read_ptr
(
&
self
.memory
)
?
;
// FIXME: insert sanity check for size and align?
let
_
old_size
=
self
.value_to_primval
(
args
[
1
],
usize
)
?
.expect_uint
(
"__rust_deallocate second arg not usize"
);
let
_
align
=
self
.value_to_primval
(
args
[
2
],
usize
)
?
.expect_uint
(
"__rust_deallocate third arg not usize"
);
let
_
old_size
=
self
.value_to_primval
(
args
[
1
],
usize
)
?
.to_u64
();
let
_
align
=
self
.value_to_primval
(
args
[
2
],
usize
)
?
.to_u64
();
self
.memory
.deallocate
(
ptr
)
?
;
},
"__rust_reallocate"
=>
{
let
ptr
=
args
[
0
]
.read_ptr
(
&
self
.memory
)
?
;
let
size
=
self
.value_to_primval
(
args
[
2
],
usize
)
?
.
expect_uint
(
"__rust_reallocate third arg not usize"
);
let
align
=
self
.value_to_primval
(
args
[
3
],
usize
)
?
.
expect_uint
(
"__rust_reallocate fourth arg not usize"
);
let
size
=
self
.value_to_primval
(
args
[
2
],
usize
)
?
.
to_u64
(
);
let
align
=
self
.value_to_primval
(
args
[
3
],
usize
)
?
.
to_u64
(
);
let
new_ptr
=
self
.memory
.reallocate
(
ptr
,
size
,
align
)
?
;
self
.write_primval
(
dest
,
PrimVal
::
from_ptr
(
new_ptr
))
?
;
self
.write_primval
(
dest
,
PrimVal
::
from_ptr
(
new_ptr
)
,
dest_ty
)
?
;
}
"memcmp"
=>
{
let
left
=
args
[
0
]
.read_ptr
(
&
self
.memory
)
?
;
let
right
=
args
[
1
]
.read_ptr
(
&
self
.memory
)
?
;
let
n
=
self
.value_to_primval
(
args
[
2
],
usize
)
?
.
expect_uint
(
"__rust_reallocate first arg not usize"
);
let
n
=
self
.value_to_primval
(
args
[
2
],
usize
)
?
.
to_u64
(
);
let
result
=
{
let
left_bytes
=
self
.memory
.read_bytes
(
left
,
n
)
?
;
...
...
@@ -368,7 +367,7 @@ fn call_c_abi(
}
};
self
.write_primval
(
dest
,
PrimVal
::
from_int_with_size
(
result
,
dest_size
)
)
?
;
self
.write_primval
(
dest
,
PrimVal
::
new
(
result
as
u64
),
dest_ty
)
?
;
}
_
=>
{
...
...
src/memory.rs
浏览文件 @
49f784a3
...
...
@@ -11,7 +11,7 @@
use
syntax
::
abi
::
Abi
;
use
error
::{
EvalError
,
EvalResult
};
use
primval
::
PrimVal
;
use
primval
::
{
PrimVal
,
PrimValKind
}
;
////////////////////////////////////////////////////////////////////////////////
// Allocations and pointers
...
...
@@ -559,13 +559,18 @@ pub fn write_ptr(&mut self, dest: Pointer, ptr: Pointer) -> EvalResult<'tcx, ()>
Ok
(())
}
pub
fn
write_primval
(
&
mut
self
,
dest
:
Pointer
,
val
:
PrimVal
)
->
EvalResult
<
'tcx
,
()
>
{
pub
fn
write_primval
(
&
mut
self
,
dest
:
Pointer
,
val
:
PrimVal
,
kind
:
PrimValKind
,
)
->
EvalResult
<
'tcx
,
()
>
{
if
let
Some
(
alloc_id
)
=
val
.relocation
{
return
self
.write_ptr
(
dest
,
Pointer
::
new
(
alloc_id
,
val
.bits
));
}
use
primval
::
PrimValKind
::
*
;
let
(
size
,
bits
)
=
match
val
.
kind
{
let
(
size
,
bits
)
=
match
kind
{
I8
|
U8
|
Bool
=>
(
1
,
val
.bits
as
u8
as
u64
),
I16
|
U16
=>
(
2
,
val
.bits
as
u16
as
u64
),
I32
|
U32
|
F32
|
Char
=>
(
4
,
val
.bits
as
u32
as
u64
),
...
...
src/primval.rs
浏览文件 @
49f784a3
...
...
@@ -38,11 +38,6 @@ pub struct PrimVal {
/// `Allocation` in the `memory` module has a list of relocations, but a `PrimVal` is only
/// large enough to contain one, hence the `Option`.
pub
relocation
:
Option
<
AllocId
>
,
// FIXME(solson): I think we can make this field unnecessary, or at least move it outside of
// this struct. We can either match over `Ty`s or generate simple `PrimVal`s from `Ty`s and
// match over those to decide which operations to perform on `PrimVal`s.
pub
kind
:
PrimValKind
,
}
#[derive(Clone,
Copy,
Debug,
PartialEq)]
...
...
@@ -87,44 +82,40 @@ pub fn from_int_size(size: u64) -> Self {
}
impl
PrimVal
{
pub
fn
new
(
bits
:
u64
,
kind
:
PrimValKind
)
->
Self
{
PrimVal
{
bits
:
bits
,
relocation
:
None
,
kind
:
kind
}
pub
fn
new
(
bits
:
u64
)
->
Self
{
PrimVal
{
bits
:
bits
,
relocation
:
None
}
}
pub
fn
new_with_relocation
(
bits
:
u64
,
kind
:
PrimValKind
,
alloc_id
:
AllocId
)
->
Self
{
PrimVal
{
bits
:
bits
,
relocation
:
Some
(
alloc_id
)
,
kind
:
kind
}
pub
fn
new_with_relocation
(
bits
:
u64
,
alloc_id
:
AllocId
)
->
Self
{
PrimVal
{
bits
:
bits
,
relocation
:
Some
(
alloc_id
)
}
}
pub
fn
from_ptr
(
ptr
:
Pointer
)
->
Self
{
PrimVal
::
new_with_relocation
(
ptr
.offset
as
u64
,
PrimValKind
::
Ptr
,
ptr
.alloc_id
)
}
pub
fn
from_fn_ptr
(
ptr
:
Pointer
)
->
Self
{
PrimVal
::
new_with_relocation
(
ptr
.offset
as
u64
,
PrimValKind
::
FnPtr
,
ptr
.alloc_id
)
PrimVal
::
new_with_relocation
(
ptr
.offset
as
u64
,
ptr
.alloc_id
)
}
pub
fn
from_bool
(
b
:
bool
)
->
Self
{
PrimVal
::
new
(
b
as
u64
,
PrimValKind
::
Bool
)
PrimVal
::
new
(
b
as
u64
)
}
pub
fn
from_char
(
c
:
char
)
->
Self
{
PrimVal
::
new
(
c
as
u64
,
PrimValKind
::
Char
)
PrimVal
::
new
(
c
as
u64
)
}
pub
fn
from_f32
(
f
:
f32
)
->
Self
{
PrimVal
::
new
(
f32_to_bits
(
f
)
,
PrimValKind
::
F32
)
PrimVal
::
new
(
f32_to_bits
(
f
))
}
pub
fn
from_f64
(
f
:
f64
)
->
Self
{
PrimVal
::
new
(
f64_to_bits
(
f
)
,
PrimValKind
::
F64
)
PrimVal
::
new
(
f64_to_bits
(
f
))
}
pub
fn
from_uint
_with_size
(
n
:
u64
,
size
:
u64
)
->
Self
{
PrimVal
::
new
(
n
,
PrimValKind
::
from_uint_size
(
size
)
)
pub
fn
from_uint
(
n
:
u64
)
->
Self
{
PrimVal
::
new
(
n
)
}
pub
fn
from_int
_with_size
(
n
:
i64
,
size
:
u
64
)
->
Self
{
PrimVal
::
new
(
n
as
u64
,
PrimValKind
::
from_int_size
(
size
)
)
pub
fn
from_int
(
n
:
i
64
)
->
Self
{
PrimVal
::
new
(
n
as
u64
)
}
pub
fn
to_f32
(
self
)
->
f32
{
...
...
@@ -144,31 +135,27 @@ pub fn to_ptr(self) -> Pointer {
}
pub
fn
try_as_uint
<
'tcx
>
(
self
)
->
EvalResult
<
'tcx
,
u64
>
{
self
.to_ptr
()
.to_int
()
.map
(|
val
|
val
as
u64
)
self
.to_ptr
()
.to_int
()
.map
(|
val
|
val
)
}
pub
fn
expect_uint
(
self
,
error_msg
:
&
str
)
->
u64
{
if
let
Ok
(
int
)
=
self
.try_as_uint
()
{
return
int
;
}
use
self
::
PrimValKind
::
*
;
match
self
.kind
{
U8
|
U16
|
U32
|
U64
=>
self
.bits
,
_
=>
bug!
(
"{}"
,
error_msg
),
pub
fn
to_u64
(
self
)
->
u64
{
if
let
Some
(
ptr
)
=
self
.try_as_ptr
()
{
return
ptr
.to_int
()
.expect
(
"non abstract ptr"
)
as
u64
;
}
self
.bits
}
pub
fn
expect_int
(
self
,
error_msg
:
&
str
)
->
i64
{
if
let
Ok
(
int
)
=
self
.try_as_uint
()
{
return
int
as
i64
;
pub
fn
to_i64
(
self
)
->
i64
{
if
let
Some
(
ptr
)
=
self
.try_as_ptr
()
{
return
ptr
.to_int
()
.expect
(
"non abstract ptr"
)
as
i64
;
}
self
.bits
as
i64
}
use
self
::
PrimValKind
::
*
;
match
self
.kind
{
I8
|
I16
|
I32
|
I64
=>
self
.bits
as
i64
,
_
=>
bug!
(
"{}"
,
error_msg
),
}
pub
fn
try_as_ptr
(
self
)
->
Option
<
Pointer
>
{
self
.relocation
.map
(|
alloc_id
|
{
Pointer
::
new
(
alloc_id
,
self
.bits
)
})
}
pub
fn
try_as_bool
<
'tcx
>
(
self
)
->
EvalResult
<
'tcx
,
bool
>
{
...
...
@@ -179,19 +166,6 @@ pub fn try_as_bool<'tcx>(self) -> EvalResult<'tcx, bool> {
}
}
pub
fn
expect_f32
(
self
,
error_msg
:
&
str
)
->
f32
{
match
self
.kind
{
PrimValKind
::
F32
=>
bits_to_f32
(
self
.bits
),
_
=>
bug!
(
"{}"
,
error_msg
),
}
}
pub
fn
expect_f64
(
self
,
error_msg
:
&
str
)
->
f64
{
match
self
.kind
{
PrimValKind
::
F32
=>
bits_to_f64
(
self
.bits
),
_
=>
bug!
(
"{}"
,
error_msg
),
}
}
}
////////////////////////////////////////////////////////////////////////////////
...
...
@@ -199,9 +173,9 @@ pub fn expect_f64(self, error_msg: &str) -> f64 {
////////////////////////////////////////////////////////////////////////////////
macro_rules!
overflow
{
(
$
kind:expr
,
$
op:ident
,
$l:expr
,
$r:expr
)
=>
({
(
$op:ident
,
$l:expr
,
$r:expr
)
=>
({
let
(
val
,
overflowed
)
=
$l
.
$op
(
$r
);
let
primval
=
PrimVal
::
new
(
val
as
u64
,
$kind
);
let
primval
=
PrimVal
::
new
(
val
as
u64
);
Ok
((
primval
,
overflowed
))
})
}
...
...
@@ -211,14 +185,14 @@ pub fn expect_f64(self, error_msg: &str) -> f64 {
let
l
=
$l
;
let
r
=
$r
;
match
$kind
{
I8
=>
overflow!
(
I8
,
$int_op
,
l
as
i8
,
r
as
i8
),
I16
=>
overflow!
(
I16
,
$int_op
,
l
as
i16
,
r
as
i16
),
I32
=>
overflow!
(
I32
,
$int_op
,
l
as
i32
,
r
as
i32
),
I64
=>
overflow!
(
I64
,
$int_op
,
l
as
i64
,
r
as
i64
),
U8
=>
overflow!
(
U8
,
$int_op
,
l
as
u8
,
r
as
u8
),
U16
=>
overflow!
(
U16
,
$int_op
,
l
as
u16
,
r
as
u16
),
U32
=>
overflow!
(
U32
,
$int_op
,
l
as
u32
,
r
as
u32
),
U64
=>
overflow!
(
U64
,
$int_op
,
l
as
u64
,
r
as
u64
),
I8
=>
overflow!
(
$int_op
,
l
as
i8
,
r
as
i8
),
I16
=>
overflow!
(
$int_op
,
l
as
i16
,
r
as
i16
),
I32
=>
overflow!
(
$int_op
,
l
as
i32
,
r
as
i32
),
I64
=>
overflow!
(
$int_op
,
l
as
i64
,
r
as
i64
),
U8
=>
overflow!
(
$int_op
,
l
as
u8
,
r
as
u8
),
U16
=>
overflow!
(
$int_op
,
l
as
u16
,
r
as
u16
),
U32
=>
overflow!
(
$int_op
,
l
as
u32
,
r
as
u32
),
U64
=>
overflow!
(
$int_op
,
l
as
u64
,
r
as
u64
),
_
=>
bug!
(
"int_arithmetic should only be called on int primvals"
),
}
})
...
...
@@ -229,37 +203,37 @@ pub fn expect_f64(self, error_msg: &str) -> f64 {
let
l
=
$l
;
let
r
=
$r
;
match
$kind
{
I8
=>
overflow!
(
I8
,
$int_op
,
l
as
i8
,
r
),
I16
=>
overflow!
(
I16
,
$int_op
,
l
as
i16
,
r
),
I32
=>
overflow!
(
I32
,
$int_op
,
l
as
i32
,
r
),
I64
=>
overflow!
(
I64
,
$int_op
,
l
as
i64
,
r
),
U8
=>
overflow!
(
U8
,
$int_op
,
l
as
u8
,
r
),
U16
=>
overflow!
(
U16
,
$int_op
,
l
as
u16
,
r
),
U32
=>
overflow!
(
U32
,
$int_op
,
l
as
u32
,
r
),
U64
=>
overflow!
(
U64
,
$int_op
,
l
as
u64
,
r
),
I8
=>
overflow!
(
$int_op
,
l
as
i8
,
r
),
I16
=>
overflow!
(
$int_op
,
l
as
i16
,
r
),
I32
=>
overflow!
(
$int_op
,
l
as
i32
,
r
),
I64
=>
overflow!
(
$int_op
,
l
as
i64
,
r
),
U8
=>
overflow!
(
$int_op
,
l
as
u8
,
r
),
U16
=>
overflow!
(
$int_op
,
l
as
u16
,
r
),
U32
=>
overflow!
(
$int_op
,
l
as
u32
,
r
),
U64
=>
overflow!
(
$int_op
,
l
as
u64
,
r
),
_
=>
bug!
(
"int_shift should only be called on int primvals"
),
}
})
}
macro_rules!
float_arithmetic
{
(
$
kind:expr
,
$
from_bits:ident
,
$to_bits:ident
,
$float_op:tt
,
$l:expr
,
$r:expr
)
=>
({
(
$from_bits:ident
,
$to_bits:ident
,
$float_op:tt
,
$l:expr
,
$r:expr
)
=>
({
let
l
=
$from_bits
(
$l
);
let
r
=
$from_bits
(
$r
);
let
bits
=
$to_bits
(
l
$float_op
r
);
PrimVal
::
new
(
bits
,
$kind
)
PrimVal
::
new
(
bits
)
})
}
macro_rules!
f32_arithmetic
{
(
$float_op:tt
,
$l:expr
,
$r:expr
)
=>
(
float_arithmetic!
(
F32
,
bits_to_f32
,
f32_to_bits
,
$float_op
,
$l
,
$r
)
float_arithmetic!
(
bits_to_f32
,
f32_to_bits
,
$float_op
,
$l
,
$r
)
)
}
macro_rules!
f64_arithmetic
{
(
$float_op:tt
,
$l:expr
,
$r:expr
)
=>
(
float_arithmetic!
(
F64
,
bits_to_f64
,
f64_to_bits
,
$float_op
,
$l
,
$r
)
float_arithmetic!
(
bits_to_f64
,
f64_to_bits
,
$float_op
,
$l
,
$r
)
)
}
...
...
@@ -267,7 +241,9 @@ pub fn expect_f64(self, error_msg: &str) -> f64 {
pub
fn
binary_op
<
'tcx
>
(
bin_op
:
mir
::
BinOp
,
left
:
PrimVal
,
right
:
PrimVal
left_kind
:
PrimValKind
,
right
:
PrimVal
,
right_kind
:
PrimValKind
,
)
->
EvalResult
<
'tcx
,
(
PrimVal
,
bool
)
>
{
use
rustc
::
mir
::
BinOp
::
*
;
use
self
::
PrimValKind
::
*
;
...
...
@@ -288,7 +264,7 @@ pub fn binary_op<'tcx>(
// These are the maximum values a bitshift RHS could possibly have. For example, u16
// can be bitshifted by 0..16, so masking with 0b1111 (16 - 1) will ensure we are in
// that range.
let
type_bits
:
u32
=
match
left
.
kind
{
let
type_bits
:
u32
=
match
left
_
kind
{
I8
|
U8
=>
8
,
I16
|
U16
=>
16
,
I32
|
U32
=>
32
,
...
...
@@ -301,18 +277,18 @@ pub fn binary_op<'tcx>(
let
r
=
(
right
.bits
as
u32
)
&
(
type_bits
-
1
);
return
match
bin_op
{
Shl
=>
int_shift!
(
left
.
kind
,
overflowing_shl
,
l
,
r
),
Shr
=>
int_shift!
(
left
.
kind
,
overflowing_shr
,
l
,
r
),
Shl
=>
int_shift!
(
left
_
kind
,
overflowing_shl
,
l
,
r
),
Shr
=>
int_shift!
(
left
_
kind
,
overflowing_shr
,
l
,
r
),
_
=>
bug!
(
"it has already been checked that this is a shift op"
),
};
}
if
left
.kind
!=
right
.
kind
{
if
left
_kind
!=
right_
kind
{
let
msg
=
format!
(
"unimplemented binary op: {:?}, {:?}, {:?}"
,
left
,
right
,
bin_op
);
return
Err
(
EvalError
::
Unimplemented
(
msg
));
}
let
val
=
match
(
bin_op
,
left
.
kind
)
{
let
val
=
match
(
bin_op
,
left
_
kind
)
{
(
Eq
,
F32
)
=>
PrimVal
::
from_bool
(
bits_to_f32
(
l
)
==
bits_to_f32
(
r
)),
(
Ne
,
F32
)
=>
PrimVal
::
from_bool
(
bits_to_f32
(
l
)
!=
bits_to_f32
(
r
)),
(
Lt
,
F32
)
=>
PrimVal
::
from_bool
(
bits_to_f32
(
l
)
<
bits_to_f32
(
r
)),
...
...
@@ -346,9 +322,9 @@ pub fn binary_op<'tcx>(
(
Gt
,
_
)
=>
PrimVal
::
from_bool
(
l
>
r
),
(
Ge
,
_
)
=>
PrimVal
::
from_bool
(
l
>=
r
),
(
BitOr
,
k
)
=>
PrimVal
::
new
(
l
|
r
,
k
),
(
BitAnd
,
k
)
=>
PrimVal
::
new
(
l
&
r
,
k
),
(
BitXor
,
k
)
=>
PrimVal
::
new
(
l
^
r
,
k
),
(
BitOr
,
_
)
=>
PrimVal
::
new
(
l
|
r
),
(
BitAnd
,
_
)
=>
PrimVal
::
new
(
l
&
r
),
(
BitXor
,
_
)
=>
PrimVal
::
new
(
l
^
r
),
(
Add
,
k
)
if
k
.is_int
()
=>
return
int_arithmetic!
(
k
,
overflowing_add
,
l
,
r
),
(
Sub
,
k
)
if
k
.is_int
()
=>
return
int_arithmetic!
(
k
,
overflowing_sub
,
l
,
r
),
...
...
@@ -378,11 +354,15 @@ fn unrelated_ptr_ops<'tcx>(bin_op: mir::BinOp, left: Pointer, right: Pointer) ->
}
}
pub
fn
unary_op
<
'tcx
>
(
un_op
:
mir
::
UnOp
,
val
:
PrimVal
)
->
EvalResult
<
'tcx
,
PrimVal
>
{
pub
fn
unary_op
<
'tcx
>
(
un_op
:
mir
::
UnOp
,
val
:
PrimVal
,
val_kind
:
PrimValKind
,
)
->
EvalResult
<
'tcx
,
PrimVal
>
{
use
rustc
::
mir
::
UnOp
::
*
;
use
self
::
PrimValKind
::
*
;
let
bits
=
match
(
un_op
,
val
.
kind
)
{
let
bits
=
match
(
un_op
,
val
_
kind
)
{
(
Not
,
Bool
)
=>
!
bits_to_bool
(
val
.bits
)
as
u64
,
(
Not
,
U8
)
=>
!
(
val
.bits
as
u8
)
as
u64
,
...
...
@@ -409,5 +389,5 @@ pub fn unary_op<'tcx>(un_op: mir::UnOp, val: PrimVal) -> EvalResult<'tcx, PrimVa
}
};
Ok
(
PrimVal
::
new
(
bits
,
val
.kind
))
Ok
(
PrimVal
::
new
(
bits
))
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录