Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
30f07f3d
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,发现更多精彩内容 >>
提交
30f07f3d
编写于
4月 29, 2016
作者:
S
Scott Olson
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Re-implement support for downcast lvalues.
上级
0f533e3a
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
38 addition
and
36 deletion
+38
-36
src/interpreter.rs
src/interpreter.rs
+38
-36
未找到文件。
src/interpreter.rs
浏览文件 @
30f07f3d
...
...
@@ -84,7 +84,8 @@ struct Lvalue {
enum
LvalueExtra
{
None
,
Length
(
u64
),
// Vtable(memory::AllocId),
// TODO(tsion): Vtable(memory::AllocId),
DowncastVariant
(
usize
),
}
#[derive(Clone)]
...
...
@@ -231,8 +232,10 @@ fn eval_terminator(&mut self, terminator: &mir::Terminator<'tcx>)
SwitchInt
{
ref
discr
,
ref
values
,
ref
targets
,
..
}
=>
{
let
discr_ptr
=
try!
(
self
.eval_lvalue
(
discr
))
.to_ptr
();
let
discr_size
=
self
.lvalue_layout
(
discr
)
.size
(
&
self
.tcx.data_layout
)
.bytes
()
as
usize
;
let
discr_size
=
self
.type_layout
(
self
.lvalue_ty
(
discr
))
.size
(
&
self
.tcx.data_layout
)
.bytes
()
as
usize
;
let
discr_val
=
try!
(
self
.memory
.read_uint
(
discr_ptr
,
discr_size
));
// Branch to the `otherwise` case by default, if no match is found.
...
...
@@ -252,7 +255,7 @@ fn eval_terminator(&mut self, terminator: &mir::Terminator<'tcx>)
Switch
{
ref
discr
,
ref
targets
,
adt_def
}
=>
{
let
adt_ptr
=
try!
(
self
.eval_lvalue
(
discr
))
.to_ptr
();
let
adt_layout
=
self
.
lvalue_layout
(
discr
);
let
adt_layout
=
self
.
type_layout
(
self
.lvalue_ty
(
discr
)
);
let
discr_size
=
match
*
adt_layout
{
Layout
::
General
{
discr
,
..
}
=>
discr
.size
()
.bytes
(),
_
=>
panic!
(
"attmpted to switch on non-aggregate type"
),
...
...
@@ -590,7 +593,7 @@ fn eval_assignment(&mut self, lvalue: &mir::Lvalue<'tcx>, rvalue: &mir::Rvalue<'
{
let
dest
=
try!
(
self
.eval_lvalue
(
lvalue
))
.to_ptr
();
let
dest_ty
=
self
.lvalue_ty
(
lvalue
);
let
dest_layout
=
self
.
lvalue_layout
(
lvalue
);
let
dest_layout
=
self
.
type_layout
(
dest_ty
);
use
rustc
::
mir
::
repr
::
Rvalue
::
*
;
match
*
rvalue
{
...
...
@@ -693,6 +696,8 @@ fn eval_assignment(&mut self, lvalue: &mir::Lvalue<'tcx>, rvalue: &mir::Rvalue<'
let
len_ptr
=
dest
.offset
(
self
.memory.pointer_size
as
isize
);
try!
(
self
.memory
.write_usize
(
len_ptr
,
len
));
}
LvalueExtra
::
DowncastVariant
(
..
)
=>
panic!
(
"attempted to take a reference to an enum downcast lvalue"
),
}
}
...
...
@@ -745,7 +750,7 @@ fn eval_operand(&mut self, op: &mir::Operand<'tcx>) -> EvalResult<Pointer> {
match
*
op
{
Consume
(
ref
lvalue
)
=>
Ok
(
try!
(
self
.eval_lvalue
(
lvalue
))
.to_ptr
()),
Constant
(
mir
::
Constant
{
ref
literal
,
ty
,
..
})
=>
{
Constant
(
mir
::
Constant
{
ref
literal
,
..
})
=>
{
use
rustc
::
mir
::
repr
::
Literal
::
*
;
match
*
literal
{
Value
{
ref
value
}
=>
Ok
(
try!
(
self
.const_to_ptr
(
value
))),
...
...
@@ -755,22 +760,6 @@ fn eval_operand(&mut self, op: &mir::Operand<'tcx>) -> EvalResult<Pointer> {
}
}
// TODO(tsion): Replace this inefficient hack with a wrapper like LvalueTy (e.g. LvalueLayout).
fn
lvalue_layout
(
&
self
,
lvalue
:
&
mir
::
Lvalue
<
'tcx
>
)
->
&
'tcx
Layout
{
use
rustc
::
mir
::
tcx
::
LvalueTy
;
match
self
.mir
()
.lvalue_ty
(
self
.tcx
,
lvalue
)
{
LvalueTy
::
Ty
{
ty
}
=>
self
.type_layout
(
ty
),
LvalueTy
::
Downcast
{
adt_def
,
substs
,
variant_index
}
=>
{
let
field_tys
=
adt_def
.variants
[
variant_index
]
.fields
.iter
()
.map
(|
f
|
f
.ty
(
self
.tcx
,
substs
));
// FIXME(tsion): Handle LvalueTy::Downcast better somehow...
unimplemented!
();
// self.repr_arena.alloc(self.make_aggregate_layout(iter::once(field_tys)))
}
}
}
fn
eval_lvalue
(
&
mut
self
,
lvalue
:
&
mir
::
Lvalue
<
'tcx
>
)
->
EvalResult
<
Lvalue
>
{
use
rustc
::
mir
::
repr
::
Lvalue
::
*
;
let
ptr
=
match
*
lvalue
{
...
...
@@ -783,32 +772,45 @@ fn eval_lvalue(&mut self, lvalue: &mir::Lvalue<'tcx>) -> EvalResult<Lvalue> {
Static
(
_
def_id
)
=>
unimplemented!
(),
Projection
(
ref
proj
)
=>
{
let
base_ptr
=
try!
(
self
.eval_lvalue
(
&
proj
.base
))
.ptr
;
let
base_layout
=
self
.lvalue_layout
(
&
proj
.base
);
let
base
=
try!
(
self
.eval_lvalue
(
&
proj
.base
));
let
base_ty
=
self
.lvalue_ty
(
&
proj
.base
);
let
base_layout
=
self
.type_layout
(
base_ty
);
use
rustc
::
mir
::
repr
::
ProjectionElem
::
*
;
match
proj
.elem
{
Field
(
field
,
_
)
=>
match
*
base_layout
{
Layout
::
Univariant
{
ref
variant
,
..
}
=>
{
let
offset
=
variant
.field_offset
(
field
.index
())
.bytes
();
base_ptr
.offset
(
offset
as
isize
)
}
_
=>
panic!
(
"field access on non-product type: {:?}"
,
base_layout
),
Field
(
field
,
_
)
=>
{
let
variant
=
match
*
base_layout
{
Layout
::
Univariant
{
ref
variant
,
..
}
=>
variant
,
Layout
::
General
{
ref
variants
,
..
}
=>
{
if
let
LvalueExtra
::
DowncastVariant
(
variant_idx
)
=
base
.extra
{
&
variants
[
variant_idx
]
}
else
{
panic!
(
"field access on enum had no variant index"
);
}
}
_
=>
panic!
(
"field access on non-product type: {:?}"
,
base_layout
),
};
let
offset
=
variant
.field_offset
(
field
.index
())
.bytes
();
base
.ptr
.offset
(
offset
as
isize
)
},
Downcast
(
..
)
=>
match
*
base_layout
{
Layout
::
General
{
discr
,
..
}
=>
base_ptr
.offset
(
discr
.size
()
.bytes
()
as
isize
),
Downcast
(
_
,
variant
)
=>
match
*
base_layout
{
Layout
::
General
{
discr
,
..
}
=>
{
return
Ok
(
Lvalue
{
ptr
:
base
.ptr
.offset
(
discr
.size
()
.bytes
()
as
isize
),
extra
:
LvalueExtra
::
DowncastVariant
(
variant
),
});
}
_
=>
panic!
(
"variant downcast on non-aggregate type: {:?}"
,
base_layout
),
},
Deref
=>
{
let
pointee_ty
=
pointee_type
(
base_ty
)
.expect
(
"Deref of non-pointer"
);
let
ptr
=
try!
(
self
.memory
.read_ptr
(
base
_
ptr
));
let
ptr
=
try!
(
self
.memory
.read_ptr
(
base
.
ptr
));
let
extra
=
match
pointee_ty
.sty
{
ty
::
TySlice
(
_
)
|
ty
::
TyStr
=>
{
let
len_ptr
=
base
_
ptr
.offset
(
self
.memory.pointer_size
as
isize
);
let
len_ptr
=
base
.
ptr
.offset
(
self
.memory.pointer_size
as
isize
);
let
len
=
try!
(
self
.memory
.read_usize
(
len_ptr
));
LvalueExtra
::
Length
(
len
)
}
...
...
@@ -826,7 +828,7 @@ fn eval_lvalue(&mut self, lvalue: &mir::Lvalue<'tcx>) -> EvalResult<Lvalue> {
};
let
n_ptr
=
try!
(
self
.eval_operand
(
operand
));
let
n
=
try!
(
self
.memory
.read_usize
(
n_ptr
));
base
_
ptr
.offset
(
n
as
isize
*
elem_size
as
isize
)
base
.
ptr
.offset
(
n
as
isize
*
elem_size
as
isize
)
}
ConstantIndex
{
..
}
=>
unimplemented!
(),
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录