Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
b723af28
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,发现更多精彩内容 >>
提交
b723af28
编写于
9月 21, 2017
作者:
E
Eduard-Mihai Burtescu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
rustc_trans: go through layouts uniformly for fat pointers and variants.
上级
026214c8
变更
25
隐藏空白更改
内联
并排
Showing
25 changed file
with
363 addition
and
447 deletion
+363
-447
src/librustc/lint/context.rs
src/librustc/lint/context.rs
+3
-3
src/librustc/ty/layout.rs
src/librustc/ty/layout.rs
+118
-115
src/librustc_lint/types.rs
src/librustc_lint/types.rs
+1
-1
src/librustc_llvm/ffi.rs
src/librustc_llvm/ffi.rs
+0
-5
src/librustc_trans/abi.rs
src/librustc_trans/abi.rs
+6
-6
src/librustc_trans/base.rs
src/librustc_trans/base.rs
+10
-7
src/librustc_trans/cabi_s390x.rs
src/librustc_trans/cabi_s390x.rs
+2
-2
src/librustc_trans/cabi_x86.rs
src/librustc_trans/cabi_x86.rs
+2
-2
src/librustc_trans/cabi_x86_64.rs
src/librustc_trans/cabi_x86_64.rs
+3
-3
src/librustc_trans/common.rs
src/librustc_trans/common.rs
+4
-28
src/librustc_trans/context.rs
src/librustc_trans/context.rs
+17
-27
src/librustc_trans/debuginfo/metadata.rs
src/librustc_trans/debuginfo/metadata.rs
+7
-7
src/librustc_trans/meth.rs
src/librustc_trans/meth.rs
+5
-1
src/librustc_trans/mir/analyze.rs
src/librustc_trans/mir/analyze.rs
+4
-10
src/librustc_trans/mir/block.rs
src/librustc_trans/mir/block.rs
+20
-13
src/librustc_trans/mir/constant.rs
src/librustc_trans/mir/constant.rs
+12
-9
src/librustc_trans/mir/lvalue.rs
src/librustc_trans/mir/lvalue.rs
+20
-41
src/librustc_trans/mir/mod.rs
src/librustc_trans/mir/mod.rs
+8
-27
src/librustc_trans/mir/operand.rs
src/librustc_trans/mir/operand.rs
+3
-3
src/librustc_trans/mir/rvalue.rs
src/librustc_trans/mir/rvalue.rs
+9
-7
src/librustc_trans/type_.rs
src/librustc_trans/type_.rs
+0
-4
src/librustc_trans/type_of.rs
src/librustc_trans/type_of.rs
+96
-112
src/test/codegen/adjustments.rs
src/test/codegen/adjustments.rs
+3
-4
src/test/codegen/function-arguments.rs
src/test/codegen/function-arguments.rs
+7
-7
src/test/codegen/refs.rs
src/test/codegen/refs.rs
+3
-3
未找到文件。
src/librustc/lint/context.rs
浏览文件 @
b723af28
...
...
@@ -35,7 +35,7 @@
use
session
::{
config
,
early_error
,
Session
};
use
traits
::
Reveal
;
use
ty
::{
self
,
TyCtxt
,
Ty
};
use
ty
::
layout
::{
FullLayout
,
LayoutError
,
LayoutOf
};
use
ty
::
layout
::{
LayoutError
,
LayoutOf
,
TyLayout
};
use
util
::
nodemap
::
FxHashMap
;
use
std
::
default
::
Default
as
StdDefault
;
...
...
@@ -628,9 +628,9 @@ fn with_param_env<F>(&mut self, id: ast::NodeId, f: F)
}
impl
<
'a
,
'tcx
>
LayoutOf
<
Ty
<
'tcx
>>
for
&
'a
LateContext
<
'a
,
'tcx
>
{
type
FullLayout
=
Result
<
Full
Layout
<
'tcx
>
,
LayoutError
<
'tcx
>>
;
type
TyLayout
=
Result
<
Ty
Layout
<
'tcx
>
,
LayoutError
<
'tcx
>>
;
fn
layout_of
(
self
,
ty
:
Ty
<
'tcx
>
)
->
Self
::
Full
Layout
{
fn
layout_of
(
self
,
ty
:
Ty
<
'tcx
>
)
->
Self
::
Ty
Layout
{
(
self
.tcx
,
self
.param_env
.reveal_all
())
.layout_of
(
ty
)
}
}
...
...
src/librustc/ty/layout.rs
浏览文件 @
b723af28
...
...
@@ -23,7 +23,7 @@
use
std
::
i64
;
use
std
::
iter
;
use
std
::
mem
;
use
std
::
ops
::{
Add
,
Sub
,
Mul
,
AddAssign
,
RangeInclusive
};
use
std
::
ops
::{
Add
,
Sub
,
Mul
,
AddAssign
,
Deref
,
RangeInclusive
};
use
ich
::
StableHashingContext
;
use
rustc_data_structures
::
stable_hasher
::{
HashStable
,
StableHasher
,
...
...
@@ -907,6 +907,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[derive(PartialEq,
Eq,
Hash,
Debug)]
pub
struct
CachedLayout
{
pub
variant_index
:
Option
<
usize
>
,
pub
layout
:
Layout
,
pub
fields
:
FieldPlacement
,
pub
abi
:
Abi
,
...
...
@@ -948,6 +949,7 @@ fn compute_uncached(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let
dl
=
cx
.data_layout
();
let
scalar
=
|
value
|
{
tcx
.intern_layout
(
CachedLayout
{
variant_index
:
None
,
layout
:
Layout
::
Scalar
,
fields
:
FieldPlacement
::
Union
(
0
),
abi
:
Abi
::
Scalar
(
value
)
...
...
@@ -962,7 +964,7 @@ enum StructKind {
/// A univariant, but part of an enum.
EnumVariant
(
Integer
),
}
let
univariant_uninterned
=
|
fields
:
&
[
Full
Layout
],
repr
:
&
ReprOptions
,
kind
|
{
let
univariant_uninterned
=
|
fields
:
&
[
Ty
Layout
],
repr
:
&
ReprOptions
,
kind
|
{
let
packed
=
repr
.packed
();
if
packed
&&
repr
.align
>
0
{
bug!
(
"struct cannot be packed and aligned"
);
...
...
@@ -1085,6 +1087,7 @@ enum StructKind {
}
Ok
(
CachedLayout
{
variant_index
:
None
,
layout
:
Layout
::
Univariant
,
fields
:
FieldPlacement
::
Arbitrary
{
offsets
,
...
...
@@ -1099,7 +1102,7 @@ enum StructKind {
}
})
};
let
univariant
=
|
fields
:
&
[
Full
Layout
],
repr
:
&
ReprOptions
,
kind
|
{
let
univariant
=
|
fields
:
&
[
Ty
Layout
],
repr
:
&
ReprOptions
,
kind
|
{
Ok
(
tcx
.intern_layout
(
univariant_uninterned
(
fields
,
repr
,
kind
)
?
))
};
assert
!
(
!
ty
.has_infer_types
());
...
...
@@ -1129,6 +1132,7 @@ enum StructKind {
memory_index
:
vec!
[
0
,
1
]
};
Ok
(
tcx
.intern_layout
(
CachedLayout
{
variant_index
:
None
,
layout
:
Layout
::
Univariant
,
fields
,
abi
:
Abi
::
Aggregate
{
...
...
@@ -1185,6 +1189,7 @@ enum StructKind {
.ok_or
(
LayoutError
::
SizeOverflow
(
ty
))
?
;
tcx
.intern_layout
(
CachedLayout
{
variant_index
:
None
,
layout
:
Layout
::
Array
,
fields
:
FieldPlacement
::
Array
{
stride
:
element_size
,
...
...
@@ -1202,6 +1207,7 @@ enum StructKind {
ty
::
TySlice
(
element
)
=>
{
let
element
=
cx
.layout_of
(
element
)
?
;
tcx
.intern_layout
(
CachedLayout
{
variant_index
:
None
,
layout
:
Layout
::
Array
,
fields
:
FieldPlacement
::
Array
{
stride
:
element
.size
(
dl
),
...
...
@@ -1218,6 +1224,7 @@ enum StructKind {
}
ty
::
TyStr
=>
{
tcx
.intern_layout
(
CachedLayout
{
variant_index
:
None
,
layout
:
Layout
::
Array
,
fields
:
FieldPlacement
::
Array
{
stride
:
Size
::
from_bytes
(
1
),
...
...
@@ -1286,6 +1293,7 @@ enum StructKind {
}
};
tcx
.intern_layout
(
CachedLayout
{
variant_index
:
None
,
layout
:
Layout
::
Vector
,
fields
:
FieldPlacement
::
Array
{
stride
:
element
.size
(
tcx
),
...
...
@@ -1343,6 +1351,7 @@ enum StructKind {
}
return
Ok
(
tcx
.intern_layout
(
CachedLayout
{
variant_index
:
None
,
layout
:
Layout
::
UntaggedUnion
,
fields
:
FieldPlacement
::
Union
(
variants
[
0
]
.len
()),
abi
:
Abi
::
Aggregate
{
...
...
@@ -1372,7 +1381,11 @@ enum StructKind {
else
{
StructKind
::
AlwaysSized
}
};
return
univariant
(
&
variants
[
0
],
&
def
.repr
,
kind
);
let
mut
cached
=
univariant_uninterned
(
&
variants
[
0
],
&
def
.repr
,
kind
)
?
;
if
def
.is_enum
()
{
cached
.variant_index
=
Some
(
0
);
}
return
Ok
(
tcx
.intern_layout
(
cached
));
}
let
no_explicit_discriminants
=
def
.variants
.iter
()
.enumerate
()
...
...
@@ -1389,12 +1402,14 @@ enum StructKind {
for
(
field_index
,
field
)
in
variants
[
i
]
.iter
()
.enumerate
()
{
if
let
Some
((
offset
,
discr
))
=
field
.non_zero_field
(
cx
)
?
{
let
st
=
vec!
[
let
mut
st
=
vec!
[
univariant_uninterned
(
&
variants
[
0
],
&
def
.repr
,
StructKind
::
AlwaysSized
)
?
,
univariant_uninterned
(
&
variants
[
1
],
&
def
.repr
,
StructKind
::
AlwaysSized
)
?
];
st
[
0
]
.variant_index
=
Some
(
0
);
st
[
1
]
.variant_index
=
Some
(
1
);
let
offset
=
st
[
i
]
.fields
.offset
(
field_index
)
+
offset
;
let
mut
abi
=
st
[
i
]
.abi
;
if
offset
.bytes
()
==
0
&&
discr
.size
(
dl
)
==
abi
.size
(
dl
)
{
...
...
@@ -1418,6 +1433,7 @@ enum StructKind {
_
=>
{}
}
return
Ok
(
tcx
.intern_layout
(
CachedLayout
{
variant_index
:
None
,
layout
:
Layout
::
NullablePointer
{
nndiscr
:
i
as
u64
,
...
...
@@ -1454,13 +1470,13 @@ enum StructKind {
assert_eq!
(
Integer
::
for_abi_align
(
dl
,
start_align
),
None
);
// Create the set of structs that represent each variant.
let
mut
variants
=
variants
.into_iter
()
.
map
(|
field_layouts
|
{
let
st
=
univariant_uninterned
(
&
field_layouts
,
let
mut
variants
=
variants
.into_iter
()
.
enumerate
()
.map
(|(
i
,
field_layouts
)
|
{
let
mut
st
=
univariant_uninterned
(
&
field_layouts
,
&
def
.repr
,
StructKind
::
EnumVariant
(
min_ity
))
?
;
st
.variant_index
=
Some
(
i
);
// Find the first field we can't move later
// to make room for a larger discriminant.
for
i
in
st
.fields
.index_by_increasing_offset
()
{
let
field
=
field_layouts
[
i
];
for
field
in
st
.fields
.index_by_increasing_offset
()
.map
(|
j
|
field_layouts
[
j
])
{
let
field_align
=
field
.align
(
dl
);
if
!
field
.is_zst
()
||
field_align
.abi
()
!=
1
{
start_align
=
start_align
.min
(
field_align
);
...
...
@@ -1539,6 +1555,7 @@ enum StructKind {
let
discr
=
Int
(
ity
,
signed
);
tcx
.intern_layout
(
CachedLayout
{
variant_index
:
None
,
layout
:
Layout
::
General
{
discr
,
...
...
@@ -1587,7 +1604,7 @@ enum StructKind {
fn
record_layout_for_printing
(
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
ty
:
Ty
<
'tcx
>
,
param_env
:
ty
::
ParamEnv
<
'tcx
>
,
layout
:
Full
Layout
<
'tcx
>
)
{
layout
:
Ty
Layout
<
'tcx
>
)
{
// If we are running with `-Zprint-type-sizes`, record layouts for
// dumping later. Ignore layouts that are done with non-empty
// environments or non-monomorphic layouts, as the user only wants
...
...
@@ -1607,7 +1624,7 @@ fn record_layout_for_printing(tcx: TyCtxt<'a, 'tcx, 'tcx>,
fn
record_layout_for_printing_outlined
(
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
ty
:
Ty
<
'tcx
>
,
param_env
:
ty
::
ParamEnv
<
'tcx
>
,
layout
:
Full
Layout
<
'tcx
>
)
{
layout
:
Ty
Layout
<
'tcx
>
)
{
let
cx
=
(
tcx
,
param_env
);
// (delay format until we actually need it)
let
record
=
|
kind
,
opt_discr_size
,
variants
|
{
...
...
@@ -1644,7 +1661,7 @@ fn record_layout_for_printing_outlined(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let
build_variant_info
=
|
n
:
Option
<
ast
::
Name
>
,
flds
:
&
[
ast
::
Name
],
layout
:
Full
Layout
<
'tcx
>
|
{
layout
:
Ty
Layout
<
'tcx
>
|
{
let
mut
min_size
=
Size
::
from_bytes
(
0
);
let
field_info
:
Vec
<
_
>
=
flds
.iter
()
.enumerate
()
.map
(|(
i
,
&
name
)|
{
match
layout
.field
(
cx
,
i
)
{
...
...
@@ -1685,7 +1702,7 @@ fn record_layout_for_printing_outlined(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
};
match
*
layout
.layout
{
match
layout
.layout
{
Layout
::
Univariant
=>
{
let
variant_names
=
||
{
adt_def
.variants
.iter
()
.map
(|
v
|
format!
(
"{}"
,
v
.name
))
.collect
::
<
Vec
<
_
>>
()
...
...
@@ -1723,7 +1740,7 @@ fn record_layout_for_printing_outlined(tcx: TyCtxt<'a, 'tcx, 'tcx>,
layout
.for_variant
(
i
))
})
.collect
();
record
(
adt_kind
.into
(),
match
*
layout
.layout
{
record
(
adt_kind
.into
(),
match
layout
.layout
{
Layout
::
General
{
discr
,
..
}
=>
Some
(
discr
.size
(
tcx
)),
_
=>
None
},
variant_infos
);
...
...
@@ -1901,12 +1918,16 @@ pub fn same_size(self, other: SizeSkeleton) -> bool {
/// layouts for which Rust types do not exist, such as enum variants
/// or synthetic fields of enums (i.e. discriminants) and fat pointers.
#[derive(Copy,
Clone,
Debug)]
pub
struct
Full
Layout
<
'tcx
>
{
pub
struct
Ty
Layout
<
'tcx
>
{
pub
ty
:
Ty
<
'tcx
>
,
pub
variant_index
:
Option
<
usize
>
,
pub
layout
:
&
'tcx
Layout
,
pub
fields
:
&
'tcx
FieldPlacement
,
pub
abi
:
Abi
,
cached
:
&
'tcx
CachedLayout
}
impl
<
'tcx
>
Deref
for
TyLayout
<
'tcx
>
{
type
Target
=
&
'tcx
CachedLayout
;
fn
deref
(
&
self
)
->
&&
'tcx
CachedLayout
{
&
self
.cached
}
}
pub
trait
HasTyCtxt
<
'tcx
>
:
HasDataLayout
{
...
...
@@ -1937,29 +1958,42 @@ fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'gcx> {
}
}
pub
trait
MaybeResult
<
T
>
{
fn
map_same
<
F
:
FnOnce
(
T
)
->
T
>
(
self
,
f
:
F
)
->
Self
;
}
impl
<
T
>
MaybeResult
<
T
>
for
T
{
fn
map_same
<
F
:
FnOnce
(
T
)
->
T
>
(
self
,
f
:
F
)
->
Self
{
f
(
self
)
}
}
impl
<
T
,
E
>
MaybeResult
<
T
>
for
Result
<
T
,
E
>
{
fn
map_same
<
F
:
FnOnce
(
T
)
->
T
>
(
self
,
f
:
F
)
->
Self
{
self
.map
(
f
)
}
}
pub
trait
LayoutOf
<
T
>
{
type
Full
Layout
;
type
Ty
Layout
;
fn
layout_of
(
self
,
ty
:
T
)
->
Self
::
Full
Layout
;
fn
layout_of
(
self
,
ty
:
T
)
->
Self
::
Ty
Layout
;
}
impl
<
'a
,
'tcx
>
LayoutOf
<
Ty
<
'tcx
>>
for
(
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
ty
::
ParamEnv
<
'tcx
>
)
{
type
FullLayout
=
Result
<
Full
Layout
<
'tcx
>
,
LayoutError
<
'tcx
>>
;
type
TyLayout
=
Result
<
Ty
Layout
<
'tcx
>
,
LayoutError
<
'tcx
>>
;
/// Computes the layout of a type. Note that this implicitly
/// executes in "reveal all" mode.
#[inline]
fn
layout_of
(
self
,
ty
:
Ty
<
'tcx
>
)
->
Self
::
Full
Layout
{
fn
layout_of
(
self
,
ty
:
Ty
<
'tcx
>
)
->
Self
::
Ty
Layout
{
let
(
tcx
,
param_env
)
=
self
;
let
ty
=
tcx
.normalize_associated_type_in_env
(
&
ty
,
param_env
.reveal_all
());
let
cached
=
tcx
.layout_raw
(
param_env
.reveal_all
()
.and
(
ty
))
?
;
let
layout
=
Full
Layout
{
let
layout
=
Ty
Layout
{
ty
,
variant_index
:
None
,
layout
:
&
cached
.layout
,
fields
:
&
cached
.fields
,
abi
:
cached
.abi
cached
};
// NB: This recording is normally disabled; when enabled, it
...
...
@@ -1976,22 +2010,19 @@ fn layout_of(self, ty: Ty<'tcx>) -> Self::FullLayout {
impl
<
'a
,
'tcx
>
LayoutOf
<
Ty
<
'tcx
>>
for
(
ty
::
maps
::
TyCtxtAt
<
'a
,
'tcx
,
'tcx
>
,
ty
::
ParamEnv
<
'tcx
>
)
{
type
FullLayout
=
Result
<
Full
Layout
<
'tcx
>
,
LayoutError
<
'tcx
>>
;
type
TyLayout
=
Result
<
Ty
Layout
<
'tcx
>
,
LayoutError
<
'tcx
>>
;
/// Computes the layout of a type. Note that this implicitly
/// executes in "reveal all" mode.
#[inline]
fn
layout_of
(
self
,
ty
:
Ty
<
'tcx
>
)
->
Self
::
Full
Layout
{
fn
layout_of
(
self
,
ty
:
Ty
<
'tcx
>
)
->
Self
::
Ty
Layout
{
let
(
tcx_at
,
param_env
)
=
self
;
let
ty
=
tcx_at
.tcx
.normalize_associated_type_in_env
(
&
ty
,
param_env
.reveal_all
());
let
cached
=
tcx_at
.layout_raw
(
param_env
.reveal_all
()
.and
(
ty
))
?
;
let
layout
=
Full
Layout
{
let
layout
=
Ty
Layout
{
ty
,
variant_index
:
None
,
layout
:
&
cached
.layout
,
fields
:
&
cached
.fields
,
abi
:
cached
.abi
cached
};
// NB: This recording is normally disabled; when enabled, it
...
...
@@ -2006,79 +2037,57 @@ fn layout_of(self, ty: Ty<'tcx>) -> Self::FullLayout {
}
}
impl
<
'a
,
'tcx
>
Full
Layout
<
'tcx
>
{
impl
<
'a
,
'tcx
>
Ty
Layout
<
'tcx
>
{
pub
fn
for_variant
(
&
self
,
variant_index
:
usize
)
->
Self
{
let
variants
=
match
self
.ty.sty
{
ty
::
TyAdt
(
def
,
_
)
if
def
.is_enum
()
=>
&
def
.variants
[
..
],
_
=>
&
[]
};
let
count
=
if
variants
.is_empty
()
{
0
}
else
{
variants
[
variant_index
]
.fields
.len
()
};
let
(
layout
,
fields
,
abi
)
=
match
*
self
.layout
{
Layout
::
Univariant
=>
(
self
.layout
,
self
.fields
,
self
.abi
),
let
cached
=
match
self
.layout
{
Layout
::
NullablePointer
{
ref
variants
,
..
}
|
Layout
::
General
{
ref
variants
,
..
}
=>
{
let
variant
=
&
variants
[
variant_index
];
(
&
variant
.layout
,
&
variant
.fields
,
variant
.abi
)
&
variants
[
variant_index
]
}
_
=>
bug!
()
_
=>
self
.cached
};
assert_eq!
(
fields
.count
(),
count
);
FullLayout
{
variant_index
:
Some
(
variant_index
),
layout
,
fields
,
abi
,
..*
self
assert_eq!
(
cached
.variant_index
,
Some
(
variant_index
));
TyLayout
{
ty
:
self
.ty
,
cached
}
}
fn
field_type_unnormalized
(
&
self
,
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
i
:
usize
)
->
Ty
<
'tcx
>
{
let
ptr_field_type
=
|
pointee
:
Ty
<
'tcx
>
|
{
pub
fn
field
<
C
>
(
&
self
,
cx
:
C
,
i
:
usize
)
->
C
::
TyLayout
where
C
:
LayoutOf
<
Ty
<
'tcx
>>
+
HasTyCtxt
<
'tcx
>
,
C
::
TyLayout
:
MaybeResult
<
TyLayout
<
'tcx
>>
{
let
tcx
=
cx
.tcx
();
let
ptr_field_layout
=
|
pointee
:
Ty
<
'tcx
>
|
{
assert
!
(
i
<
2
);
let
mk_ptr
=
|
ty
:
Ty
<
'tcx
>
|
{
match
self
.ty.sty
{
ty
::
TyRef
(
r
,
ty
::
TypeAndMut
{
mutbl
,
..
})
=>
{
tcx
.mk_ref
(
r
,
ty
::
TypeAndMut
{
ty
,
mutbl
})
}
ty
::
TyRawPtr
(
ty
::
TypeAndMut
{
mutbl
,
..
})
=>
{
tcx
.mk_ptr
(
ty
::
TypeAndMut
{
ty
,
mutbl
})
}
ty
::
TyAdt
(
def
,
_
)
if
def
.is_box
()
=>
{
tcx
.mk_box
(
ty
)
}
_
=>
bug!
()
}
};
let
slice
=
|
element
:
Ty
<
'tcx
>
|
{
if
i
==
0
{
mk_ptr
(
element
)
}
else
{
tcx
.types.usize
}
};
match
tcx
.struct_tail
(
pointee
)
.sty
{
ty
::
TySlice
(
element
)
=>
slice
(
element
),
ty
::
TyStr
=>
slice
(
tcx
.types.u8
),
// Reuse the fat *T type as its own thin pointer data field.
// This provides information about e.g. DST struct pointees
// (which may have no non-DST form), and will work as long
// as the `Abi` or `FieldPlacement` is checked by users.
if
i
==
0
{
return
cx
.layout_of
(
Pointer
.to_ty
(
tcx
))
.map_same
(|
mut
ptr_layout
|
{
ptr_layout
.ty
=
self
.ty
;
ptr_layout
});
}
let
meta_ty
=
match
tcx
.struct_tail
(
pointee
)
.sty
{
ty
::
TySlice
(
_
)
|
ty
::
TyStr
=>
tcx
.types.usize
,
ty
::
TyDynamic
(
..
)
=>
{
if
i
==
0
{
mk_ptr
(
tcx
.mk_nil
())
}
else
{
Pointer
.to_ty
(
tcx
)
}
// FIXME(eddyb) use an usize/fn() array with
// the correct number of vtables slots.
tcx
.mk_imm_ref
(
tcx
.types.re_static
,
tcx
.mk_nil
())
}
_
=>
bug!
(
"FullLayout::field_type({:?}): not applicable"
,
self
)
}
_
=>
bug!
(
"TyLayout::field_type({:?}): not applicable"
,
self
)
};
cx
.layout_of
(
meta_ty
)
};
match
self
.ty.sty
{
cx
.layout_of
(
match
self
.ty.sty
{
ty
::
TyBool
|
ty
::
TyChar
|
ty
::
TyInt
(
_
)
|
...
...
@@ -2089,16 +2098,16 @@ fn field_type_unnormalized(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, i: usize) -> Ty<'
ty
::
TyFnDef
(
..
)
|
ty
::
TyDynamic
(
..
)
|
ty
::
TyForeign
(
..
)
=>
{
bug!
(
"
Full
Layout::field_type({:?}): not applicable"
,
self
)
bug!
(
"
Ty
Layout::field_type({:?}): not applicable"
,
self
)
}
// Potentially-fat pointers.
ty
::
TyRef
(
_
,
ty
::
TypeAndMut
{
ty
:
pointee
,
..
})
|
ty
::
TyRawPtr
(
ty
::
TypeAndMut
{
ty
:
pointee
,
..
})
=>
{
ptr_field_type
(
pointee
)
return
ptr_field_layout
(
pointee
);
}
ty
::
TyAdt
(
def
,
_
)
if
def
.is_box
()
=>
{
ptr_field_type
(
self
.ty
.boxed_ty
())
return
ptr_field_layout
(
self
.ty
.boxed_ty
());
}
// Arrays and slices.
...
...
@@ -2126,16 +2135,16 @@ fn field_type_unnormalized(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, i: usize) -> Ty<'
ty
::
TyAdt
(
def
,
substs
)
=>
{
let
v
=
if
def
.is_enum
()
{
match
self
.variant_index
{
None
=>
match
*
self
.layout
{
None
=>
match
self
.layout
{
// Discriminant field for enums (where applicable).
Layout
::
General
{
discr
,
..
}
|
Layout
::
NullablePointer
{
discr
,
..
}
=>
{
return
[
discr
.to_ty
(
tcx
)][
i
];
return
cx
.layout_of
([
discr
.to_ty
(
tcx
)][
i
]);
}
_
=>
{
bug!
(
"TyLayout::field_type: enum `{}` has no discriminant"
,
self
.ty
)
}
_
if
def
.variants
.len
()
>
1
=>
return
[][
i
],
// Enums with one variant behave like structs.
_
=>
0
},
Some
(
v
)
=>
v
}
...
...
@@ -2148,16 +2157,9 @@ fn field_type_unnormalized(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, i: usize) -> Ty<'
ty
::
TyProjection
(
_
)
|
ty
::
TyAnon
(
..
)
|
ty
::
TyParam
(
_
)
|
ty
::
TyInfer
(
_
)
|
ty
::
TyError
=>
{
bug!
(
"
Full
Layout::field_type: unexpected type `{}`"
,
self
.ty
)
bug!
(
"
Ty
Layout::field_type: unexpected type `{}`"
,
self
.ty
)
}
}
}
pub
fn
field
<
C
:
LayoutOf
<
Ty
<
'tcx
>>
+
HasTyCtxt
<
'tcx
>>
(
&
self
,
cx
:
C
,
i
:
usize
)
->
C
::
FullLayout
{
cx
.layout_of
(
self
.field_type_unnormalized
(
cx
.tcx
(),
i
))
})
}
/// Returns true if the layout corresponds to an unsized type.
...
...
@@ -2198,11 +2200,11 @@ pub fn primitive_align<C: HasDataLayout>(&self, cx: C) -> Align {
// FIXME(eddyb) track value ranges and traverse already optimized enums.
fn
non_zero_field
<
C
>
(
&
self
,
cx
:
C
)
->
Result
<
Option
<
(
Size
,
Primitive
)
>
,
LayoutError
<
'tcx
>>
where
C
:
LayoutOf
<
Ty
<
'tcx
>
,
Full
Layout
=
Result
<
Self
,
LayoutError
<
'tcx
>>>
+
where
C
:
LayoutOf
<
Ty
<
'tcx
>
,
Ty
Layout
=
Result
<
Self
,
LayoutError
<
'tcx
>>>
+
HasTyCtxt
<
'tcx
>
{
let
tcx
=
cx
.tcx
();
match
(
self
.layout
,
self
.abi
,
&
self
.ty.sty
)
{
match
(
&
self
.layout
,
self
.abi
,
&
self
.ty.sty
)
{
// FIXME(eddyb) check this via value ranges on scalars.
(
&
Layout
::
Scalar
,
Abi
::
Scalar
(
Pointer
),
&
ty
::
TyRef
(
..
))
|
(
&
Layout
::
Scalar
,
Abi
::
Scalar
(
Pointer
),
&
ty
::
TyFnPtr
(
..
))
=>
{
...
...
@@ -2238,7 +2240,7 @@ fn non_zero_field<C>(&self, cx: C)
// Perhaps one of the fields is non-zero, let's recurse and find out.
_
=>
{
if
let
FieldPlacement
::
Array
{
count
,
..
}
=
*
self
.fields
{
if
let
FieldPlacement
::
Array
{
count
,
..
}
=
self
.fields
{
if
count
>
0
{
return
self
.field
(
cx
,
0
)
?
.non_zero_field
(
cx
);
}
...
...
@@ -2341,6 +2343,7 @@ fn hash_stable<W: StableHasherResult>(&self,
}
impl_stable_hash_for!
(
struct
::
ty
::
layout
::
CachedLayout
{
variant_index
,
layout
,
fields
,
abi
...
...
src/librustc_lint/types.rs
浏览文件 @
b723af28
...
...
@@ -753,7 +753,7 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
bug!
(
"failed to get layout for `{}`: {}"
,
t
,
e
)
});
if
let
Layout
::
General
{
ref
variants
,
discr
,
..
}
=
*
layout
.layout
{
if
let
Layout
::
General
{
ref
variants
,
discr
,
..
}
=
layout
.layout
{
let
discr_size
=
discr
.size
(
cx
.tcx
)
.bytes
();
debug!
(
"enum `{}` is {} bytes large with layout:
\n
{:#?}"
,
...
...
src/librustc_llvm/ffi.rs
浏览文件 @
b723af28
...
...
@@ -1316,11 +1316,6 @@ pub fn LLVMStructSetBody(StructTy: TypeRef,
ElementCount
:
c_uint
,
Packed
:
Bool
);
pub
fn
LLVMConstNamedStruct
(
S
:
TypeRef
,
ConstantVals
:
*
const
ValueRef
,
Count
:
c_uint
)
->
ValueRef
;
/// Enables LLVM debug output.
pub
fn
LLVMRustSetDebug
(
Enabled
:
c_int
);
...
...
src/librustc_trans/abi.rs
浏览文件 @
b723af28
...
...
@@ -36,7 +36,7 @@
use
rustc
::
hir
;
use
rustc
::
ty
::{
self
,
Ty
};
use
rustc
::
ty
::
layout
::{
self
,
Align
,
Size
,
Full
Layout
};
use
rustc
::
ty
::
layout
::{
self
,
Align
,
Size
,
Ty
Layout
};
use
rustc
::
ty
::
layout
::{
HasDataLayout
,
LayoutOf
};
use
rustc_back
::
PanicStrategy
;
...
...
@@ -275,7 +275,7 @@ pub trait LayoutExt<'tcx> {
fn
homogeneous_aggregate
<
'a
>
(
&
self
,
ccx
:
&
CrateContext
<
'a
,
'tcx
>
)
->
Option
<
Reg
>
;
}
impl
<
'tcx
>
LayoutExt
<
'tcx
>
for
Full
Layout
<
'tcx
>
{
impl
<
'tcx
>
LayoutExt
<
'tcx
>
for
Ty
Layout
<
'tcx
>
{
fn
is_aggregate
(
&
self
)
->
bool
{
match
self
.abi
{
layout
::
Abi
::
Scalar
(
_
)
|
...
...
@@ -311,7 +311,7 @@ fn homogeneous_aggregate<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Option<Reg>
let
mut
total
=
Size
::
from_bytes
(
0
);
let
mut
result
=
None
;
let
is_union
=
match
*
self
.fields
{
let
is_union
=
match
self
.fields
{
layout
::
FieldPlacement
::
Array
{
count
,
..
}
=>
{
if
count
>
0
{
return
self
.field
(
ccx
,
0
)
.homogeneous_aggregate
(
ccx
);
...
...
@@ -424,7 +424,7 @@ pub fn llvm_type(&self, ccx: &CrateContext) -> Type {
#[derive(Debug)]
pub
struct
ArgType
<
'tcx
>
{
kind
:
ArgKind
,
pub
layout
:
Full
Layout
<
'tcx
>
,
pub
layout
:
Ty
Layout
<
'tcx
>
,
/// Cast target, either a single uniform or a pair of registers.
pub
cast
:
Option
<
CastTarget
>
,
/// Dummy argument, which is emitted before the real argument.
...
...
@@ -435,7 +435,7 @@ pub struct ArgType<'tcx> {
}
impl
<
'a
,
'tcx
>
ArgType
<
'tcx
>
{
fn
new
(
layout
:
Full
Layout
<
'tcx
>
)
->
ArgType
<
'tcx
>
{
fn
new
(
layout
:
Ty
Layout
<
'tcx
>
)
->
ArgType
<
'tcx
>
{
ArgType
{
kind
:
ArgKind
::
Direct
,
layout
,
...
...
@@ -610,7 +610,7 @@ pub fn of_instance(ccx: &CrateContext<'a, 'tcx>, instance: &ty::Instance<'tcx>)
let
fn_ty
=
instance_ty
(
ccx
.tcx
(),
&
instance
);
let
sig
=
ty_fn_sig
(
ccx
,
fn_ty
);
let
sig
=
ccx
.tcx
()
.erase_late_bound_regions_and_normalize
(
&
sig
);
Self
::
new
(
ccx
,
sig
,
&
[])
FnType
::
new
(
ccx
,
sig
,
&
[])
}
pub
fn
new
(
ccx
:
&
CrateContext
<
'a
,
'tcx
>
,
...
...
src/librustc_trans/base.rs
浏览文件 @
b723af28
...
...
@@ -28,6 +28,7 @@
use
super
::
ModuleTranslation
;
use
super
::
ModuleKind
;
use
abi
;
use
assert_module_sources
;
use
back
::
link
;
use
back
::
symbol_export
;
...
...
@@ -40,7 +41,7 @@
use
rustc
::
middle
::
trans
::{
Linkage
,
Visibility
,
Stats
};
use
rustc
::
middle
::
cstore
::{
EncodedMetadata
,
EncodedMetadataHashes
};
use
rustc
::
ty
::{
self
,
Ty
,
TyCtxt
};
use
rustc
::
ty
::
layout
::{
self
,
Align
,
Full
Layout
,
LayoutOf
};
use
rustc
::
ty
::
layout
::{
self
,
Align
,
Ty
Layout
,
LayoutOf
};
use
rustc
::
ty
::
maps
::
Providers
;
use
rustc
::
dep_graph
::{
DepNode
,
DepKind
,
DepConstructor
};
use
rustc
::
middle
::
cstore
::{
self
,
LinkMeta
,
LinkagePreference
};
...
...
@@ -68,7 +69,7 @@
use
time_graph
;
use
trans_item
::{
TransItem
,
BaseTransItemExt
,
TransItemExt
,
DefPathBasedNames
};
use
type_
::
Type
;
use
type_of
::
{
self
,
LayoutLlvmExt
}
;
use
type_of
::
LayoutLlvmExt
;
use
rustc
::
util
::
nodemap
::{
NodeSet
,
FxHashMap
,
FxHashSet
,
DefIdSet
};
use
CrateInfo
;
...
...
@@ -203,8 +204,10 @@ pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
old_info
.expect
(
"unsized_info: missing old info for trait upcast"
)
}
(
_
,
&
ty
::
TyDynamic
(
ref
data
,
..
))
=>
{
let
vtable_ptr
=
ccx
.layout_of
(
ccx
.tcx
()
.mk_mut_ptr
(
target
))
.field
(
ccx
,
abi
::
FAT_PTR_EXTRA
);
consts
::
ptrcast
(
meth
::
get_vtable
(
ccx
,
source
,
data
.principal
()),
Type
::
vtable_ptr
(
ccx
))
vtable_ptr
.llvm_type
(
ccx
))
}
_
=>
bug!
(
"unsized_info: invalid unsizing {:?} -> {:?}"
,
source
,
...
...
@@ -255,8 +258,8 @@ pub fn coerce_unsized_into<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
// i.e. &'a fmt::Debug+Send => &'a fmt::Debug
// So we need to pointercast the base to ensure
// the types match up.
let
llcast_ty
=
type_of
::
fat_ptr_base_ty
(
bcx
.ccx
,
dst_ty
);
(
bcx
.pointercast
(
base
,
llcast_ty
),
info
)
let
thin_ptr
=
dst
.layout
.field
(
bcx
.ccx
,
abi
::
FAT_PTR_ADDR
);
(
bcx
.pointercast
(
base
,
thin_ptr
.llvm_type
(
bcx
.ccx
)
),
info
)
}
OperandValue
::
Immediate
(
base
)
=>
{
unsize_thin_ptr
(
bcx
,
base
,
src_ty
,
dst_ty
)
...
...
@@ -371,7 +374,7 @@ pub fn from_immediate(bcx: &Builder, val: ValueRef) -> ValueRef {
}
}
pub
fn
to_immediate
(
bcx
:
&
Builder
,
val
:
ValueRef
,
layout
:
layout
::
Full
Layout
)
->
ValueRef
{
pub
fn
to_immediate
(
bcx
:
&
Builder
,
val
:
ValueRef
,
layout
:
layout
::
Ty
Layout
)
->
ValueRef
{
if
let
layout
::
Abi
::
Scalar
(
layout
::
Int
(
layout
::
I1
,
_
))
=
layout
.abi
{
bcx
.trunc
(
val
,
Type
::
i1
(
bcx
.ccx
))
}
else
{
...
...
@@ -400,7 +403,7 @@ pub fn memcpy_ty<'a, 'tcx>(
bcx
:
&
Builder
<
'a
,
'tcx
>
,
dst
:
ValueRef
,
src
:
ValueRef
,
layout
:
Full
Layout
<
'tcx
>
,
layout
:
Ty
Layout
<
'tcx
>
,
align
:
Option
<
Align
>
,
)
{
let
ccx
=
bcx
.ccx
;
...
...
src/librustc_trans/cabi_s390x.rs
浏览文件 @
b723af28
...
...
@@ -14,7 +14,7 @@
use
abi
::{
FnType
,
ArgType
,
LayoutExt
,
Reg
};
use
context
::
CrateContext
;
use
rustc
::
ty
::
layout
::{
self
,
Full
Layout
};
use
rustc
::
ty
::
layout
::{
self
,
Ty
Layout
};
fn
classify_ret_ty
<
'a
,
'tcx
>
(
ccx
:
&
CrateContext
<
'a
,
'tcx
>
,
ret
:
&
mut
ArgType
<
'tcx
>
)
{
if
!
ret
.layout
.is_aggregate
()
&&
ret
.layout
.size
(
ccx
)
.bits
()
<=
64
{
...
...
@@ -25,7 +25,7 @@ fn classify_ret_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ret: &mut ArgType<'tc
}
fn
is_single_fp_element
<
'a
,
'tcx
>
(
ccx
:
&
CrateContext
<
'a
,
'tcx
>
,
layout
:
Full
Layout
<
'tcx
>
)
->
bool
{
layout
:
Ty
Layout
<
'tcx
>
)
->
bool
{
match
layout
.abi
{
layout
::
Abi
::
Scalar
(
layout
::
F32
)
|
layout
::
Abi
::
Scalar
(
layout
::
F64
)
=>
true
,
...
...
src/librustc_trans/cabi_x86.rs
浏览文件 @
b723af28
...
...
@@ -11,7 +11,7 @@
use
abi
::{
ArgAttribute
,
FnType
,
LayoutExt
,
Reg
,
RegKind
};
use
common
::
CrateContext
;
use
rustc
::
ty
::
layout
::{
self
,
Full
Layout
};
use
rustc
::
ty
::
layout
::{
self
,
Ty
Layout
};
#[derive(PartialEq)]
pub
enum
Flavor
{
...
...
@@ -20,7 +20,7 @@ pub enum Flavor {
}
fn
is_single_fp_element
<
'a
,
'tcx
>
(
ccx
:
&
CrateContext
<
'a
,
'tcx
>
,
layout
:
Full
Layout
<
'tcx
>
)
->
bool
{
layout
:
Ty
Layout
<
'tcx
>
)
->
bool
{
match
layout
.abi
{
layout
::
Abi
::
Scalar
(
layout
::
F32
)
|
layout
::
Abi
::
Scalar
(
layout
::
F64
)
=>
true
,
...
...
src/librustc_trans/cabi_x86_64.rs
浏览文件 @
b723af28
...
...
@@ -14,7 +14,7 @@
use
abi
::{
ArgType
,
ArgAttribute
,
CastTarget
,
FnType
,
LayoutExt
,
Reg
,
RegKind
};
use
context
::
CrateContext
;
use
rustc
::
ty
::
layout
::{
self
,
Layout
,
Full
Layout
,
Size
};
use
rustc
::
ty
::
layout
::{
self
,
Layout
,
Ty
Layout
,
Size
};
#[derive(Clone,
Copy,
PartialEq,
Debug)]
enum
Class
{
...
...
@@ -53,7 +53,7 @@ fn unify(cls: &mut [Class],
}
fn
classify
<
'a
,
'tcx
>
(
ccx
:
&
CrateContext
<
'a
,
'tcx
>
,
layout
:
Full
Layout
<
'tcx
>
,
layout
:
Ty
Layout
<
'tcx
>
,
cls
:
&
mut
[
Class
],
off
:
Size
)
->
Result
<
(),
Memory
>
{
...
...
@@ -90,7 +90,7 @@ fn classify<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
// FIXME(eddyb) have to work around Rust enums for now.
// Fix is either guarantee no data where there is no field,
// by putting variants in fields, or be more clever.
match
*
layout
.layout
{
match
layout
.layout
{
Layout
::
General
{
..
}
|
Layout
::
NullablePointer
{
..
}
=>
return
Err
(
Memory
),
_
=>
{}
...
...
src/librustc_trans/common.rs
浏览文件 @
b723af28
...
...
@@ -54,20 +54,11 @@ pub fn type_is_fat_ptr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) ->
}
}
pub
fn
type_is_immediate
<
'a
,
'tcx
>
(
ccx
:
&
CrateContext
<
'a
,
'tcx
>
,
ty
:
Ty
<
'tcx
>
)
->
bool
{
let
layout
=
ccx
.layout_of
(
ty
);
match
layout
.abi
{
layout
::
Abi
::
Scalar
(
_
)
|
layout
::
Abi
::
Vector
{
..
}
=>
true
,
layout
::
Abi
::
Aggregate
{
..
}
=>
layout
.is_zst
()
}
}
/// Returns true if the type is represented as a pair of immediates.
pub
fn
type_is_imm_pair
<
'a
,
'tcx
>
(
ccx
:
&
CrateContext
<
'a
,
'tcx
>
,
ty
:
Ty
<
'tcx
>
)
->
bool
{
let
layout
=
ccx
.layout_of
(
ty
);
match
*
layout
.fields
{
match
layout
.fields
{
layout
::
FieldPlacement
::
Arbitrary
{
..
}
=>
{
// There must be only 2 fields.
if
layout
.fields
.count
()
!=
2
{
...
...
@@ -75,8 +66,8 @@ pub fn type_is_imm_pair<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>)
}
// The two fields must be both immediates.
type_is_immediate
(
ccx
,
layout
.field
(
ccx
,
0
)
.ty
)
&&
type_is_immediate
(
ccx
,
layout
.field
(
ccx
,
1
)
.ty
)
layout
.field
(
ccx
,
0
)
.is_llvm_immediate
(
)
&&
layout
.field
(
ccx
,
1
)
.is_llvm_immediate
(
)
}
_
=>
false
}
...
...
@@ -256,16 +247,7 @@ pub fn C_str_slice(cx: &CrateContext, s: InternedString) -> ValueRef {
let
len
=
s
.len
();
let
cs
=
consts
::
ptrcast
(
C_cstr
(
cx
,
s
,
false
),
cx
.layout_of
(
cx
.tcx
()
.mk_str
())
.llvm_type
(
cx
)
.ptr_to
());
let
empty
=
C_array
(
Type
::
i8
(
cx
),
&
[]);
assert_eq!
(
abi
::
FAT_PTR_ADDR
,
0
);
assert_eq!
(
abi
::
FAT_PTR_EXTRA
,
1
);
C_named_struct
(
cx
.str_slice_type
(),
&
[
empty
,
cs
,
empty
,
C_usize
(
cx
,
len
as
u64
),
empty
])
C_fat_ptr
(
cx
,
cs
,
C_usize
(
cx
,
len
as
u64
))
}
pub
fn
C_fat_ptr
(
cx
:
&
CrateContext
,
ptr
:
ValueRef
,
meta
:
ValueRef
)
->
ValueRef
{
...
...
@@ -293,12 +275,6 @@ pub fn C_struct_in_context(llcx: ContextRef, elts: &[ValueRef], packed: bool) ->
}
}
pub
fn
C_named_struct
(
t
:
Type
,
elts
:
&
[
ValueRef
])
->
ValueRef
{
unsafe
{
llvm
::
LLVMConstNamedStruct
(
t
.to_ref
(),
elts
.as_ptr
(),
elts
.len
()
as
c_uint
)
}
}
pub
fn
C_array
(
ty
:
Type
,
elts
:
&
[
ValueRef
])
->
ValueRef
{
unsafe
{
return
llvm
::
LLVMConstArray
(
ty
.to_ref
(),
elts
.as_ptr
(),
elts
.len
()
as
c_uint
);
...
...
src/librustc_trans/context.rs
浏览文件 @
b723af28
...
...
@@ -24,14 +24,13 @@
use
partitioning
::
CodegenUnit
;
use
type_
::
Type
;
use
type_of
::
LayoutLlvmExt
;
use
rustc_data_structures
::
base_n
;
use
rustc
::
middle
::
trans
::
Stats
;
use
rustc_data_structures
::
stable_hasher
::
StableHashingContextProvider
;
use
rustc
::
session
::
config
::{
self
,
NoDebugInfo
};
use
rustc
::
session
::
Session
;
use
rustc
::
ty
::
layout
::{
LayoutError
,
LayoutOf
,
Full
Layout
};
use
rustc
::
ty
::
layout
::{
LayoutError
,
LayoutOf
,
Ty
Layout
};
use
rustc
::
ty
::{
self
,
Ty
,
TyCtxt
};
use
rustc
::
util
::
nodemap
::
FxHashMap
;
use
rustc_trans_utils
;
...
...
@@ -101,9 +100,9 @@ pub struct LocalCrateContext<'a, 'tcx: 'a> {
/// See http://llvm.org/docs/LangRef.html#the-llvm-used-global-variable for details
used_statics
:
RefCell
<
Vec
<
ValueRef
>>
,
lltypes
:
RefCell
<
FxHashMap
<
Ty
<
'tcx
>
,
Type
>>
,
lltypes
:
RefCell
<
FxHashMap
<
(
Ty
<
'tcx
>
,
Option
<
usize
>
),
Type
>>
,
scalar_lltypes
:
RefCell
<
FxHashMap
<
Ty
<
'tcx
>
,
Type
>>
,
isize_ty
:
Type
,
str_slice_type
:
Type
,
dbg_cx
:
Option
<
debuginfo
::
CrateDebugContext
<
'tcx
>>
,
...
...
@@ -378,8 +377,8 @@ pub fn new(shared: &SharedCrateContext<'a, 'tcx>,
statics_to_rauw
:
RefCell
::
new
(
Vec
::
new
()),
used_statics
:
RefCell
::
new
(
Vec
::
new
()),
lltypes
:
RefCell
::
new
(
FxHashMap
()),
scalar_lltypes
:
RefCell
::
new
(
FxHashMap
()),
isize_ty
:
Type
::
from_ref
(
ptr
::
null_mut
()),
str_slice_type
:
Type
::
from_ref
(
ptr
::
null_mut
()),
dbg_cx
,
eh_personality
:
Cell
::
new
(
None
),
eh_unwind_resume
:
Cell
::
new
(
None
),
...
...
@@ -389,28 +388,19 @@ pub fn new(shared: &SharedCrateContext<'a, 'tcx>,
placeholder
:
PhantomData
,
};
let
(
isize_ty
,
str_slice_ty
,
mut
local_ccx
)
=
{
let
(
isize_ty
,
mut
local_ccx
)
=
{
// Do a little dance to create a dummy CrateContext, so we can
// create some things in the LLVM module of this codegen unit
let
mut
local_ccxs
=
vec!
[
local_ccx
];
let
(
isize_ty
,
str_slice_ty
)
=
{
let
isize_ty
=
{
let
dummy_ccx
=
LocalCrateContext
::
dummy_ccx
(
shared
,
local_ccxs
.as_mut_slice
());
let
mut
str_slice_ty
=
Type
::
named_struct
(
&
dummy_ccx
,
"str_slice"
);
str_slice_ty
.set_struct_body
(
&
[
Type
::
array
(
&
Type
::
i8
(
&
dummy_ccx
),
0
),
dummy_ccx
.layout_of
(
shared
.tcx
.mk_str
())
.llvm_type
(
&
dummy_ccx
)
.ptr_to
(),
Type
::
array
(
&
Type
::
i8
(
&
dummy_ccx
),
0
),
Type
::
isize
(
&
dummy_ccx
),
Type
::
array
(
&
Type
::
i8
(
&
dummy_ccx
),
0
)
],
false
);
(
Type
::
isize
(
&
dummy_ccx
),
str_slice_ty
)
Type
::
isize
(
&
dummy_ccx
)
};
(
isize_ty
,
str_slice_ty
,
local_ccxs
.pop
()
.unwrap
())
(
isize_ty
,
local_ccxs
.pop
()
.unwrap
())
};
local_ccx
.isize_ty
=
isize_ty
;
local_ccx
.str_slice_type
=
str_slice_ty
;
local_ccx
}
...
...
@@ -515,10 +505,14 @@ pub fn used_statics<'a>(&'a self) -> &'a RefCell<Vec<ValueRef>> {
&
self
.local
()
.used_statics
}
pub
fn
lltypes
<
'a
>
(
&
'a
self
)
->
&
'a
RefCell
<
FxHashMap
<
Ty
<
'tcx
>
,
Type
>>
{
pub
fn
lltypes
<
'a
>
(
&
'a
self
)
->
&
'a
RefCell
<
FxHashMap
<
(
Ty
<
'tcx
>
,
Option
<
usize
>
)
,
Type
>>
{
&
self
.local
()
.lltypes
}
pub
fn
scalar_lltypes
<
'a
>
(
&
'a
self
)
->
&
'a
RefCell
<
FxHashMap
<
Ty
<
'tcx
>
,
Type
>>
{
&
self
.local
()
.scalar_lltypes
}
pub
fn
stats
<
'a
>
(
&
'a
self
)
->
&
'a
RefCell
<
Stats
>
{
&
self
.local
()
.stats
}
...
...
@@ -527,10 +521,6 @@ pub fn isize_ty(&self) -> Type {
self
.local
()
.isize_ty
}
pub
fn
str_slice_type
(
&
self
)
->
Type
{
self
.local
()
.str_slice_type
}
pub
fn
dbg_cx
<
'a
>
(
&
'a
self
)
->
&
'a
Option
<
debuginfo
::
CrateDebugContext
<
'tcx
>>
{
&
self
.local
()
.dbg_cx
}
...
...
@@ -669,9 +659,9 @@ fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
}
impl
<
'a
,
'tcx
>
LayoutOf
<
Ty
<
'tcx
>>
for
&
'a
SharedCrateContext
<
'a
,
'tcx
>
{
type
FullLayout
=
Full
Layout
<
'tcx
>
;
type
TyLayout
=
Ty
Layout
<
'tcx
>
;
fn
layout_of
(
self
,
ty
:
Ty
<
'tcx
>
)
->
Self
::
Full
Layout
{
fn
layout_of
(
self
,
ty
:
Ty
<
'tcx
>
)
->
Self
::
Ty
Layout
{
(
self
.tcx
,
ty
::
ParamEnv
::
empty
(
traits
::
Reveal
::
All
))
.layout_of
(
ty
)
.unwrap_or_else
(|
e
|
match
e
{
...
...
@@ -682,10 +672,10 @@ fn layout_of(self, ty: Ty<'tcx>) -> Self::FullLayout {
}
impl
<
'a
,
'tcx
>
LayoutOf
<
Ty
<
'tcx
>>
for
&
'a
CrateContext
<
'a
,
'tcx
>
{
type
FullLayout
=
Full
Layout
<
'tcx
>
;
type
TyLayout
=
Ty
Layout
<
'tcx
>
;
fn
layout_of
(
self
,
ty
:
Ty
<
'tcx
>
)
->
Self
::
Full
Layout
{
fn
layout_of
(
self
,
ty
:
Ty
<
'tcx
>
)
->
Self
::
Ty
Layout
{
self
.shared
.layout_of
(
ty
)
}
}
...
...
src/librustc_trans/debuginfo/metadata.rs
浏览文件 @
b723af28
...
...
@@ -32,7 +32,7 @@
use
rustc
::
ich
::
Fingerprint
;
use
common
::{
self
,
CrateContext
};
use
rustc
::
ty
::{
self
,
AdtKind
,
Ty
};
use
rustc
::
ty
::
layout
::{
self
,
Align
,
LayoutOf
,
Size
,
Full
Layout
};
use
rustc
::
ty
::
layout
::{
self
,
Align
,
LayoutOf
,
Size
,
Ty
Layout
};
use
rustc
::
session
::{
Session
,
config
};
use
rustc
::
util
::
nodemap
::
FxHashMap
;
use
rustc
::
util
::
common
::
path2cstr
;
...
...
@@ -1052,7 +1052,7 @@ fn prepare_tuple_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
//=-----------------------------------------------------------------------------
struct
UnionMemberDescriptionFactory
<
'tcx
>
{
layout
:
Full
Layout
<
'tcx
>
,
layout
:
Ty
Layout
<
'tcx
>
,
variant
:
&
'tcx
ty
::
VariantDef
,
span
:
Span
,
}
...
...
@@ -1119,7 +1119,7 @@ fn prepare_union_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
// offset of zero bytes).
struct
EnumMemberDescriptionFactory
<
'tcx
>
{
enum_type
:
Ty
<
'tcx
>
,
type_rep
:
Full
Layout
<
'tcx
>
,
type_rep
:
Ty
Layout
<
'tcx
>
,
discriminant_type_metadata
:
Option
<
DIType
>
,
containing_scope
:
DIScope
,
span
:
Span
,
...
...
@@ -1129,7 +1129,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
fn
create_member_descriptions
<
'a
>
(
&
self
,
cx
:
&
CrateContext
<
'a
,
'tcx
>
)
->
Vec
<
MemberDescription
>
{
let
adt
=
&
self
.enum_type
.ty_adt_def
()
.unwrap
();
match
*
self
.type_rep.layout
{
match
self
.type_rep.layout
{
layout
::
Layout
::
General
{
ref
variants
,
..
}
=>
{
let
discriminant_info
=
RegularDiscriminant
(
self
.discriminant_type_metadata
.expect
(
""
));
...
...
@@ -1220,7 +1220,7 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
// of discriminant instead of us having to recover its path.
fn
compute_field_path
<
'a
,
'tcx
>
(
ccx
:
&
CrateContext
<
'a
,
'tcx
>
,
name
:
&
mut
String
,
layout
:
Full
Layout
<
'tcx
>
,
layout
:
Ty
Layout
<
'tcx
>
,
offset
:
Size
,
size
:
Size
)
{
for
i
in
0
..
layout
.fields
.count
()
{
...
...
@@ -1300,7 +1300,7 @@ enum EnumDiscriminantInfo {
// descriptions of the fields of the variant. This is a rudimentary version of a
// full RecursiveTypeDescription.
fn
describe_enum_variant
<
'a
,
'tcx
>
(
cx
:
&
CrateContext
<
'a
,
'tcx
>
,
layout
:
layout
::
Full
Layout
<
'tcx
>
,
layout
:
layout
::
Ty
Layout
<
'tcx
>
,
variant
:
&
'tcx
ty
::
VariantDef
,
discriminant_info
:
EnumDiscriminantInfo
,
containing_scope
:
DIScope
,
...
...
@@ -1431,7 +1431,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
let
type_rep
=
cx
.layout_of
(
enum_type
);
let
discriminant_type_metadata
=
match
*
type_rep
.layout
{
let
discriminant_type_metadata
=
match
type_rep
.layout
{
layout
::
Layout
::
NullablePointer
{
..
}
|
layout
::
Layout
::
Univariant
{
..
}
=>
None
,
layout
::
Layout
::
General
{
discr
,
..
}
=>
Some
(
discriminant_type_metadata
(
discr
)),
...
...
src/librustc_trans/meth.rs
浏览文件 @
b723af28
...
...
@@ -9,6 +9,7 @@
// except according to those terms.
use
llvm
::
ValueRef
;
use
abi
::
FnType
;
use
callee
;
use
common
::
*
;
use
builder
::
Builder
;
...
...
@@ -32,10 +33,13 @@ pub fn from_index(index: usize) -> Self {
VirtualIndex
(
index
as
u64
+
3
)
}
pub
fn
get_fn
(
self
,
bcx
:
&
Builder
<
'a
,
'tcx
>
,
llvtable
:
ValueRef
)
->
ValueRef
{
pub
fn
get_fn
(
self
,
bcx
:
&
Builder
<
'a
,
'tcx
>
,
llvtable
:
ValueRef
,
fn_ty
:
&
FnType
<
'tcx
>
)
->
ValueRef
{
// Load the data pointer from the object.
debug!
(
"get_fn({:?}, {:?})"
,
Value
(
llvtable
),
self
);
let
llvtable
=
bcx
.pointercast
(
llvtable
,
fn_ty
.llvm_type
(
bcx
.ccx
)
.ptr_to
()
.ptr_to
());
let
ptr
=
bcx
.load_nonnull
(
bcx
.inbounds_gep
(
llvtable
,
&
[
C_usize
(
bcx
.ccx
,
self
.0
)]),
None
);
// Vtable loads are invariant
bcx
.set_invariant_load
(
ptr
);
...
...
src/librustc_trans/mir/analyze.rs
浏览文件 @
b723af28
...
...
@@ -20,6 +20,7 @@
use
rustc
::
ty
;
use
rustc
::
ty
::
layout
::
LayoutOf
;
use
common
;
use
type_of
::
LayoutLlvmExt
;
use
super
::
MirContext
;
pub
fn
lvalue_locals
<
'a
,
'tcx
>
(
mircx
:
&
MirContext
<
'a
,
'tcx
>
)
->
BitVector
{
...
...
@@ -31,21 +32,14 @@ pub fn lvalue_locals<'a, 'tcx>(mircx: &MirContext<'a, 'tcx>) -> BitVector {
for
(
index
,
ty
)
in
mir
.local_decls
.iter
()
.map
(|
l
|
l
.ty
)
.enumerate
()
{
let
ty
=
mircx
.monomorphize
(
&
ty
);
debug!
(
"local {} has type {:?}"
,
index
,
ty
);
if
ty
.is_scalar
()
||
ty
.is_box
()
||
ty
.is_region_ptr
()
||
ty
.is_simd
()
||
mircx
.ccx
.layout_of
(
ty
)
.is_zst
()
{
if
mircx
.ccx
.layout_of
(
ty
)
.is_llvm_immediate
()
{
// These sorts of types are immediates that we can store
// in an ValueRef without an alloca.
assert
!
(
common
::
type_is_immediate
(
mircx
.ccx
,
ty
)
||
common
::
type_is_fat_ptr
(
mircx
.ccx
,
ty
));
}
else
if
common
::
type_is_imm_pair
(
mircx
.ccx
,
ty
)
{
// We allow pairs and uses of any of their 2 fields.
}
else
{
// These sorts of types require an alloca. Note that
//
type_is
_immediate() may *still* be true, particularly
//
is_llvm
_immediate() may *still* be true, particularly
// for newtypes, but we currently force some types
// (e.g. structs) into an alloca unconditionally, just so
// that we don't have to deal with having two pathways
...
...
@@ -179,9 +173,9 @@ fn visit_local(&mut self,
LvalueContext
::
StorageLive
|
LvalueContext
::
StorageDead
|
LvalueContext
::
Validate
|
LvalueContext
::
Inspect
|
LvalueContext
::
Consume
=>
{}
LvalueContext
::
Inspect
|
LvalueContext
::
Store
|
LvalueContext
::
Borrow
{
..
}
|
LvalueContext
::
Projection
(
..
)
=>
{
...
...
src/librustc_trans/mir/block.rs
浏览文件 @
b723af28
...
...
@@ -274,13 +274,22 @@ fn trans_terminator(&mut self,
}
let
lvalue
=
self
.trans_lvalue
(
&
bcx
,
location
);
let
fn_ty
=
FnType
::
of_instance
(
bcx
.ccx
,
&
drop_fn
);
let
(
drop_fn
,
need_extra
)
=
match
ty
.sty
{
ty
::
TyDynamic
(
..
)
=>
(
meth
::
DESTRUCTOR
.get_fn
(
&
bcx
,
lvalue
.llextra
),
false
),
_
=>
(
callee
::
get_fn
(
bcx
.ccx
,
drop_fn
),
lvalue
.has_extra
())
let
mut
args
:
&
[
_
]
=
&
[
lvalue
.llval
,
lvalue
.llextra
];
args
=
&
args
[
..
1
+
lvalue
.has_extra
()
as
usize
];
let
(
drop_fn
,
fn_ty
)
=
match
ty
.sty
{
ty
::
TyDynamic
(
..
)
=>
{
let
fn_ty
=
common
::
instance_ty
(
bcx
.ccx
.tcx
(),
&
drop_fn
);
let
sig
=
common
::
ty_fn_sig
(
bcx
.ccx
,
fn_ty
);
let
sig
=
bcx
.tcx
()
.erase_late_bound_regions_and_normalize
(
&
sig
);
let
fn_ty
=
FnType
::
new_vtable
(
bcx
.ccx
,
sig
,
&
[]);
args
=
&
args
[
..
1
];
(
meth
::
DESTRUCTOR
.get_fn
(
&
bcx
,
lvalue
.llextra
,
&
fn_ty
),
fn_ty
)
}
_
=>
{
(
callee
::
get_fn
(
bcx
.ccx
,
drop_fn
),
FnType
::
of_instance
(
bcx
.ccx
,
&
drop_fn
))
}
};
let
args
=
&
[
lvalue
.llval
,
lvalue
.llextra
][
..
1
+
need_extra
as
usize
];
do_call
(
self
,
bcx
,
fn_ty
,
drop_fn
,
args
,
Some
((
ReturnDest
::
Nothing
,
target
)),
unwind
);
...
...
@@ -561,15 +570,13 @@ fn trans_terminator(&mut self,
(
&
args
[
..
],
None
)
};
for
(
i
dx
,
arg
)
in
first_args
.iter
()
.enumerate
()
{
for
(
i
,
arg
)
in
first_args
.iter
()
.enumerate
()
{
let
mut
op
=
self
.trans_operand
(
&
bcx
,
arg
);
if
i
dx
==
0
{
if
i
==
0
{
if
let
Pair
(
_
,
meta
)
=
op
.val
{
if
let
Some
(
ty
::
InstanceDef
::
Virtual
(
_
,
idx
))
=
def
{
let
llmeth
=
meth
::
VirtualIndex
::
from_index
(
idx
)
.get_fn
(
&
bcx
,
meta
);
let
llty
=
fn_ty
.llvm_type
(
bcx
.ccx
)
.ptr_to
();
llfn
=
Some
(
bcx
.pointercast
(
llmeth
,
llty
));
llfn
=
Some
(
meth
::
VirtualIndex
::
from_index
(
idx
)
.get_fn
(
&
bcx
,
meta
,
&
fn_ty
));
}
}
}
...
...
@@ -582,7 +589,7 @@ fn trans_terminator(&mut self,
op
.val
=
Ref
(
tmp
.llval
,
tmp
.alignment
);
}
self
.trans_argument
(
&
bcx
,
op
,
&
mut
llargs
,
&
fn_ty
.args
[
i
dx
]);
self
.trans_argument
(
&
bcx
,
op
,
&
mut
llargs
,
&
fn_ty
.args
[
i
]);
}
if
let
Some
(
tup
)
=
untuple
{
self
.trans_arguments_untupled
(
&
bcx
,
tup
,
&
mut
llargs
,
...
...
src/librustc_trans/mir/constant.rs
浏览文件 @
b723af28
...
...
@@ -32,7 +32,7 @@
use
common
::{
C_null
,
C_struct
,
C_str_slice
,
C_undef
,
C_usize
,
C_vector
,
C_fat_ptr
};
use
common
::
const_to_opt_u128
;
use
consts
;
use
type_of
::
{
self
,
LayoutLlvmExt
}
;
use
type_of
::
LayoutLlvmExt
;
use
type_
::
Type
;
use
value
::
Value
;
...
...
@@ -145,7 +145,7 @@ pub fn to_operand(&self, ccx: &CrateContext<'a, 'tcx>) -> OperandRef<'tcx> {
let
val
=
if
llty
==
llvalty
&&
common
::
type_is_imm_pair
(
ccx
,
self
.ty
)
{
let
(
a
,
b
)
=
self
.get_pair
(
ccx
);
OperandValue
::
Pair
(
a
,
b
)
}
else
if
llty
==
llvalty
&&
c
ommon
::
type_is_immediate
(
ccx
,
self
.ty
)
{
}
else
if
llty
==
llvalty
&&
c
cx
.layout_of
(
self
.ty
)
.is_llvm_immediate
(
)
{
// If the types match, we can use the value directly.
OperandValue
::
Immediate
(
self
.llval
)
}
else
{
...
...
@@ -677,11 +677,12 @@ fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>,
}
C_fat_ptr
(
self
.ccx
,
base
,
info
)
}
mir
::
CastKind
::
Misc
if
common
::
type_is_immediate
(
self
.ccx
,
operand
.ty
)
=>
{
debug_assert!
(
common
::
type_is_immediate
(
self
.ccx
,
cast_ty
));
mir
::
CastKind
::
Misc
if
self
.ccx
.layout_of
(
operand
.ty
)
.is_llvm_immediate
()
=>
{
let
r_t_in
=
CastTy
::
from_ty
(
operand
.ty
)
.expect
(
"bad input type for cast"
);
let
r_t_out
=
CastTy
::
from_ty
(
cast_ty
)
.expect
(
"bad output type for cast"
);
let
ll_t_out
=
self
.ccx
.layout_of
(
cast_ty
)
.immediate_llvm_type
(
self
.ccx
);
let
cast_layout
=
self
.ccx
.layout_of
(
cast_ty
);
assert
!
(
cast_layout
.is_llvm_immediate
());
let
ll_t_out
=
cast_layout
.immediate_llvm_type
(
self
.ccx
);
let
llval
=
operand
.llval
;
let
signed
=
match
self
.ccx
.layout_of
(
operand
.ty
)
.abi
{
layout
::
Abi
::
Scalar
(
layout
::
Int
(
_
,
signed
))
=>
signed
,
...
...
@@ -728,8 +729,10 @@ fn const_rvalue(&self, rvalue: &mir::Rvalue<'tcx>,
if
common
::
type_is_fat_ptr
(
self
.ccx
,
operand
.ty
)
{
let
(
data_ptr
,
meta
)
=
operand
.get_fat_ptr
(
self
.ccx
);
if
common
::
type_is_fat_ptr
(
self
.ccx
,
cast_ty
)
{
let
llcast_ty
=
type_of
::
fat_ptr_base_ty
(
self
.ccx
,
cast_ty
);
let
data_cast
=
consts
::
ptrcast
(
data_ptr
,
llcast_ty
);
let
thin_ptr
=
self
.ccx
.layout_of
(
cast_ty
)
.field
(
self
.ccx
,
abi
::
FAT_PTR_ADDR
);
let
data_cast
=
consts
::
ptrcast
(
data_ptr
,
thin_ptr
.llvm_type
(
self
.ccx
));
C_fat_ptr
(
self
.ccx
,
data_cast
,
meta
)
}
else
{
// cast to thin-ptr
// Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
...
...
@@ -1091,7 +1094,7 @@ fn trans_const_adt<'a, 'tcx>(
mir
::
AggregateKind
::
Adt
(
_
,
index
,
_
,
_
)
=>
index
,
_
=>
0
,
};
match
*
l
.layout
{
match
l
.layout
{
layout
::
Layout
::
General
{
..
}
=>
{
let
discr
=
match
*
kind
{
mir
::
AggregateKind
::
Adt
(
adt_def
,
_
,
_
,
_
)
=>
{
...
...
@@ -1147,7 +1150,7 @@ fn trans_const_adt<'a, 'tcx>(
/// a two-element struct will locate it at offset 4, and accesses to it
/// will read the wrong memory.
fn
build_const_struct
<
'a
,
'tcx
>
(
ccx
:
&
CrateContext
<
'a
,
'tcx
>
,
layout
:
layout
::
Full
Layout
<
'tcx
>
,
layout
:
layout
::
Ty
Layout
<
'tcx
>
,
vals
:
&
[
Const
<
'tcx
>
],
discr
:
Option
<
Const
<
'tcx
>>
)
->
Const
<
'tcx
>
{
...
...
src/librustc_trans/mir/lvalue.rs
浏览文件 @
b723af28
...
...
@@ -10,7 +10,7 @@
use
llvm
::{
self
,
ValueRef
};
use
rustc
::
ty
::{
self
,
Ty
};
use
rustc
::
ty
::
layout
::{
self
,
Align
,
Full
Layout
,
LayoutOf
};
use
rustc
::
ty
::
layout
::{
self
,
Align
,
Ty
Layout
,
LayoutOf
};
use
rustc
::
mir
;
use
rustc
::
mir
::
tcx
::
LvalueTy
;
use
rustc_data_structures
::
indexed_vec
::
Idx
;
...
...
@@ -19,7 +19,7 @@
use
builder
::
Builder
;
use
common
::{
self
,
CrateContext
,
C_usize
,
C_u8
,
C_u32
,
C_uint
,
C_int
,
C_null
,
val_ty
};
use
consts
;
use
type_of
::
{
self
,
LayoutLlvmExt
}
;
use
type_of
::
LayoutLlvmExt
;
use
type_
::
Type
;
use
value
::
Value
;
use
glue
;
...
...
@@ -54,8 +54,8 @@ fn bitor(self, rhs: Self) -> Self {
}
}
impl
<
'a
>
From
<
Full
Layout
<
'a
>>
for
Alignment
{
fn
from
(
layout
:
Full
Layout
)
->
Self
{
impl
<
'a
>
From
<
Ty
Layout
<
'a
>>
for
Alignment
{
fn
from
(
layout
:
Ty
Layout
)
->
Self
{
if
let
layout
::
Abi
::
Aggregate
{
packed
:
true
,
align
,
..
}
=
layout
.abi
{
Alignment
::
Packed
(
align
)
}
else
{
...
...
@@ -86,7 +86,7 @@ pub struct LvalueRef<'tcx> {
pub
llextra
:
ValueRef
,
/// Monomorphized type of this lvalue, including variant information
pub
layout
:
Full
Layout
<
'tcx
>
,
pub
layout
:
Ty
Layout
<
'tcx
>
,
/// Whether this lvalue is known to be aligned according to its layout
pub
alignment
:
Alignment
,
...
...
@@ -94,7 +94,7 @@ pub struct LvalueRef<'tcx> {
impl
<
'a
,
'tcx
>
LvalueRef
<
'tcx
>
{
pub
fn
new_sized
(
llval
:
ValueRef
,
layout
:
Full
Layout
<
'tcx
>
,
layout
:
Ty
Layout
<
'tcx
>
,
alignment
:
Alignment
)
->
LvalueRef
<
'tcx
>
{
LvalueRef
{
...
...
@@ -105,7 +105,7 @@ pub fn new_sized(llval: ValueRef,
}
}
pub
fn
alloca
(
bcx
:
&
Builder
<
'a
,
'tcx
>
,
layout
:
Full
Layout
<
'tcx
>
,
name
:
&
str
)
pub
fn
alloca
(
bcx
:
&
Builder
<
'a
,
'tcx
>
,
layout
:
Ty
Layout
<
'tcx
>
,
name
:
&
str
)
->
LvalueRef
<
'tcx
>
{
debug!
(
"alloca({:?}: {:?})"
,
name
,
layout
);
let
tmp
=
bcx
.alloca
(
...
...
@@ -114,7 +114,7 @@ pub fn alloca(bcx: &Builder<'a, 'tcx>, layout: FullLayout<'tcx>, name: &str)
}
pub
fn
len
(
&
self
,
ccx
:
&
CrateContext
<
'a
,
'tcx
>
)
->
ValueRef
{
if
let
layout
::
FieldPlacement
::
Array
{
count
,
..
}
=
*
self
.layout.fields
{
if
let
layout
::
FieldPlacement
::
Array
{
count
,
..
}
=
self
.layout.fields
{
if
self
.layout
.is_unsized
()
{
assert
!
(
self
.has_extra
());
assert_eq!
(
count
,
0
);
...
...
@@ -163,7 +163,7 @@ pub fn load(&self, bcx: &Builder<'a, 'tcx>) -> OperandRef<'tcx> {
OperandValue
::
Pair
(
self
.project_field
(
bcx
,
0
)
.load
(
bcx
)
.pack_if_pair
(
bcx
)
.immediate
(),
self
.project_field
(
bcx
,
1
)
.load
(
bcx
)
.pack_if_pair
(
bcx
)
.immediate
())
}
else
if
common
::
type_is_immediate
(
bcx
.ccx
,
self
.layout.ty
)
{
}
else
if
self
.layout
.is_llvm_immediate
(
)
{
let
mut
const_llval
=
ptr
::
null_mut
();
unsafe
{
let
global
=
llvm
::
LLVMIsAGlobalVariable
(
self
.llval
);
...
...
@@ -202,28 +202,15 @@ pub fn project_field(self, bcx: &Builder<'a, 'tcx>, ix: usize) -> LvalueRef<'tcx
let
ccx
=
bcx
.ccx
;
let
field
=
self
.layout
.field
(
ccx
,
ix
);
let
offset
=
self
.layout.fields
.offset
(
ix
)
.bytes
();
let
alignment
=
self
.alignment
|
Alignment
::
from
(
self
.layout
);
// Unions and newtypes only use an offset of 0.
let
has_llvm_fields
=
match
*
self
.layout.fields
{
layout
::
FieldPlacement
::
Union
(
_
)
=>
false
,
layout
::
FieldPlacement
::
Array
{
..
}
=>
true
,
layout
::
FieldPlacement
::
Arbitrary
{
..
}
=>
{
match
self
.layout.abi
{
layout
::
Abi
::
Scalar
(
_
)
|
layout
::
Abi
::
Vector
{
..
}
=>
false
,
layout
::
Abi
::
Aggregate
{
..
}
=>
true
}
}
};
let
simple
=
||
{
LvalueRef
{
llval
:
if
has_llvm_fields
{
bcx
.struct_gep
(
self
.llval
,
self
.layout
.llvm_field_index
(
ix
))
}
else
{
assert_eq!
(
offset
,
0
);
// Unions and newtypes only use an offset of 0.
llval
:
if
offset
==
0
{
bcx
.pointercast
(
self
.llval
,
field
.llvm_type
(
ccx
)
.ptr_to
())
}
else
{
bcx
.struct_gep
(
self
.llval
,
self
.layout
.llvm_field_index
(
ix
))
},
llextra
:
if
ccx
.shared
()
.type_has_metadata
(
field
.ty
)
{
self
.llextra
...
...
@@ -309,7 +296,7 @@ pub fn project_field(self, bcx: &Builder<'a, 'tcx>, ix: usize) -> LvalueRef<'tcx
/// Obtain the actual discriminant of a value.
pub
fn
trans_get_discr
(
self
,
bcx
:
&
Builder
<
'a
,
'tcx
>
,
cast_to
:
Ty
<
'tcx
>
)
->
ValueRef
{
let
cast_to
=
bcx
.ccx
.layout_of
(
cast_to
)
.immediate_llvm_type
(
bcx
.ccx
);
match
*
self
.layout.layout
{
match
self
.layout.layout
{
layout
::
Layout
::
Univariant
{
..
}
|
layout
::
Layout
::
UntaggedUnion
{
..
}
=>
return
C_uint
(
cast_to
,
0
),
_
=>
{}
...
...
@@ -320,7 +307,7 @@ pub fn trans_get_discr(self, bcx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> Valu
layout
::
Abi
::
Scalar
(
discr
)
=>
discr
,
_
=>
bug!
(
"discriminant not scalar: {:#?}"
,
discr
.layout
)
};
let
(
min
,
max
)
=
match
*
self
.layout.layout
{
let
(
min
,
max
)
=
match
self
.layout.layout
{
layout
::
Layout
::
General
{
ref
discr_range
,
..
}
=>
(
discr_range
.start
,
discr_range
.end
),
_
=>
(
0
,
u64
::
max_value
()),
};
...
...
@@ -346,7 +333,7 @@ pub fn trans_get_discr(self, bcx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> Valu
bcx
.load
(
discr
.llval
,
discr
.alignment
.non_abi
())
}
};
match
*
self
.layout.layout
{
match
self
.layout.layout
{
layout
::
Layout
::
General
{
..
}
=>
{
let
signed
=
match
discr_scalar
{
layout
::
Int
(
_
,
signed
)
=>
signed
,
...
...
@@ -369,7 +356,7 @@ pub fn trans_set_discr(&self, bcx: &Builder<'a, 'tcx>, variant_index: usize) {
let
to
=
self
.layout.ty
.ty_adt_def
()
.unwrap
()
.discriminant_for_variant
(
bcx
.tcx
(),
variant_index
)
.to_u128_unchecked
()
as
u64
;
match
*
self
.layout.layout
{
match
self
.layout.layout
{
layout
::
Layout
::
General
{
..
}
=>
{
let
ptr
=
self
.project_field
(
bcx
,
0
);
bcx
.store
(
C_int
(
ptr
.layout
.llvm_type
(
bcx
.ccx
),
to
as
i64
),
...
...
@@ -419,17 +406,9 @@ pub fn project_downcast(&self, bcx: &Builder<'a, 'tcx>, variant_index: usize)
let
mut
downcast
=
*
self
;
downcast
.layout
=
self
.layout
.for_variant
(
variant_index
);
// If this is an enum, cast to the appropriate variant struct type.
match
*
self
.layout.layout
{
layout
::
Layout
::
NullablePointer
{
..
}
|
layout
::
Layout
::
General
{
..
}
=>
{
let
variant_ty
=
Type
::
struct_
(
bcx
.ccx
,
&
type_of
::
struct_llfields
(
bcx
.ccx
,
downcast
.layout
),
downcast
.layout
.is_packed
());
downcast
.llval
=
bcx
.pointercast
(
downcast
.llval
,
variant_ty
.ptr_to
());
}
_
=>
{}
}
// Cast to the appropriate variant struct type.
let
variant_ty
=
downcast
.layout
.llvm_type
(
bcx
.ccx
);
downcast
.llval
=
bcx
.pointercast
(
downcast
.llval
,
variant_ty
.ptr_to
());
downcast
}
...
...
src/librustc_trans/mir/mod.rs
浏览文件 @
b723af28
...
...
@@ -12,18 +12,17 @@
use
llvm
::{
self
,
ValueRef
,
BasicBlockRef
};
use
llvm
::
debuginfo
::
DIScope
;
use
rustc
::
ty
::{
self
,
TypeFoldable
};
use
rustc
::
ty
::
layout
::{
LayoutOf
,
Full
Layout
};
use
rustc
::
ty
::
layout
::{
LayoutOf
,
Ty
Layout
};
use
rustc
::
mir
::{
self
,
Mir
};
use
rustc
::
ty
::
subst
::
Substs
;
use
rustc
::
infer
::
TransNormalize
;
use
rustc
::
session
::
config
::
FullDebugInfo
;
use
base
;
use
builder
::
Builder
;
use
common
::{
self
,
CrateContext
,
Funclet
};
use
common
::{
CrateContext
,
Funclet
};
use
debuginfo
::{
self
,
declare_local
,
VariableAccess
,
VariableKind
,
FunctionDebugContext
};
use
monomorphize
::
Instance
;
use
abi
::{
ArgAttribute
,
FnType
};
use
type_of
::{
self
,
LayoutLlvmExt
};
use
syntax_pos
::{
DUMMY_SP
,
NO_EXPANSION
,
BytePos
,
Span
};
use
syntax
::
symbol
::
keywords
;
...
...
@@ -85,7 +84,7 @@ pub struct MirContext<'a, 'tcx:'a> {
/// directly using an `OperandRef`, which makes for tighter LLVM
/// IR. The conditions for using an `OperandRef` are as follows:
///
/// - the type of the local must be judged "immediate" by `
type_is
_immediate`
/// - the type of the local must be judged "immediate" by `
is_llvm
_immediate`
/// - the operand must never be referenced indirectly
/// - we should not take its address using the `&` operator
/// - nor should it appear in an lvalue path like `tmp.a`
...
...
@@ -177,7 +176,7 @@ enum LocalRef<'tcx> {
}
impl
<
'a
,
'tcx
>
LocalRef
<
'tcx
>
{
fn
new_operand
(
ccx
:
&
CrateContext
<
'a
,
'tcx
>
,
layout
:
Full
Layout
<
'tcx
>
)
->
LocalRef
<
'tcx
>
{
fn
new_operand
(
ccx
:
&
CrateContext
<
'a
,
'tcx
>
,
layout
:
Ty
Layout
<
'tcx
>
)
->
LocalRef
<
'tcx
>
{
if
layout
.is_zst
()
{
// Zero-size temporaries aren't always initialized, which
// doesn't matter because they don't contain data, but
...
...
@@ -448,32 +447,14 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
assert
!
(
!
a
.is_ignore
()
&&
a
.cast
.is_none
()
&&
a
.pad
.is_none
());
assert
!
(
!
b
.is_ignore
()
&&
b
.cast
.is_none
()
&&
b
.pad
.is_none
());
let
mut
a
=
llvm
::
get_param
(
bcx
.llfn
(),
llarg_idx
as
c_uint
);
let
a
=
llvm
::
get_param
(
bcx
.llfn
(),
llarg_idx
as
c_uint
);
bcx
.set_value_name
(
a
,
&
(
name
.clone
()
+
".0"
));
llarg_idx
+=
1
;
let
mut
b
=
llvm
::
get_param
(
bcx
.llfn
(),
llarg_idx
as
c_uint
);
let
b
=
llvm
::
get_param
(
bcx
.llfn
(),
llarg_idx
as
c_uint
);
bcx
.set_value_name
(
b
,
&
(
name
+
".1"
));
llarg_idx
+=
1
;
if
common
::
type_is_fat_ptr
(
bcx
.ccx
,
arg
.layout.ty
)
{
// FIXME(eddyb) As we can't perfectly represent the data and/or
// vtable pointer in a fat pointers in Rust's typesystem, and
// because we split fat pointers into two ArgType's, they're
// not the right type so we have to cast them for now.
let
pointee
=
match
arg
.layout.ty.sty
{
ty
::
TyRef
(
_
,
ty
::
TypeAndMut
{
ty
,
..
})
|
ty
::
TyRawPtr
(
ty
::
TypeAndMut
{
ty
,
..
})
=>
ty
,
ty
::
TyAdt
(
def
,
_
)
if
def
.is_box
()
=>
arg
.layout.ty
.boxed_ty
(),
_
=>
bug!
()
};
let
data_llty
=
bcx
.ccx
.layout_of
(
pointee
)
.llvm_type
(
bcx
.ccx
);
let
meta_llty
=
type_of
::
unsized_info_ty
(
bcx
.ccx
,
pointee
);
a
=
bcx
.pointercast
(
a
,
data_llty
.ptr_to
());
bcx
.set_value_name
(
a
,
&
(
name
.clone
()
+
".ptr"
));
b
=
bcx
.pointercast
(
b
,
meta_llty
);
bcx
.set_value_name
(
b
,
&
(
name
+
".meta"
));
}
return
LocalRef
::
Operand
(
Some
(
OperandRef
{
val
:
OperandValue
::
Pair
(
a
,
b
),
layout
:
arg
.layout
...
...
src/librustc_trans/mir/operand.rs
浏览文件 @
b723af28
...
...
@@ -10,7 +10,7 @@
use
llvm
::
ValueRef
;
use
rustc
::
ty
;
use
rustc
::
ty
::
layout
::{
LayoutOf
,
Full
Layout
};
use
rustc
::
ty
::
layout
::{
LayoutOf
,
Ty
Layout
};
use
rustc
::
mir
;
use
rustc_data_structures
::
indexed_vec
::
Idx
;
...
...
@@ -71,7 +71,7 @@ pub struct OperandRef<'tcx> {
pub
val
:
OperandValue
,
// The layout of value, based on its Rust type.
pub
layout
:
Full
Layout
<
'tcx
>
,
pub
layout
:
Ty
Layout
<
'tcx
>
,
}
impl
<
'tcx
>
fmt
::
Debug
for
OperandRef
<
'tcx
>
{
...
...
@@ -82,7 +82,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
impl
<
'a
,
'tcx
>
OperandRef
<
'tcx
>
{
pub
fn
new_zst
(
ccx
:
&
CrateContext
<
'a
,
'tcx
>
,
layout
:
Full
Layout
<
'tcx
>
)
->
OperandRef
<
'tcx
>
{
layout
:
Ty
Layout
<
'tcx
>
)
->
OperandRef
<
'tcx
>
{
assert
!
(
layout
.is_zst
());
let
llty
=
layout
.llvm_type
(
ccx
);
// FIXME(eddyb) ZSTs should always be immediate, not pairs.
...
...
src/librustc_trans/mir/rvalue.rs
浏览文件 @
b723af28
...
...
@@ -18,6 +18,7 @@
use
rustc_const_math
::
MAX_F32_PLUS_HALF_ULP
;
use
std
::{
u128
,
i128
};
use
abi
;
use
base
;
use
builder
::
Builder
;
use
callee
;
...
...
@@ -26,7 +27,7 @@
use
consts
;
use
monomorphize
;
use
type_
::
Type
;
use
type_of
::
{
self
,
LayoutLlvmExt
}
;
use
type_of
::
LayoutLlvmExt
;
use
value
::
Value
;
use
super
::{
MirContext
,
LocalRef
};
...
...
@@ -234,8 +235,8 @@ pub fn trans_rvalue_operand(&mut self,
// &'a fmt::Debug+Send => &'a fmt::Debug,
// So we need to pointercast the base to ensure
// the types match up.
let
llcast_ty
=
type_of
::
fat_ptr_base_ty
(
bcx
.ccx
,
cast
.ty
);
let
lldata
=
bcx
.pointercast
(
lldata
,
llcast_ty
);
let
thin_ptr
=
cast
.field
(
bcx
.ccx
,
abi
::
FAT_PTR_ADDR
);
let
lldata
=
bcx
.pointercast
(
lldata
,
thin_ptr
.llvm_type
(
bcx
.ccx
)
);
OperandValue
::
Pair
(
lldata
,
llextra
)
}
OperandValue
::
Immediate
(
lldata
)
=>
{
...
...
@@ -253,8 +254,9 @@ pub fn trans_rvalue_operand(&mut self,
mir
::
CastKind
::
Misc
if
common
::
type_is_fat_ptr
(
bcx
.ccx
,
operand
.layout.ty
)
=>
{
if
let
OperandValue
::
Pair
(
data_ptr
,
meta
)
=
operand
.val
{
if
common
::
type_is_fat_ptr
(
bcx
.ccx
,
cast
.ty
)
{
let
llcast_ty
=
type_of
::
fat_ptr_base_ty
(
bcx
.ccx
,
cast
.ty
);
let
data_cast
=
bcx
.pointercast
(
data_ptr
,
llcast_ty
);
let
thin_ptr
=
cast
.field
(
bcx
.ccx
,
abi
::
FAT_PTR_ADDR
);
let
data_cast
=
bcx
.pointercast
(
data_ptr
,
thin_ptr
.llvm_type
(
bcx
.ccx
));
OperandValue
::
Pair
(
data_cast
,
meta
)
}
else
{
// cast to thin-ptr
// Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
...
...
@@ -268,7 +270,7 @@ pub fn trans_rvalue_operand(&mut self,
}
}
mir
::
CastKind
::
Misc
=>
{
debug_assert!
(
common
::
type_is_immediate
(
bcx
.ccx
,
cast
.ty
));
assert
!
(
cast
.is_llvm_immediate
(
));
let
r_t_in
=
CastTy
::
from_ty
(
operand
.layout.ty
)
.expect
(
"bad input type for cast"
);
let
r_t_out
=
CastTy
::
from_ty
(
cast
.ty
)
.expect
(
"bad output type for cast"
);
...
...
@@ -276,7 +278,7 @@ pub fn trans_rvalue_operand(&mut self,
let
ll_t_out
=
cast
.immediate_llvm_type
(
bcx
.ccx
);
let
llval
=
operand
.immediate
();
if
let
Layout
::
General
{
ref
discr_range
,
..
}
=
*
operand
.layout.layout
{
if
let
Layout
::
General
{
ref
discr_range
,
..
}
=
operand
.layout.layout
{
if
discr_range
.end
>
discr_range
.start
{
// We want `table[e as usize]` to not
// have bound checks, and this is the most
...
...
src/librustc_trans/type_.rs
浏览文件 @
b723af28
...
...
@@ -207,10 +207,6 @@ pub fn vector(ty: &Type, len: u64) -> Type {
ty!
(
llvm
::
LLVMVectorType
(
ty
.to_ref
(),
len
as
c_uint
))
}
pub
fn
vtable_ptr
(
ccx
:
&
CrateContext
)
->
Type
{
Type
::
func
(
&
[
Type
::
i8p
(
ccx
)],
&
Type
::
void
(
ccx
))
.ptr_to
()
.ptr_to
()
}
pub
fn
kind
(
&
self
)
->
TypeKind
{
unsafe
{
llvm
::
LLVMRustGetTypeKind
(
self
.to_ref
())
...
...
src/librustc_trans/type_of.rs
浏览文件 @
b723af28
...
...
@@ -11,131 +11,68 @@
use
abi
::
FnType
;
use
common
::
*
;
use
rustc
::
ty
::{
self
,
Ty
,
TypeFoldable
};
use
rustc
::
ty
::
layout
::{
self
,
HasDataLayout
,
Align
,
LayoutOf
,
Size
,
Full
Layout
};
use
rustc
::
ty
::
layout
::{
self
,
HasDataLayout
,
Align
,
LayoutOf
,
Size
,
Ty
Layout
};
use
trans_item
::
DefPathBasedNames
;
use
type_
::
Type
;
use
s
yntax
::
ast
;
use
s
td
::
fmt
::
Write
;
pub
fn
fat_ptr_base_ty
<
'a
,
'tcx
>
(
ccx
:
&
CrateContext
<
'a
,
'tcx
>
,
ty
:
Ty
<
'tcx
>
)
->
Type
{
match
ty
.sty
{
ty
::
TyRef
(
_
,
ty
::
TypeAndMut
{
ty
:
t
,
..
})
|
ty
::
TyRawPtr
(
ty
::
TypeAndMut
{
ty
:
t
,
..
})
if
ccx
.shared
()
.type_has_metadata
(
t
)
=>
{
ccx
.layout_of
(
t
)
.llvm_type
(
ccx
)
.ptr_to
()
}
ty
::
TyAdt
(
def
,
_
)
if
def
.is_box
()
=>
{
ccx
.layout_of
(
ty
.boxed_ty
())
.llvm_type
(
ccx
)
.ptr_to
()
}
_
=>
bug!
(
"expected fat ptr ty but got {:?}"
,
ty
)
}
}
pub
fn
unsized_info_ty
<
'a
,
'tcx
>
(
ccx
:
&
CrateContext
<
'a
,
'tcx
>
,
ty
:
Ty
<
'tcx
>
)
->
Type
{
let
unsized_part
=
ccx
.tcx
()
.struct_tail
(
ty
);
match
unsized_part
.sty
{
ty
::
TyStr
|
ty
::
TyArray
(
..
)
|
ty
::
TySlice
(
_
)
=>
{
Type
::
uint_from_ty
(
ccx
,
ast
::
UintTy
::
Us
)
}
ty
::
TyDynamic
(
..
)
=>
Type
::
vtable_ptr
(
ccx
),
_
=>
bug!
(
"Unexpected tail in unsized_info_ty: {:?} for ty={:?}"
,
unsized_part
,
ty
)
}
}
fn
uncached_llvm_type
<
'a
,
'tcx
>
(
cx
:
&
CrateContext
<
'a
,
'tcx
>
,
ty
:
Ty
<
'tcx
>
,
defer
:
&
mut
Option
<
(
Type
,
FullLayout
<
'tcx
>
)
>
)
fn
uncached_llvm_type
<
'a
,
'tcx
>
(
ccx
:
&
CrateContext
<
'a
,
'tcx
>
,
layout
:
TyLayout
<
'tcx
>
,
defer
:
&
mut
Option
<
(
Type
,
TyLayout
<
'tcx
>
)
>
)
->
Type
{
let
ptr_ty
=
|
ty
:
Ty
<
'tcx
>
|
{
if
cx
.shared
()
.type_has_metadata
(
ty
)
{
if
let
ty
::
TyStr
=
ty
.sty
{
// This means we get a nicer name in the output (str is always
// unsized).
cx
.str_slice_type
()
}
else
{
let
ptr_ty
=
cx
.layout_of
(
ty
)
.llvm_type
(
cx
)
.ptr_to
();
let
info_ty
=
unsized_info_ty
(
cx
,
ty
);
Type
::
struct_
(
cx
,
&
[
Type
::
array
(
&
Type
::
i8
(
cx
),
0
),
ptr_ty
,
Type
::
array
(
&
Type
::
i8
(
cx
),
0
),
info_ty
,
Type
::
array
(
&
Type
::
i8
(
cx
),
0
)
],
false
)
}
}
else
{
cx
.layout_of
(
ty
)
.llvm_type
(
cx
)
.ptr_to
()
}
};
match
ty
.sty
{
ty
::
TyRef
(
_
,
ty
::
TypeAndMut
{
ty
,
..
})
|
ty
::
TyRawPtr
(
ty
::
TypeAndMut
{
ty
,
..
})
=>
{
return
ptr_ty
(
ty
);
match
layout
.abi
{
layout
::
Abi
::
Scalar
(
_
)
=>
bug!
(
"handled elsewhere"
),
layout
::
Abi
::
Vector
{
..
}
=>
{
return
Type
::
vector
(
&
layout
.field
(
ccx
,
0
)
.llvm_type
(
ccx
),
layout
.fields
.count
()
as
u64
);
}
ty
::
TyAdt
(
def
,
_
)
if
def
.is_box
()
=>
{
return
ptr_ty
(
ty
.boxed_ty
());
}
ty
::
TyFnPtr
(
sig
)
=>
{
let
sig
=
cx
.tcx
()
.erase_late_bound_regions_and_normalize
(
&
sig
);
return
FnType
::
new
(
cx
,
sig
,
&
[])
.llvm_type
(
cx
)
.ptr_to
();
}
_
=>
{}
layout
::
Abi
::
Aggregate
{
..
}
=>
{}
}
let
layout
=
cx
.layout_of
(
ty
);
if
let
layout
::
Abi
::
Scalar
(
value
)
=
layout
.abi
{
let
llty
=
match
value
{
layout
::
Int
(
layout
::
I1
,
_
)
=>
Type
::
i8
(
cx
),
layout
::
Int
(
i
,
_
)
=>
Type
::
from_integer
(
cx
,
i
),
layout
::
F32
=>
Type
::
f32
(
cx
),
layout
::
F64
=>
Type
::
f64
(
cx
),
layout
::
Pointer
=>
{
cx
.layout_of
(
layout
::
Pointer
.to_ty
(
cx
.tcx
()))
.llvm_type
(
cx
)
}
};
return
llty
;
}
if
let
layout
::
Abi
::
Vector
{
..
}
=
layout
.abi
{
return
Type
::
vector
(
&
layout
.field
(
cx
,
0
)
.llvm_type
(
cx
),
layout
.fields
.count
()
as
u64
);
}
let
name
=
match
ty
.sty
{
ty
::
TyClosure
(
..
)
|
ty
::
TyGenerator
(
..
)
|
ty
::
TyAdt
(
..
)
=>
{
let
name
=
match
layout
.ty.sty
{
ty
::
TyClosure
(
..
)
|
ty
::
TyGenerator
(
..
)
|
ty
::
TyAdt
(
..
)
|
ty
::
TyDynamic
(
..
)
|
ty
::
TyForeign
(
..
)
|
ty
::
TyStr
=>
{
let
mut
name
=
String
::
with_capacity
(
32
);
let
printer
=
DefPathBasedNames
::
new
(
cx
.tcx
(),
true
,
true
);
printer
.push_type_name
(
ty
,
&
mut
name
);
let
printer
=
DefPathBasedNames
::
new
(
ccx
.tcx
(),
true
,
true
);
printer
.push_type_name
(
layout
.ty
,
&
mut
name
);
if
let
(
&
ty
::
TyAdt
(
def
,
_
),
Some
(
v
))
=
(
&
layout
.ty.sty
,
layout
.variant_index
)
{
write!
(
&
mut
name
,
"::{}"
,
def
.variants
[
v
]
.name
)
.unwrap
();
}
Some
(
name
)
}
_
=>
None
};
match
*
layout
.fields
{
match
layout
.fields
{
layout
::
FieldPlacement
::
Union
(
_
)
=>
{
let
size
=
layout
.size
(
cx
)
.bytes
();
let
fill
=
Type
::
array
(
&
Type
::
i8
(
cx
),
size
);
let
size
=
layout
.size
(
c
c
x
)
.bytes
();
let
fill
=
Type
::
array
(
&
Type
::
i8
(
c
c
x
),
size
);
match
name
{
None
=>
{
Type
::
struct_
(
cx
,
&
[
fill
],
layout
.is_packed
())
Type
::
struct_
(
c
c
x
,
&
[
fill
],
layout
.is_packed
())
}
Some
(
ref
name
)
=>
{
let
mut
llty
=
Type
::
named_struct
(
cx
,
name
);
let
mut
llty
=
Type
::
named_struct
(
c
c
x
,
name
);
llty
.set_struct_body
(
&
[
fill
],
layout
.is_packed
());
llty
}
}
}
layout
::
FieldPlacement
::
Array
{
count
,
..
}
=>
{
Type
::
array
(
&
layout
.field
(
c
x
,
0
)
.llvm_type
(
cx
),
count
)
Type
::
array
(
&
layout
.field
(
c
cx
,
0
)
.llvm_type
(
c
cx
),
count
)
}
layout
::
FieldPlacement
::
Arbitrary
{
..
}
=>
{
match
name
{
None
=>
{
Type
::
struct_
(
c
x
,
&
struct_llfields
(
cx
,
layout
),
layout
.is_packed
())
Type
::
struct_
(
c
cx
,
&
struct_llfields
(
c
cx
,
layout
),
layout
.is_packed
())
}
Some
(
ref
name
)
=>
{
let
llty
=
Type
::
named_struct
(
cx
,
name
);
let
llty
=
Type
::
named_struct
(
c
c
x
,
name
);
*
defer
=
Some
((
llty
,
layout
));
llty
}
...
...
@@ -144,37 +81,37 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
}
}
pub
fn
struct_llfields
<
'a
,
'tcx
>
(
cx
:
&
CrateContext
<
'a
,
'tcx
>
,
layout
:
Full
Layout
<
'tcx
>
)
->
Vec
<
Type
>
{
fn
struct_llfields
<
'a
,
'tcx
>
(
c
cx
:
&
CrateContext
<
'a
,
'tcx
>
,
layout
:
Ty
Layout
<
'tcx
>
)
->
Vec
<
Type
>
{
debug!
(
"struct_llfields: {:#?}"
,
layout
);
let
align
=
layout
.align
(
cx
);
let
size
=
layout
.size
(
cx
);
let
align
=
layout
.align
(
c
c
x
);
let
size
=
layout
.size
(
c
c
x
);
let
field_count
=
layout
.fields
.count
();
let
mut
offset
=
Size
::
from_bytes
(
0
);
let
mut
result
:
Vec
<
Type
>
=
Vec
::
with_capacity
(
1
+
field_count
*
2
);
for
i
in
layout
.fields
.index_by_increasing_offset
()
{
let
field
=
layout
.field
(
cx
,
i
);
let
field
=
layout
.field
(
c
c
x
,
i
);
let
target_offset
=
layout
.fields
.offset
(
i
as
usize
);
debug!
(
"struct_llfields: {}: {:?} offset: {:?} target_offset: {:?}"
,
i
,
field
,
offset
,
target_offset
);
assert
!
(
target_offset
>=
offset
);
let
padding
=
target_offset
-
offset
;
result
.push
(
Type
::
array
(
&
Type
::
i8
(
cx
),
padding
.bytes
()));
result
.push
(
Type
::
array
(
&
Type
::
i8
(
c
c
x
),
padding
.bytes
()));
debug!
(
" padding before: {:?}"
,
padding
);
result
.push
(
field
.llvm_type
(
cx
));
result
.push
(
field
.llvm_type
(
c
c
x
));
if
layout
.is_packed
()
{
assert_eq!
(
padding
.bytes
(),
0
);
}
else
{
let
field_align
=
field
.align
(
cx
);
let
field_align
=
field
.align
(
c
c
x
);
assert
!
(
field_align
.abi
()
<=
align
.abi
(),
"non-packed type has field with larger align ({}): {:#?}"
,
field_align
.abi
(),
layout
);
}
offset
=
target_offset
+
field
.size
(
cx
);
offset
=
target_offset
+
field
.size
(
c
c
x
);
}
if
!
layout
.is_unsized
()
&&
field_count
>
0
{
if
offset
>
size
{
...
...
@@ -184,7 +121,7 @@ pub fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
let
padding
=
size
-
offset
;
debug!
(
"struct_llfields: pad_bytes: {:?} offset: {:?} stride: {:?}"
,
padding
,
offset
,
size
);
result
.push
(
Type
::
array
(
&
Type
::
i8
(
cx
),
padding
.bytes
()));
result
.push
(
Type
::
array
(
&
Type
::
i8
(
c
c
x
),
padding
.bytes
()));
assert
!
(
result
.len
()
==
1
+
field_count
*
2
);
}
else
{
debug!
(
"struct_llfields: offset: {:?} stride: {:?}"
,
...
...
@@ -210,13 +147,22 @@ pub fn size_and_align_of(&self, ty: Ty<'tcx>) -> (Size, Align) {
}
pub
trait
LayoutLlvmExt
<
'tcx
>
{
fn
is_llvm_immediate
(
&
self
)
->
bool
;
fn
llvm_type
<
'a
>
(
&
self
,
ccx
:
&
CrateContext
<
'a
,
'tcx
>
)
->
Type
;
fn
immediate_llvm_type
<
'a
>
(
&
self
,
ccx
:
&
CrateContext
<
'a
,
'tcx
>
)
->
Type
;
fn
over_align
(
&
self
,
ccx
:
&
CrateContext
)
->
Option
<
Align
>
;
fn
llvm_field_index
(
&
self
,
index
:
usize
)
->
u64
;
}
impl
<
'tcx
>
LayoutLlvmExt
<
'tcx
>
for
FullLayout
<
'tcx
>
{
impl
<
'tcx
>
LayoutLlvmExt
<
'tcx
>
for
TyLayout
<
'tcx
>
{
fn
is_llvm_immediate
(
&
self
)
->
bool
{
match
self
.abi
{
layout
::
Abi
::
Scalar
(
_
)
|
layout
::
Abi
::
Vector
{
..
}
=>
true
,
layout
::
Abi
::
Aggregate
{
..
}
=>
self
.is_zst
()
}
}
/// Get the LLVM type corresponding to a Rust type, i.e. `rustc::ty::Ty`.
/// The pointee type of the pointer in `LvalueRef` is always this type.
/// For sized types, it is also the right LLVM type for an `alloca`
...
...
@@ -229,8 +175,42 @@ impl<'tcx> LayoutLlvmExt<'tcx> for FullLayout<'tcx> {
/// of that field's type - this is useful for taking the address of
/// that field and ensuring the struct has the right alignment.
fn
llvm_type
<
'a
>
(
&
self
,
ccx
:
&
CrateContext
<
'a
,
'tcx
>
)
->
Type
{
if
let
layout
::
Abi
::
Scalar
(
value
)
=
self
.abi
{
// Use a different cache for scalars because pointers to DSTs
// can be either fat or thin (data pointers of fat pointers).
if
let
Some
(
&
llty
)
=
ccx
.scalar_lltypes
()
.borrow
()
.get
(
&
self
.ty
)
{
return
llty
;
}
let
llty
=
match
value
{
layout
::
Int
(
layout
::
I1
,
_
)
=>
Type
::
i8
(
ccx
),
layout
::
Int
(
i
,
_
)
=>
Type
::
from_integer
(
ccx
,
i
),
layout
::
F32
=>
Type
::
f32
(
ccx
),
layout
::
F64
=>
Type
::
f64
(
ccx
),
layout
::
Pointer
=>
{
let
pointee
=
match
self
.ty.sty
{
ty
::
TyRef
(
_
,
ty
::
TypeAndMut
{
ty
,
..
})
|
ty
::
TyRawPtr
(
ty
::
TypeAndMut
{
ty
,
..
})
=>
{
ccx
.layout_of
(
ty
)
.llvm_type
(
ccx
)
}
ty
::
TyAdt
(
def
,
_
)
if
def
.is_box
()
=>
{
ccx
.layout_of
(
self
.ty
.boxed_ty
())
.llvm_type
(
ccx
)
}
ty
::
TyFnPtr
(
sig
)
=>
{
let
sig
=
ccx
.tcx
()
.erase_late_bound_regions_and_normalize
(
&
sig
);
FnType
::
new
(
ccx
,
sig
,
&
[])
.llvm_type
(
ccx
)
}
_
=>
Type
::
i8
(
ccx
)
};
pointee
.ptr_to
()
}
};
ccx
.scalar_lltypes
()
.borrow_mut
()
.insert
(
self
.ty
,
llty
);
return
llty
;
}
// Check the cache.
if
let
Some
(
&
llty
)
=
ccx
.lltypes
()
.borrow
()
.get
(
&
self
.ty
)
{
if
let
Some
(
&
llty
)
=
ccx
.lltypes
()
.borrow
()
.get
(
&
(
self
.ty
,
self
.variant_index
)
)
{
return
llty
;
}
...
...
@@ -244,13 +224,17 @@ fn llvm_type<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> Type {
let
mut
defer
=
None
;
let
llty
=
if
self
.ty
!=
normal_ty
{
ccx
.layout_of
(
normal_ty
)
.llvm_type
(
ccx
)
let
mut
layout
=
ccx
.layout_of
(
normal_ty
);
if
let
Some
(
v
)
=
self
.variant_index
{
layout
=
layout
.for_variant
(
v
);
}
layout
.llvm_type
(
ccx
)
}
else
{
uncached_llvm_type
(
ccx
,
self
.ty
,
&
mut
defer
)
uncached_llvm_type
(
ccx
,
*
self
,
&
mut
defer
)
};
debug!
(
"--> mapped {:#?} to llty={:?}"
,
self
,
llty
);
ccx
.lltypes
()
.borrow_mut
()
.insert
(
self
.ty
,
llty
);
ccx
.lltypes
()
.borrow_mut
()
.insert
(
(
self
.ty
,
self
.variant_index
)
,
llty
);
if
let
Some
((
mut
llty
,
layout
))
=
defer
{
llty
.set_struct_body
(
&
struct_llfields
(
ccx
,
layout
),
layout
.is_packed
())
...
...
@@ -279,11 +263,11 @@ fn over_align(&self, ccx: &CrateContext) -> Option<Align> {
fn
llvm_field_index
(
&
self
,
index
:
usize
)
->
u64
{
if
let
layout
::
Abi
::
Scalar
(
_
)
=
self
.abi
{
bug!
(
"
Full
Layout::llvm_field_index({:?}): not applicable"
,
self
);
bug!
(
"
Ty
Layout::llvm_field_index({:?}): not applicable"
,
self
);
}
match
*
self
.fields
{
match
self
.fields
{
layout
::
FieldPlacement
::
Union
(
_
)
=>
{
bug!
(
"
Full
Layout::llvm_field_index({:?}): not applicable"
,
self
)
bug!
(
"
Ty
Layout::llvm_field_index({:?}): not applicable"
,
self
)
}
layout
::
FieldPlacement
::
Array
{
..
}
=>
{
...
...
src/test/codegen/adjustments.rs
浏览文件 @
b723af28
...
...
@@ -24,10 +24,9 @@ pub fn helper(_: usize) {
pub
fn
no_op_slice_adjustment
(
x
:
&
[
u8
])
->
&
[
u8
]
{
// We used to generate an extra alloca and memcpy for the block's trailing expression value, so
// check that we copy directly to the return value slot
// CHECK: %x.ptr = bitcast i8* %0 to [0 x i8]*
// CHECK: %1 = insertvalue { [0 x i8], [0 x i8]*, [0 x i8], [[USIZE]], [0 x i8] } undef, [0 x i8]* %x.ptr, 1
// CHECK: %2 = insertvalue { [0 x i8], [0 x i8]*, [0 x i8], [[USIZE]], [0 x i8] } %1, [[USIZE]] %x.meta, 3
// CHECK: ret { [0 x i8], [0 x i8]*, [0 x i8], [[USIZE]], [0 x i8] } %2
// CHECK: %0 = insertvalue { [0 x i8], [0 x i8]*, [0 x i8], [[USIZE]], [0 x i8] } undef, [0 x i8]* %x.0, 1
// CHECK: %1 = insertvalue { [0 x i8], [0 x i8]*, [0 x i8], [[USIZE]], [0 x i8] } %0, [[USIZE]] %x.1, 3
// CHECK: ret { [0 x i8], [0 x i8]*, [0 x i8], [[USIZE]], [0 x i8] } %1
{
x
}
}
...
...
src/test/codegen/function-arguments.rs
浏览文件 @
b723af28
...
...
@@ -97,43 +97,43 @@ pub fn struct_return() -> S {
pub
fn
helper
(
_
:
usize
)
{
}
// CHECK: @slice(
i8* noalias nonnull readonly %arg0.ptr, [[USIZE]] %arg0.meta
)
// CHECK: @slice(
[0 x i8]* noalias nonnull readonly %arg0.0, [[USIZE]] %arg0.1
)
// FIXME #25759 This should also have `nocapture`
#[no_mangle]
pub
fn
slice
(
_
:
&
[
u8
])
{
}
// CHECK: @mutable_slice(
i8* nonnull %arg0.ptr, [[USIZE]] %arg0.meta
)
// CHECK: @mutable_slice(
[0 x i8]* nonnull %arg0.0, [[USIZE]] %arg0.1
)
// FIXME #25759 This should also have `nocapture`
// ... there's this LLVM bug that forces us to not use noalias, see #29485
#[no_mangle]
pub
fn
mutable_slice
(
_
:
&
mut
[
u8
])
{
}
// CHECK: @unsafe_slice(
%UnsafeInner* nonnull %arg0.ptr, [[USIZE]] %arg0.meta
)
// CHECK: @unsafe_slice(
[0 x %UnsafeInner]* nonnull %arg0.0, [[USIZE]] %arg0.1
)
// unsafe interior means this isn't actually readonly and there may be aliases ...
#[no_mangle]
pub
fn
unsafe_slice
(
_
:
&
[
UnsafeInner
])
{
}
// CHECK: @str(
i8* noalias nonnull readonly %arg0.ptr, [[USIZE]] %arg0.meta
)
// CHECK: @str(
[0 x i8]* noalias nonnull readonly %arg0.0, [[USIZE]] %arg0.1
)
// FIXME #25759 This should also have `nocapture`
#[no_mangle]
pub
fn
str
(
_
:
&
[
u8
])
{
}
// CHECK: @trait_borrow(
{}* nonnull, {}* noalias nonnull readonly
)
// CHECK: @trait_borrow(
%"core::ops::drop::Drop"* nonnull %arg0.0, {}* noalias nonnull readonly %arg0.1
)
// FIXME #25759 This should also have `nocapture`
#[no_mangle]
pub
fn
trait_borrow
(
_
:
&
Drop
)
{
}
// CHECK: @trait_box(
{}
* noalias nonnull, {}* noalias nonnull readonly)
// CHECK: @trait_box(
%"core::ops::drop::Drop"
* noalias nonnull, {}* noalias nonnull readonly)
#[no_mangle]
pub
fn
trait_box
(
_
:
Box
<
Drop
>
)
{
}
// CHECK: { [0 x i8], [0 x i16]*, [0 x i8], [[USIZE]], [0 x i8] } @return_slice(
i16* noalias nonnull readonly %x.ptr, [[USIZE]] %x.meta
)
// CHECK: { [0 x i8], [0 x i16]*, [0 x i8], [[USIZE]], [0 x i8] } @return_slice(
[0 x i16]* noalias nonnull readonly %x.0, [[USIZE]] %x.1
)
#[no_mangle]
pub
fn
return_slice
(
x
:
&
[
u16
])
->
&
[
u16
]
{
x
...
...
src/test/codegen/refs.rs
浏览文件 @
b723af28
...
...
@@ -24,10 +24,10 @@ pub fn helper(_: usize) {
pub
fn
ref_dst
(
s
:
&
[
u8
])
{
// We used to generate an extra alloca and memcpy to ref the dst, so check that we copy
// directly to the alloca for "x"
// CHECK: [[X0:%[0-9]+]] =
getelementptr {{.*}} { [0 x i8], [0 x i8]*, [0 x i8], [[USIZE]], [0 x i8] }* %x, i32 0, i32 1
// CHECK: store [0 x i8]* %s.
ptr
, [0 x i8]** [[X0]]
// CHECK: [[X0:%[0-9]+]] =
bitcast { [0 x i8], [0 x i8]*, [0 x i8], [[USIZE]], [0 x i8] }* %x to [0 x i8]**
// CHECK: store [0 x i8]* %s.
0
, [0 x i8]** [[X0]]
// CHECK: [[X1:%[0-9]+]] = getelementptr {{.*}} { [0 x i8], [0 x i8]*, [0 x i8], [[USIZE]], [0 x i8] }* %x, i32 0, i32 3
// CHECK: store [[USIZE]] %s.
meta
, [[USIZE]]* [[X1]]
// CHECK: store [[USIZE]] %s.
1
, [[USIZE]]* [[X1]]
let
x
=
&*
s
;
&
x
;
// keep variable in an alloca
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录