Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
ff080d38
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,发现更多精彩内容 >>
提交
ff080d38
编写于
12月 16, 2017
作者:
E
Eduard-Mihai Burtescu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
miri: track the Align instead of packedness in PtrAndAlign.
上级
5cab0bf0
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
152 addition
and
182 deletion
+152
-182
src/librustc/mir/interpret/value.rs
src/librustc/mir/interpret/value.rs
+3
-11
src/librustc_mir/interpret/const_eval.rs
src/librustc_mir/interpret/const_eval.rs
+13
-13
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/eval_context.rs
+70
-93
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/memory.rs
+32
-34
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/place.rs
+27
-23
src/librustc_mir/interpret/step.rs
src/librustc_mir/interpret/step.rs
+2
-2
src/librustc_mir/interpret/terminator/mod.rs
src/librustc_mir/interpret/terminator/mod.rs
+5
-6
未找到文件。
src/librustc/mir/interpret/value.rs
浏览文件 @
ff080d38
#![allow(unknown_lints)]
use
ty
::
layout
::
HasDataLayout
;
use
ty
::
layout
::
{
Align
,
HasDataLayout
}
;
use
super
::{
EvalResult
,
MemoryPointer
,
PointerArithmetic
};
use
syntax
::
ast
::
FloatTy
;
...
...
@@ -9,8 +9,7 @@
#[derive(Copy,
Clone,
Debug)]
pub
struct
PtrAndAlign
{
pub
ptr
:
Pointer
,
/// Remember whether this place is *supposed* to be aligned.
pub
aligned
:
bool
,
pub
align
:
Align
,
}
impl
PtrAndAlign
{
...
...
@@ -20,7 +19,7 @@ pub fn to_ptr<'tcx>(self) -> EvalResult<'tcx, MemoryPointer> {
pub
fn
offset
<
'tcx
,
C
:
HasDataLayout
>
(
self
,
i
:
u64
,
cx
:
C
)
->
EvalResult
<
'tcx
,
Self
>
{
Ok
(
PtrAndAlign
{
ptr
:
self
.ptr
.offset
(
i
,
cx
)
?
,
align
ed
:
self
.aligned
,
align
:
self
.align
,
})
}
}
...
...
@@ -182,13 +181,6 @@ pub enum PrimValKind {
Char
,
}
impl
<
'a
,
'tcx
:
'a
>
Value
{
#[inline]
pub
fn
by_ref
(
ptr
:
Pointer
)
->
Self
{
Value
::
ByRef
(
PtrAndAlign
{
ptr
,
aligned
:
true
})
}
}
impl
<
'tcx
>
PrimVal
{
pub
fn
from_u128
(
n
:
u128
)
->
Self
{
PrimVal
::
Bytes
(
n
)
...
...
src/librustc_mir/interpret/const_eval.rs
浏览文件 @
ff080d38
...
...
@@ -77,7 +77,7 @@ pub fn eval_body<'a, 'tcx>(
instance
,
mir
.span
,
mir
,
Place
::
from_ptr
(
ptr
),
Place
::
from_ptr
(
ptr
,
layout
.align
),
cleanup
.clone
(),
)
?
;
...
...
@@ -357,10 +357,11 @@ pub fn const_eval_provider<'a, 'tcx>(
(
_
,
Err
(
err
))
=>
Err
(
err
),
(
Ok
((
miri_val
,
miri_ty
)),
Ok
(
ctfe
))
=>
{
let
mut
ecx
=
mk_eval_cx
(
tcx
,
instance
,
key
.param_env
)
.unwrap
();
check_ctfe_against_miri
(
&
mut
ecx
,
PtrAndAlign
{
let
miri_ptr
=
PtrAndAlign
{
ptr
:
miri_val
,
aligned
:
true
},
miri_ty
,
ctfe
.val
);
align
:
ecx
.layout_of
(
miri_ty
)
.unwrap
()
.align
};
check_ctfe_against_miri
(
&
mut
ecx
,
miri_ptr
,
miri_ty
,
ctfe
.val
);
Ok
(
ctfe
)
}
}
...
...
@@ -380,7 +381,7 @@ fn check_ctfe_against_miri<'a, 'tcx>(
use
rustc
::
ty
::
TypeVariants
::
*
;
match
miri_ty
.sty
{
TyInt
(
int_ty
)
=>
{
let
value
=
ecx
.read_
maybe_aligned
(
miri_val
.aligned
,
|
ectx
|
{
let
value
=
ecx
.read_
with_align
(
miri_val
.align
,
|
ectx
|
{
ectx
.try_read_value
(
miri_val
.ptr
,
miri_ty
)
});
let
prim
=
get_prim
(
ecx
,
value
);
...
...
@@ -391,7 +392,7 @@ fn check_ctfe_against_miri<'a, 'tcx>(
assert_eq!
(
c
,
ctfe
,
"miri evaluated to {:?}, but ctfe yielded {:?}"
,
c
,
ctfe
);
},
TyUint
(
uint_ty
)
=>
{
let
value
=
ecx
.read_
maybe_aligned
(
miri_val
.aligned
,
|
ectx
|
{
let
value
=
ecx
.read_
with_align
(
miri_val
.align
,
|
ectx
|
{
ectx
.try_read_value
(
miri_val
.ptr
,
miri_ty
)
});
let
prim
=
get_prim
(
ecx
,
value
);
...
...
@@ -402,7 +403,7 @@ fn check_ctfe_against_miri<'a, 'tcx>(
assert_eq!
(
c
,
ctfe
,
"miri evaluated to {:?}, but ctfe yielded {:?}"
,
c
,
ctfe
);
},
TyFloat
(
ty
)
=>
{
let
value
=
ecx
.read_
maybe_aligned
(
miri_val
.aligned
,
|
ectx
|
{
let
value
=
ecx
.read_
with_align
(
miri_val
.align
,
|
ectx
|
{
ectx
.try_read_value
(
miri_val
.ptr
,
miri_ty
)
});
let
prim
=
get_prim
(
ecx
,
value
);
...
...
@@ -410,7 +411,7 @@ fn check_ctfe_against_miri<'a, 'tcx>(
assert_eq!
(
f
,
ctfe
,
"miri evaluated to {:?}, but ctfe yielded {:?}"
,
f
,
ctfe
);
},
TyBool
=>
{
let
value
=
ecx
.read_
maybe_aligned
(
miri_val
.aligned
,
|
ectx
|
{
let
value
=
ecx
.read_
with_align
(
miri_val
.align
,
|
ectx
|
{
ectx
.try_read_value
(
miri_val
.ptr
,
miri_ty
)
});
let
bits
=
get_prim
(
ecx
,
value
);
...
...
@@ -421,7 +422,7 @@ fn check_ctfe_against_miri<'a, 'tcx>(
assert_eq!
(
b
,
ctfe
,
"miri evaluated to {:?}, but ctfe yielded {:?}"
,
b
,
ctfe
);
},
TyChar
=>
{
let
value
=
ecx
.read_
maybe_aligned
(
miri_val
.aligned
,
|
ectx
|
{
let
value
=
ecx
.read_
with_align
(
miri_val
.align
,
|
ectx
|
{
ectx
.try_read_value
(
miri_val
.ptr
,
miri_ty
)
});
let
bits
=
get_prim
(
ecx
,
value
);
...
...
@@ -435,7 +436,7 @@ fn check_ctfe_against_miri<'a, 'tcx>(
}
},
TyStr
=>
{
let
value
=
ecx
.read_
maybe_aligned
(
miri_val
.aligned
,
|
ectx
|
{
let
value
=
ecx
.read_
with_align
(
miri_val
.align
,
|
ectx
|
{
ectx
.try_read_value
(
miri_val
.ptr
,
miri_ty
)
});
if
let
Ok
(
Some
(
Value
::
ByValPair
(
PrimVal
::
Ptr
(
ptr
),
PrimVal
::
Bytes
(
len
))))
=
value
{
...
...
@@ -522,8 +523,7 @@ fn check_ctfe_against_miri<'a, 'tcx>(
Field
::
new
(
field
),
layout
,
)
.unwrap
();
let
ptr
=
place
.to_ptr_extra_aligned
()
.0
;
check_ctfe_against_miri
(
ecx
,
ptr
,
elem
.ty
,
elem
.val
);
check_ctfe_against_miri
(
ecx
,
place
.to_ptr_align
(),
elem
.ty
,
elem
.val
);
}
},
TySlice
(
_
)
=>
bug!
(
"miri produced a slice?"
),
...
...
@@ -543,7 +543,7 @@ fn check_ctfe_against_miri<'a, 'tcx>(
// should be fine
TyFnDef
(
..
)
=>
{}
TyFnPtr
(
_
)
=>
{
let
value
=
ecx
.read_
maybe_aligned
(
miri_val
.aligned
,
|
ectx
|
{
let
value
=
ecx
.read_
with_align
(
miri_val
.align
,
|
ectx
|
{
ectx
.try_read_value
(
miri_val
.ptr
,
miri_ty
)
});
let
ptr
=
match
value
{
...
...
src/librustc_mir/interpret/eval_context.rs
浏览文件 @
ff080d38
...
...
@@ -241,7 +241,7 @@ pub fn str_to_value(&mut self, s: &str) -> EvalResult<'tcx, Value> {
))
}
pub
(
super
)
fn
const_to_value
(
&
mut
self
,
const_val
:
&
ConstVal
<
'tcx
>
)
->
EvalResult
<
'tcx
,
Value
>
{
pub
(
super
)
fn
const_to_value
(
&
mut
self
,
const_val
:
&
ConstVal
<
'tcx
>
,
ty
:
Ty
<
'tcx
>
)
->
EvalResult
<
'tcx
,
Value
>
{
use
rustc
::
middle
::
const_val
::
ConstVal
::
*
;
let
primval
=
match
*
const_val
{
...
...
@@ -264,7 +264,7 @@ pub(super) fn const_to_value(&mut self, const_val: &ConstVal<'tcx>) -> EvalResul
return
Ok
(
self
.read_global_as_value
(
GlobalId
{
instance
,
promoted
:
None
,
}));
}
,
self
.layout_of
(
ty
)
?
));
}
Aggregate
(
..
)
|
...
...
@@ -637,7 +637,7 @@ pub(super) fn eval_rvalue_into_place(
let
src
=
self
.eval_place
(
place
)
?
;
// We ignore the alignment of the place here -- special handling for packed structs ends
// at the `&` operator.
let
(
ptr
,
extra
)
=
self
.force_allocation
(
src
)
?
.to_ptr_
extra_aligned
();
let
(
ptr
,
extra
)
=
self
.force_allocation
(
src
)
?
.to_ptr_
align_extra
();
let
val
=
match
extra
{
PlaceExtra
::
None
=>
ptr
.ptr
.to_value
(),
...
...
@@ -677,7 +677,9 @@ pub(super) fn eval_rvalue_into_place(
match
kind
{
Unsize
=>
{
let
src
=
self
.eval_operand
(
operand
)
?
;
self
.unsize_into
(
src
.value
,
src
.ty
,
dest
,
dest_ty
)
?
;
let
src_layout
=
self
.layout_of
(
src
.ty
)
?
;
let
dst_layout
=
self
.layout_of
(
dest_ty
)
?
;
self
.unsize_into
(
src
.value
,
src_layout
,
dest
,
dst_layout
)
?
;
}
Misc
=>
{
...
...
@@ -830,13 +832,13 @@ pub fn eval_operand(&mut self, op: &mir::Operand<'tcx>) -> EvalResult<'tcx, ValT
use
rustc
::
mir
::
Literal
;
let
mir
::
Constant
{
ref
literal
,
..
}
=
**
constant
;
let
value
=
match
*
literal
{
Literal
::
Value
{
ref
value
}
=>
self
.const_to_value
(
&
value
.val
)
?
,
Literal
::
Value
{
ref
value
}
=>
self
.const_to_value
(
&
value
.val
,
ty
)
?
,
Literal
::
Promoted
{
index
}
=>
{
self
.read_global_as_value
(
GlobalId
{
instance
:
self
.frame
()
.instance
,
promoted
:
Some
(
index
),
})
}
,
self
.layout_of
(
ty
)
?
)
}
};
...
...
@@ -948,10 +950,10 @@ pub(crate) fn write_discriminant_value(
Ok
(())
}
pub
fn
read_global_as_value
(
&
self
,
gid
:
GlobalId
)
->
Value
{
pub
fn
read_global_as_value
(
&
self
,
gid
:
GlobalId
,
layout
:
TyLayout
)
->
Value
{
Value
::
ByRef
(
PtrAndAlign
{
ptr
:
self
.tcx.interpret_interner
.borrow
()
.get_cached
(
gid
)
.expect
(
"global not cached"
),
align
ed
:
true
align
:
layout
.align
})
}
...
...
@@ -979,11 +981,15 @@ pub fn force_allocation(&mut self, place: Place) -> EvalResult<'tcx, Place> {
Some
(
val
)
=>
{
let
ty
=
self
.stack
[
frame
]
.mir.local_decls
[
local
]
.ty
;
let
ty
=
self
.monomorphize
(
ty
,
self
.stack
[
frame
]
.instance.substs
);
let
layout
=
self
.layout_of
(
ty
)
?
;
let
ptr
=
self
.alloc_ptr
(
ty
)
?
;
self
.stack
[
frame
]
.locals
[
local
.index
()
-
1
]
=
Some
(
Value
::
by_ref
(
ptr
.into
()));
// it stays live
Some
(
Value
::
ByRef
(
PtrAndAlign
{
ptr
:
ptr
.into
(),
align
:
layout
.align
}));
// it stays live
self
.write_value_to_ptr
(
val
,
ptr
.into
(),
ty
)
?
;
Place
::
from_ptr
(
ptr
)
Place
::
from_ptr
(
ptr
,
layout
.align
)
}
}
}
...
...
@@ -999,8 +1005,8 @@ pub fn follow_by_ref_value(
ty
:
Ty
<
'tcx
>
,
)
->
EvalResult
<
'tcx
,
Value
>
{
match
value
{
Value
::
ByRef
(
PtrAndAlign
{
ptr
,
align
ed
})
=>
{
self
.read_
maybe_aligned
(
aligned
,
|
ectx
|
ectx
.read_value
(
ptr
,
ty
))
Value
::
ByRef
(
PtrAndAlign
{
ptr
,
align
})
=>
{
self
.read_
with_align
(
align
,
|
ectx
|
ectx
.read_value
(
ptr
,
ty
))
}
other
=>
Ok
(
other
),
}
...
...
@@ -1056,14 +1062,12 @@ pub fn write_value(
match
dest
{
Place
::
Ptr
{
ptr
:
PtrAndAlign
{
ptr
,
align
ed
},
ptr
:
PtrAndAlign
{
ptr
,
align
},
extra
,
}
=>
{
assert_eq!
(
extra
,
PlaceExtra
::
None
);
self
.write_maybe_aligned_mut
(
aligned
,
|
ectx
|
ectx
.write_value_to_ptr
(
src_val
,
ptr
,
dest_ty
),
)
self
.write_with_align_mut
(
align
,
|
ectx
|
ectx
.write_value_to_ptr
(
src_val
,
ptr
,
dest_ty
))
}
Place
::
Local
{
frame
,
local
}
=>
{
...
...
@@ -1088,7 +1092,7 @@ fn write_value_possibly_by_val<F: FnOnce(&mut Self, Value) -> EvalResult<'tcx>>(
)
->
EvalResult
<
'tcx
>
{
if
let
Value
::
ByRef
(
PtrAndAlign
{
ptr
:
dest_ptr
,
align
ed
,
align
,
})
=
old_dest_val
{
// If the value is already `ByRef` (that is, backed by an `Allocation`),
...
...
@@ -1098,13 +1102,13 @@ fn write_value_possibly_by_val<F: FnOnce(&mut Self, Value) -> EvalResult<'tcx>>(
//
// Thus, it would be an error to replace the `ByRef` with a `ByVal`, unless we
// knew for certain that there were no outstanding pointers to this allocation.
self
.write_
maybe_aligned_mut
(
aligned
,
|
ectx
|
{
self
.write_
with_align_mut
(
align
,
|
ectx
|
{
ectx
.write_value_to_ptr
(
src_val
,
dest_ptr
,
dest_ty
)
})
?
;
}
else
if
let
Value
::
ByRef
(
PtrAndAlign
{
ptr
:
src_ptr
,
align
ed
,
align
,
})
=
src_val
{
// If the value is not `ByRef`, then we know there are no pointers to it
...
...
@@ -1118,13 +1122,17 @@ fn write_value_possibly_by_val<F: FnOnce(&mut Self, Value) -> EvalResult<'tcx>>(
// It is a valid optimization to attempt reading a primitive value out of the
// source and write that into the destination without making an allocation, so
// we do so here.
self
.read_
maybe_aligned_mut
(
aligned
,
|
ectx
|
{
self
.read_
with_align_mut
(
align
,
|
ectx
|
{
if
let
Ok
(
Some
(
src_val
))
=
ectx
.try_read_value
(
src_ptr
,
dest_ty
)
{
write_dest
(
ectx
,
src_val
)
?
;
}
else
{
let
dest_ptr
=
ectx
.alloc_ptr
(
dest_ty
)
?
.into
();
ectx
.copy
(
src_ptr
,
dest_ptr
,
dest_ty
)
?
;
write_dest
(
ectx
,
Value
::
by_ref
(
dest_ptr
))
?
;
let
layout
=
ectx
.layout_of
(
dest_ty
)
?
;
write_dest
(
ectx
,
Value
::
ByRef
(
PtrAndAlign
{
ptr
:
dest_ptr
,
align
:
layout
.align
}))
?
;
}
Ok
(())
})
?
;
...
...
@@ -1145,8 +1153,8 @@ pub fn write_value_to_ptr(
)
->
EvalResult
<
'tcx
>
{
trace!
(
"write_value_to_ptr: {:#?}"
,
value
);
match
value
{
Value
::
ByRef
(
PtrAndAlign
{
ptr
,
align
ed
})
=>
{
self
.read_
maybe_aligned_mut
(
aligned
,
|
ectx
|
ectx
.copy
(
ptr
,
dest
,
dest_ty
))
Value
::
ByRef
(
PtrAndAlign
{
ptr
,
align
})
=>
{
self
.read_
with_align_mut
(
align
,
|
ectx
|
ectx
.copy
(
ptr
,
dest
,
dest_ty
))
}
Value
::
ByVal
(
primval
)
=>
{
let
layout
=
self
.layout_of
(
dest_ty
)
?
;
...
...
@@ -1441,92 +1449,62 @@ fn unsize_into_ptr(
fn
unsize_into
(
&
mut
self
,
src
:
Value
,
src_
ty
:
Ty
<
'tcx
>
,
src_
layout
:
TyLayout
<
'tcx
>
,
dst
:
Place
,
dst_
ty
:
Ty
<
'tcx
>
,
dst_
layout
:
TyLayout
<
'tcx
>
,
)
->
EvalResult
<
'tcx
>
{
let
src_layout
=
self
.layout_of
(
src_ty
)
?
;
let
dst_layout
=
self
.layout_of
(
dst_ty
)
?
;
match
(
&
src_ty
.sty
,
&
dst_ty
.sty
)
{
match
(
&
src_layout
.ty.sty
,
&
dst_layout
.ty.sty
)
{
(
&
ty
::
TyRef
(
_
,
ref
s
),
&
ty
::
TyRef
(
_
,
ref
d
))
|
(
&
ty
::
TyRef
(
_
,
ref
s
),
&
ty
::
TyRawPtr
(
ref
d
))
|
(
&
ty
::
TyRawPtr
(
ref
s
),
&
ty
::
TyRawPtr
(
ref
d
))
=>
{
self
.unsize_into_ptr
(
src
,
src_
ty
,
dst
,
dst_
ty
,
s
.ty
,
d
.ty
)
self
.unsize_into_ptr
(
src
,
src_
layout
.ty
,
dst
,
dst_layout
.
ty
,
s
.ty
,
d
.ty
)
}
(
&
ty
::
TyAdt
(
def_a
,
_
),
&
ty
::
TyAdt
(
def_b
,
_
))
=>
{
assert_eq!
(
def_a
,
def_b
);
if
def_a
.is_box
()
||
def_b
.is_box
()
{
if
!
def_a
.is_box
()
||
!
def_b
.is_box
()
{
panic!
(
"invalid unsizing between {:?} -> {:?}"
,
src_ty
,
dst_ty
);
bug!
(
"invalid unsizing between {:?} -> {:?}"
,
src_layout
,
dst_layout
);
}
return
self
.unsize_into_ptr
(
src
,
src_ty
,
src_
layout
.
ty
,
dst
,
dst_ty
,
src_ty
.boxed_ty
(),
dst_ty
.boxed_ty
(),
dst_
layout
.
ty
,
src_
layout
.
ty
.boxed_ty
(),
dst_
layout
.
ty
.boxed_ty
(),
);
}
if
self
.ty_to_primval_kind
(
src_ty
)
.is_ok
()
{
// TODO: We ignore the packed flag here
let
sty
=
src_layout
.field
(
&
self
,
0
)
?
.ty
;
let
dty
=
dst_layout
.field
(
&
self
,
0
)
?
.ty
;
return
self
.unsize_into
(
src
,
sty
,
dst
,
dty
);
}
// unsizing of generic struct with pointer fields
// Example: `Arc<T>` -> `Arc<Trait>`
// here we need to increase the size of every &T thin ptr field to a fat ptr
assert_eq!
(
def_a
,
def_b
);
let
src_ptr
=
match
src
{
Value
::
ByRef
(
PtrAndAlign
{
ptr
,
aligned
:
true
})
=>
ptr
,
// the entire struct is just a pointer
Value
::
ByVal
(
_
)
=>
{
for
i
in
0
..
src_layout
.fields
.count
()
{
let
src_field
=
src_layout
.field
(
&
self
,
i
)
?
;
let
dst_field
=
dst_layout
.field
(
&
self
,
i
)
?
;
if
dst_layout
.is_zst
()
{
continue
;
}
assert_eq!
(
src_layout
.fields
.offset
(
i
)
.bytes
(),
0
);
assert_eq!
(
dst_layout
.fields
.offset
(
i
)
.bytes
(),
0
);
assert_eq!
(
src_field
.size
,
src_layout
.size
);
assert_eq!
(
dst_field
.size
,
dst_layout
.size
);
return
self
.unsize_into
(
src
,
src_field
.ty
,
dst
,
dst_field
.ty
,
);
}
bug!
(
"by val unsize into where the value doesn't cover the entire type"
)
}
// TODO: Is it possible for unaligned pointers to occur here?
_
=>
bug!
(
"expected aligned pointer, got {:?}"
,
src
),
};
// FIXME(solson)
let
dst
=
self
.force_allocation
(
dst
)
?
.to_ptr
()
?
;
for
i
in
0
..
src_layout
.fields
.count
()
{
let
src_field
=
src_layout
.field
(
&
self
,
i
)
?
;
let
dst_field
=
dst_layout
.field
(
&
self
,
i
)
?
;
let
(
dst_f_place
,
dst_field
)
=
self
.place_field
(
dst
,
mir
::
Field
::
new
(
i
),
dst_layout
)
?
;
if
dst_field
.is_zst
()
{
continue
;
}
let
src_field_offset
=
src_layout
.fields
.offset
(
i
)
.bytes
();
let
dst_field_offset
=
dst_layout
.fields
.offset
(
i
)
.bytes
();
let
src_f_ptr
=
src_ptr
.offset
(
src_field_offset
,
&
self
)
?
;
let
dst_f_ptr
=
dst
.offset
(
dst_field_offset
,
&
self
)
?
;
let
(
src_f_value
,
src_field
)
=
match
src
{
Value
::
ByRef
(
PtrAndAlign
{
ptr
,
align
})
=>
{
let
src_place
=
Place
::
from_primval_ptr
(
ptr
,
align
);
let
(
src_f_place
,
src_field
)
=
self
.place_field
(
src_place
,
mir
::
Field
::
new
(
i
),
src_layout
)
?
;
(
self
.read_place
(
src_f_place
)
?
,
src_field
)
}
Value
::
ByVal
(
_
)
|
Value
::
ByValPair
(
..
)
=>
{
let
src_field
=
src_layout
.field
(
&
self
,
i
)
?
;
assert_eq!
(
src_layout
.fields
.offset
(
i
)
.bytes
(),
0
);
assert_eq!
(
src_field
.size
,
src_layout
.size
);
(
src
,
src_field
)
}
};
if
src_field
.ty
==
dst_field
.ty
{
self
.copy
(
src_f_ptr
,
dst_f_ptr
.into
(),
src_field
.ty
)
?
;
self
.write_value
(
ValTy
{
value
:
src_f_value
,
ty
:
src_field
.ty
,
},
dst_f_place
)
?
;
}
else
{
self
.unsize_into
(
Value
::
by_ref
(
src_f_ptr
),
src_field
.ty
,
Place
::
from_ptr
(
dst_f_ptr
),
dst_field
.ty
,
)
?
;
self
.unsize_into
(
src_f_value
,
src_field
,
dst_f_place
,
dst_field
)
?
;
}
}
Ok
(())
...
...
@@ -1534,8 +1512,8 @@ fn unsize_into(
_
=>
{
bug!
(
"unsize_into: invalid conversion: {:?} -> {:?}"
,
src_
ty
,
dst_
ty
src_
layout
,
dst_
layout
)
}
}
...
...
@@ -1559,11 +1537,10 @@ pub fn dump_local(&self, place: Place) {
Err
(
err
)
=>
{
panic!
(
"Failed to access local: {:?}"
,
err
);
}
Ok
(
Value
::
ByRef
(
PtrAndAlign
{
ptr
,
align
ed
}))
=>
{
Ok
(
Value
::
ByRef
(
PtrAndAlign
{
ptr
,
align
}))
=>
{
match
ptr
.into_inner_primval
()
{
PrimVal
::
Ptr
(
ptr
)
=>
{
write!
(
msg
,
" by {}ref:"
,
if
aligned
{
""
}
else
{
"unaligned "
})
.unwrap
();
write!
(
msg
,
" by align({}) ref:"
,
align
.abi
())
.unwrap
();
allocs
.push
(
ptr
.alloc_id
);
}
ptr
=>
write!
(
msg
,
" integral by ref: {:?}"
,
ptr
)
.unwrap
(),
...
...
@@ -1589,10 +1566,10 @@ pub fn dump_local(&self, place: Place) {
trace!
(
"{}"
,
msg
);
self
.memory
.dump_allocs
(
allocs
);
}
Place
::
Ptr
{
ptr
:
PtrAndAlign
{
ptr
,
align
ed
},
..
}
=>
{
Place
::
Ptr
{
ptr
:
PtrAndAlign
{
ptr
,
align
},
..
}
=>
{
match
ptr
.into_inner_primval
()
{
PrimVal
::
Ptr
(
ptr
)
=>
{
trace!
(
"by
{}ref:"
,
if
aligned
{
""
}
else
{
"unaligned "
}
);
trace!
(
"by
align({}) ref:"
,
align
.abi
()
);
self
.memory
.dump_alloc
(
ptr
.alloc_id
);
}
ptr
=>
trace!
(
" integral by ref: {:?}"
,
ptr
),
...
...
src/librustc_mir/interpret/memory.rs
浏览文件 @
ff080d38
...
...
@@ -4,7 +4,7 @@
use
std
::
cell
::
Cell
;
use
rustc
::
ty
::{
Instance
,
TyCtxt
};
use
rustc
::
ty
::
layout
::{
self
,
TargetDataLayout
};
use
rustc
::
ty
::
layout
::{
self
,
Align
,
TargetDataLayout
};
use
syntax
::
ast
::
Mutability
;
use
rustc
::
mir
::
interpret
::{
MemoryPointer
,
AllocId
,
Allocation
,
AccessKind
,
UndefMask
,
PtrAndAlign
,
Value
,
Pointer
,
...
...
@@ -51,10 +51,10 @@ pub struct Memory<'a, 'tcx: 'a, M: Machine<'tcx>> {
/// Maximum number of virtual bytes that may be allocated.
memory_size
:
u64
,
/// To avoid having to pass flags to every single memory access, we have some global state saying
whether
/// To avoid having to pass flags to every single memory access, we have some global state saying
how
/// alignment checking is currently enforced for read and/or write accesses.
read
s_are_aligned
:
Cell
<
bool
>
,
write
s_are_aligned
:
Cell
<
bool
>
,
read
_align_override
:
Cell
<
Option
<
Align
>
>
,
write
_align_override
:
Cell
<
Option
<
Align
>
>
,
/// The current stack frame. Used to check accesses against locks.
pub
cur_frame
:
usize
,
...
...
@@ -72,8 +72,8 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, max_memory: u64, data: M::MemoryData) ->
tcx
,
memory_size
:
max_memory
,
memory_usage
:
0
,
read
s_are_aligned
:
Cell
::
new
(
tru
e
),
write
s_are_aligned
:
Cell
::
new
(
tru
e
),
read
_align_override
:
Cell
::
new
(
Non
e
),
write
_align_override
:
Cell
::
new
(
Non
e
),
cur_frame
:
usize
::
max_value
(),
}
}
...
...
@@ -272,14 +272,12 @@ pub fn check_align(&self, ptr: Pointer, align: u64, access: Option<AccessKind>)
PrimVal
::
Undef
=>
return
err!
(
ReadUndefBytes
),
};
// See if alignment checking is disabled
let
enforce_alignment
=
match
access
{
Some
(
AccessKind
::
Read
)
=>
self
.read
s_are_aligned
.get
(),
Some
(
AccessKind
::
Write
)
=>
self
.write
s_are_aligned
.get
(),
None
=>
tru
e
,
let
align_override
=
match
access
{
Some
(
AccessKind
::
Read
)
=>
self
.read
_align_override
.get
(),
Some
(
AccessKind
::
Write
)
=>
self
.write
_align_override
.get
(),
None
=>
Non
e
,
};
if
!
enforce_alignment
{
return
Ok
(());
}
let
align
=
align_override
.map_or
(
align
,
|
o
|
o
.abi
()
.min
(
align
));
// Check alignment
if
alloc_align
<
align
{
return
err!
(
AlignmentCheckFailed
{
...
...
@@ -1005,39 +1003,39 @@ pub trait HasMemory<'a, 'tcx: 'a, M: Machine<'tcx>> {
fn
memory
(
&
self
)
->
&
Memory
<
'a
,
'tcx
,
M
>
;
// These are not supposed to be overriden.
fn
read_
maybe_aligned
<
F
,
T
>
(
&
self
,
aligned
:
bool
,
f
:
F
)
->
EvalResult
<
'tcx
,
T
>
fn
read_
with_align
<
F
,
T
>
(
&
self
,
align
:
Align
,
f
:
F
)
->
EvalResult
<
'tcx
,
T
>
where
F
:
FnOnce
(
&
Self
)
->
EvalResult
<
'tcx
,
T
>
,
{
let
old
=
self
.memory
()
.read
s_are_aligned
.get
();
// Do alignment checking
if *all* nested calls say it has to be aligned
.
self
.memory
()
.read
s_are_aligned
.set
(
old
&&
aligned
);
let
old
=
self
.memory
()
.read
_align_override
.get
();
// Do alignment checking
for the minimum align out of *all* nested calls
.
self
.memory
()
.read
_align_override
.set
(
Some
(
old
.map_or
(
align
,
|
old
|
old
.min
(
align
)))
);
let
t
=
f
(
self
);
self
.memory
()
.read
s_are_aligned
.set
(
old
);
self
.memory
()
.read
_align_override
.set
(
old
);
t
}
fn
read_
maybe_aligned_mut
<
F
,
T
>
(
&
mut
self
,
aligned
:
bool
,
f
:
F
)
->
EvalResult
<
'tcx
,
T
>
fn
read_
with_align_mut
<
F
,
T
>
(
&
mut
self
,
align
:
Align
,
f
:
F
)
->
EvalResult
<
'tcx
,
T
>
where
F
:
FnOnce
(
&
mut
Self
)
->
EvalResult
<
'tcx
,
T
>
,
{
let
old
=
self
.memory
()
.read
s_are_aligned
.get
();
// Do alignment checking
if *all* nested calls say it has to be aligned
.
self
.memory
()
.read
s_are_aligned
.set
(
old
&&
aligned
);
let
old
=
self
.memory
()
.read
_align_override
.get
();
// Do alignment checking
for the minimum align out of *all* nested calls
.
self
.memory
()
.read
_align_override
.set
(
Some
(
old
.map_or
(
align
,
|
old
|
old
.min
(
align
)))
);
let
t
=
f
(
self
);
self
.memory
()
.read
s_are_aligned
.set
(
old
);
self
.memory
()
.read
_align_override
.set
(
old
);
t
}
fn
write_
maybe_aligned_mut
<
F
,
T
>
(
&
mut
self
,
aligned
:
bool
,
f
:
F
)
->
EvalResult
<
'tcx
,
T
>
fn
write_
with_align_mut
<
F
,
T
>
(
&
mut
self
,
align
:
Align
,
f
:
F
)
->
EvalResult
<
'tcx
,
T
>
where
F
:
FnOnce
(
&
mut
Self
)
->
EvalResult
<
'tcx
,
T
>
,
{
let
old
=
self
.memory
()
.write
s_are_aligned
.get
();
// Do alignment checking
if *all* nested calls say it has to be aligned
.
self
.memory
()
.write
s_are_aligned
.set
(
old
&&
aligned
);
let
old
=
self
.memory
()
.write
_align_override
.get
();
// Do alignment checking
for the minimum align out of *all* nested calls
.
self
.memory
()
.write
_align_override
.set
(
Some
(
old
.map_or
(
align
,
|
old
|
old
.min
(
align
)))
);
let
t
=
f
(
self
);
self
.memory
()
.write
s_are_aligned
.set
(
old
);
self
.memory
()
.write
_align_override
.set
(
old
);
t
}
...
...
@@ -1048,8 +1046,8 @@ fn into_ptr(
value
:
Value
,
)
->
EvalResult
<
'tcx
,
Pointer
>
{
Ok
(
match
value
{
Value
::
ByRef
(
PtrAndAlign
{
ptr
,
align
ed
})
=>
{
self
.memory
()
.read_
maybe_aligned
(
aligned
,
|
mem
|
mem
.read_ptr_sized_unsigned
(
ptr
.to_ptr
()
?
))
?
Value
::
ByRef
(
PtrAndAlign
{
ptr
,
align
})
=>
{
self
.memory
()
.read_
with_align
(
align
,
|
mem
|
mem
.read_ptr_sized_unsigned
(
ptr
.to_ptr
()
?
))
?
}
Value
::
ByVal
(
ptr
)
|
Value
::
ByValPair
(
ptr
,
_
)
=>
ptr
,
...
...
@@ -1063,9 +1061,9 @@ fn into_ptr_vtable_pair(
match
value
{
Value
::
ByRef
(
PtrAndAlign
{
ptr
:
ref_ptr
,
align
ed
,
align
,
})
=>
{
self
.memory
()
.read_
maybe_aligned
(
aligned
,
|
mem
|
{
self
.memory
()
.read_
with_align
(
align
,
|
mem
|
{
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
.tcx.data_layout
)
?
.to_ptr
()
?
,
...
...
@@ -1088,9 +1086,9 @@ fn into_slice(
match
value
{
Value
::
ByRef
(
PtrAndAlign
{
ptr
:
ref_ptr
,
align
ed
,
align
,
})
=>
{
self
.memory
()
.read_
maybe_aligned
(
aligned
,
|
mem
|
{
self
.memory
()
.read_
with_align
(
align
,
|
mem
|
{
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
.tcx.data_layout
)
?
.to_ptr
()
?
,
...
...
src/librustc_mir/interpret/place.rs
浏览文件 @
ff080d38
use
rustc
::
mir
;
use
rustc
::
ty
::{
self
,
Ty
};
use
rustc
::
ty
::
layout
::{
self
,
LayoutOf
,
TyLayout
};
use
rustc
::
ty
::
layout
::{
self
,
Align
,
LayoutOf
,
TyLayout
};
use
rustc_data_structures
::
indexed_vec
::
Idx
;
use
rustc
::
mir
::
interpret
::{
GlobalId
,
PtrAndAlign
};
...
...
@@ -35,21 +35,21 @@ pub enum PlaceExtra {
impl
<
'tcx
>
Place
{
/// Produces an Place that will error if attempted to be read from
pub
fn
undef
()
->
Self
{
Self
::
from_primval_ptr
(
PrimVal
::
Undef
.into
())
Self
::
from_primval_ptr
(
PrimVal
::
Undef
.into
()
,
Align
::
from_bytes
(
1
,
1
)
.unwrap
()
)
}
pub
fn
from_primval_ptr
(
ptr
:
Pointer
)
->
Self
{
pub
fn
from_primval_ptr
(
ptr
:
Pointer
,
align
:
Align
)
->
Self
{
Place
::
Ptr
{
ptr
:
PtrAndAlign
{
ptr
,
align
ed
:
true
},
ptr
:
PtrAndAlign
{
ptr
,
align
},
extra
:
PlaceExtra
::
None
,
}
}
pub
fn
from_ptr
(
ptr
:
MemoryPointer
)
->
Self
{
Self
::
from_primval_ptr
(
ptr
.into
())
pub
fn
from_ptr
(
ptr
:
MemoryPointer
,
align
:
Align
)
->
Self
{
Self
::
from_primval_ptr
(
ptr
.into
()
,
align
)
}
pub
fn
to_ptr_
extra_aligned
(
self
)
->
(
PtrAndAlign
,
PlaceExtra
)
{
pub
fn
to_ptr_
align_extra
(
self
)
->
(
PtrAndAlign
,
PlaceExtra
)
{
match
self
{
Place
::
Ptr
{
ptr
,
extra
}
=>
(
ptr
,
extra
),
_
=>
bug!
(
"to_ptr_and_extra: expected Place::Ptr, got {:?}"
,
self
),
...
...
@@ -57,12 +57,15 @@ pub fn to_ptr_extra_aligned(self) -> (PtrAndAlign, PlaceExtra) {
}
}
pub
fn
to_ptr_align
(
self
)
->
PtrAndAlign
{
let
(
ptr
,
_
extra
)
=
self
.to_ptr_align_extra
();
ptr
}
pub
fn
to_ptr
(
self
)
->
EvalResult
<
'tcx
,
MemoryPointer
>
{
let
(
ptr
,
extra
)
=
self
.to_ptr_extra_aligned
();
// At this point, we forget about the alignment information -- the place has been turned into a reference,
// and no matter where it came from, it now must be aligned.
assert_eq!
(
extra
,
PlaceExtra
::
None
);
ptr
.to_ptr
()
self
.to_ptr_align
()
.to_ptr
()
}
pub
(
super
)
fn
elem_ty_and_len
(
self
,
ty
:
Ty
<
'tcx
>
)
->
(
Ty
<
'tcx
>
,
u64
)
{
...
...
@@ -102,11 +105,10 @@ pub fn try_read_place(
// Directly reading a static will always succeed
Static
(
ref
static_
)
=>
{
let
instance
=
ty
::
Instance
::
mono
(
self
.tcx
,
static_
.def_id
);
let
cid
=
GlobalId
{
Ok
(
Some
(
self
.read_global_as_value
(
GlobalId
{
instance
,
promoted
:
None
,
};
Ok
(
Some
(
self
.read_global_as_value
(
cid
)))
},
self
.layout_of
(
self
.place_ty
(
place
))
?
)))
}
Projection
(
ref
proj
)
=>
self
.try_read_place_projection
(
proj
),
}
...
...
@@ -190,10 +192,11 @@ pub fn eval_place(&mut self, mir_place: &mir::Place<'tcx>) -> EvalResult<'tcx, P
instance
,
promoted
:
None
,
};
let
layout
=
self
.layout_of
(
self
.place_ty
(
mir_place
))
?
;
Place
::
Ptr
{
ptr
:
PtrAndAlign
{
ptr
:
self
.tcx.interpret_interner
.borrow
()
.get_cached
(
gid
)
.expect
(
"uncached global"
),
align
ed
:
true
align
:
layout
.align
},
extra
:
PlaceExtra
::
None
,
}
...
...
@@ -241,7 +244,7 @@ pub fn place_field(
{
return
Ok
((
base
,
field
));
}
_
=>
self
.force_allocation
(
base
)
?
.to_ptr_
extra_aligned
(),
_
=>
self
.force_allocation
(
base
)
?
.to_ptr_
align_extra
(),
}
}
};
...
...
@@ -258,7 +261,7 @@ pub fn place_field(
};
let
mut
ptr
=
base_ptr
.offset
(
offset
,
&
self
)
?
;
ptr
.align
ed
&=
base_layout
.align
.abi
()
>=
field
.align
.abi
(
);
ptr
.align
=
ptr
.align
.min
(
base_layout
.align
)
.min
(
field
.align
);
let
extra
=
if
!
field
.is_unsized
()
{
PlaceExtra
::
None
...
...
@@ -278,22 +281,23 @@ pub fn place_field(
}
pub
fn
val_to_place
(
&
self
,
val
:
Value
,
ty
:
Ty
<
'tcx
>
)
->
EvalResult
<
'tcx
,
Place
>
{
let
layout
=
self
.layout_of
(
ty
)
?
;
Ok
(
match
self
.tcx
.struct_tail
(
ty
)
.sty
{
ty
::
TyDynamic
(
..
)
=>
{
let
(
ptr
,
vtable
)
=
self
.into_ptr_vtable_pair
(
val
)
?
;
Place
::
Ptr
{
ptr
:
PtrAndAlign
{
ptr
,
align
ed
:
true
},
ptr
:
PtrAndAlign
{
ptr
,
align
:
layout
.align
},
extra
:
PlaceExtra
::
Vtable
(
vtable
),
}
}
ty
::
TyStr
|
ty
::
TySlice
(
_
)
=>
{
let
(
ptr
,
len
)
=
self
.into_slice
(
val
)
?
;
Place
::
Ptr
{
ptr
:
PtrAndAlign
{
ptr
,
align
ed
:
true
},
ptr
:
PtrAndAlign
{
ptr
,
align
:
layout
.align
},
extra
:
PlaceExtra
::
Length
(
len
),
}
}
_
=>
Place
::
from_primval_ptr
(
self
.into_ptr
(
val
)
?
),
_
=>
Place
::
from_primval_ptr
(
self
.into_ptr
(
val
)
?
,
layout
.align
),
})
}
...
...
@@ -305,7 +309,7 @@ pub fn place_index(
)
->
EvalResult
<
'tcx
,
Place
>
{
// Taking the outer type here may seem odd; it's needed because for array types, the outer type gives away the length.
let
base
=
self
.force_allocation
(
base
)
?
;
let
(
base_ptr
,
_
)
=
base
.to_ptr_extra_aligned
();
let
base_ptr
=
base
.to_ptr_align
();
let
(
elem_ty
,
len
)
=
base
.elem_ty_and_len
(
outer_ty
);
let
elem_size
=
self
.layout_of
(
elem_ty
)
?
.size
.bytes
();
...
...
@@ -329,7 +333,7 @@ pub(super) fn place_downcast(
)
->
EvalResult
<
'tcx
,
Place
>
{
// FIXME(solson)
let
base
=
self
.force_allocation
(
base
)
?
;
let
(
ptr
,
_
)
=
base
.to_ptr_extra_aligned
();
let
ptr
=
base
.to_ptr_align
();
let
extra
=
PlaceExtra
::
DowncastVariant
(
variant
);
Ok
(
Place
::
Ptr
{
ptr
,
extra
})
}
...
...
@@ -380,7 +384,7 @@ pub fn eval_place_projection(
}
=>
{
// FIXME(solson)
let
base
=
self
.force_allocation
(
base
)
?
;
let
(
base_ptr
,
_
)
=
base
.to_ptr_extra_aligned
();
let
base_ptr
=
base
.to_ptr_align
();
let
(
elem_ty
,
n
)
=
base
.elem_ty_and_len
(
base_ty
);
let
elem_size
=
self
.layout_of
(
elem_ty
)
?
.size
.bytes
();
...
...
@@ -399,7 +403,7 @@ pub fn eval_place_projection(
Subslice
{
from
,
to
}
=>
{
// FIXME(solson)
let
base
=
self
.force_allocation
(
base
)
?
;
let
(
base_ptr
,
_
)
=
base
.to_ptr_extra_aligned
();
let
base_ptr
=
base
.to_ptr_align
();
let
(
elem_ty
,
n
)
=
base
.elem_ty_and_len
(
base_ty
);
let
elem_size
=
self
.layout_of
(
elem_ty
)
?
.size
.bytes
();
...
...
src/librustc_mir/interpret/step.rs
浏览文件 @
ff080d38
...
...
@@ -197,7 +197,7 @@ fn global_item(
instance
,
span
,
mir
,
Place
::
from_ptr
(
ptr
),
Place
::
from_ptr
(
ptr
,
layout
.align
),
cleanup
,
)
?
;
Ok
(
true
)
...
...
@@ -273,7 +273,7 @@ fn visit_constant(&mut self, constant: &mir::Constant<'tcx>, location: mir::Loca
this
.instance
,
constant
.span
,
mir
,
Place
::
from_ptr
(
ptr
),
Place
::
from_ptr
(
ptr
,
layout
.align
),
StackPopCleanup
::
MarkStatic
(
Mutability
::
Immutable
),
)
?
;
Ok
(
true
)
...
...
src/librustc_mir/interpret/terminator/mod.rs
浏览文件 @
ff080d38
...
...
@@ -327,15 +327,14 @@ fn eval_fn_call(
if
let
ty
::
TyTuple
(
..
)
=
args
[
1
]
.ty.sty
{
if
self
.frame
()
.mir
.args_iter
()
.count
()
==
layout
.fields
.count
()
+
1
{
match
args
[
1
]
.value
{
Value
::
ByRef
(
PtrAndAlign
{
ptr
,
aligned
})
=>
{
assert
!
(
aligned
,
"Unaligned ByRef-values cannot occur as function arguments"
);
Value
::
ByRef
(
PtrAndAlign
{
ptr
,
align
})
=>
{
for
(
i
,
arg_local
)
in
arg_locals
.enumerate
()
{
let
field
=
layout
.field
(
&
self
,
i
)
?
;
let
offset
=
layout
.fields
.offset
(
i
)
.bytes
();
let
arg
=
Value
::
by_ref
(
ptr
.offset
(
offset
,
&
self
)
?
);
let
arg
=
Value
::
ByRef
(
PtrAndAlign
{
ptr
:
ptr
.offset
(
offset
,
&
self
)
?
,
align
:
align
.min
(
field
.align
)
});
let
dest
=
self
.eval_place
(
&
mir
::
Place
::
Local
(
arg_local
))
?
;
trace!
(
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录