Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
15d1c4d2
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,发现更多精彩内容 >>
提交
15d1c4d2
编写于
2月 04, 2018
作者:
C
Cameron Hart
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Implementation of `#[repr(packed(n))]` RFC 1399.
上级
ca26ef32
变更
26
隐藏空白更改
内联
并排
Showing
26 changed file
with
844 addition
and
162 deletion
+844
-162
src/doc/unstable-book/src/language-features/repr-packed.md
src/doc/unstable-book/src/language-features/repr-packed.md
+8
-0
src/librustc/session/code_stats.rs
src/librustc/session/code_stats.rs
+21
-16
src/librustc/ty/layout.rs
src/librustc/ty/layout.rs
+52
-26
src/librustc/ty/mod.rs
src/librustc/ty/mod.rs
+22
-8
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/mod.rs
+13
-2
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/diagnostics.rs
+3
-2
src/libsyntax/attr.rs
src/libsyntax/attr.rs
+30
-16
src/libsyntax/feature_gate.rs
src/libsyntax/feature_gate.rs
+15
-4
src/libsyntax_ext/deriving/generic/mod.rs
src/libsyntax_ext/deriving/generic/mod.rs
+7
-3
src/test/codegen/packed.rs
src/test/codegen/packed.rs
+71
-13
src/test/compile-fail/conflicting-repr-hints.rs
src/test/compile-fail/conflicting-repr-hints.rs
+11
-0
src/test/run-pass/align-struct.rs
src/test/run-pass/align-struct.rs
+22
-0
src/test/run-pass/auxiliary/packed.rs
src/test/run-pass/auxiliary/packed.rs
+17
-1
src/test/run-pass/issue-48159.rs
src/test/run-pass/issue-48159.rs
+37
-0
src/test/run-pass/packed-struct-borrow-element.rs
src/test/run-pass/packed-struct-borrow-element.rs
+23
-2
src/test/run-pass/packed-struct-generic-size.rs
src/test/run-pass/packed-struct-generic-size.rs
+30
-3
src/test/run-pass/packed-struct-match.rs
src/test/run-pass/packed-struct-match.rs
+33
-4
src/test/run-pass/packed-struct-size-xc.rs
src/test/run-pass/packed-struct-size-xc.rs
+10
-1
src/test/run-pass/packed-struct-size.rs
src/test/run-pass/packed-struct-size.rs
+112
-14
src/test/run-pass/packed-struct-vec.rs
src/test/run-pass/packed-struct-vec.rs
+89
-10
src/test/run-pass/packed-tuple-struct-size.rs
src/test/run-pass/packed-tuple-struct-size.rs
+54
-14
src/test/run-pass/union/union-packed.rs
src/test/run-pass/union/union-packed.rs
+93
-19
src/test/ui/feature-gate-repr_packed.rs
src/test/ui/feature-gate-repr_packed.rs
+14
-0
src/test/ui/feature-gate-repr_packed.stderr
src/test/ui/feature-gate-repr_packed.stderr
+11
-0
src/test/ui/print_type_sizes/packed.rs
src/test/ui/print_type_sizes/packed.rs
+29
-3
src/test/ui/print_type_sizes/packed.stdout
src/test/ui/print_type_sizes/packed.stdout
+17
-1
未找到文件。
src/doc/unstable-book/src/language-features/repr-packed.md
0 → 100644
浏览文件 @
15d1c4d2
# `repr_packed`
The tracking issue for this feature is [#33158]
[
#33158
]:
https://github.com/rust-lang/rust/issues/33158
------------------------
src/librustc/session/code_stats.rs
浏览文件 @
15d1c4d2
...
...
@@ -62,6 +62,7 @@ pub struct TypeSizeInfo {
pub
type_description
:
String
,
pub
align
:
u64
,
pub
overall_size
:
u64
,
pub
packed
:
bool
,
pub
opt_discr_size
:
Option
<
u64
>
,
pub
variants
:
Vec
<
VariantInfo
>
,
}
...
...
@@ -79,6 +80,7 @@ pub fn record_type_size<S: ToString>(&mut self,
type_desc
:
S
,
align
:
Align
,
overall_size
:
Size
,
packed
:
bool
,
opt_discr_size
:
Option
<
Size
>
,
variants
:
Vec
<
VariantInfo
>
)
{
let
info
=
TypeSizeInfo
{
...
...
@@ -86,6 +88,7 @@ pub fn record_type_size<S: ToString>(&mut self,
type_description
:
type_desc
.to_string
(),
align
:
align
.abi
(),
overall_size
:
overall_size
.bytes
(),
packed
:
packed
,
opt_discr_size
:
opt_discr_size
.map
(|
s
|
s
.bytes
()),
variants
,
};
...
...
@@ -153,24 +156,26 @@ pub fn print_type_sizes(&self) {
for
field
in
fields
.iter
()
{
let
FieldInfo
{
ref
name
,
offset
,
size
,
align
}
=
*
field
;
// Include field alignment in output only if it caused padding injection
if
min_offset
!=
offset
{
if
offset
>
min_offset
{
let
pad
=
offset
-
min_offset
;
println!
(
"print-type-size {}padding: {} bytes"
,
indent
,
pad
);
println!
(
"print-type-size {}field `.{}`: {} bytes,
\
alignment: {} bytes"
,
indent
,
name
,
size
,
align
);
}
else
{
println!
(
"print-type-size {}field `.{}`: {} bytes,
\
offset: {} bytes,
\
alignment: {} bytes"
,
indent
,
name
,
size
,
offset
,
align
);
}
}
else
{
if
offset
>
min_offset
{
let
pad
=
offset
-
min_offset
;
println!
(
"print-type-size {}padding: {} bytes"
,
indent
,
pad
);
}
if
offset
<
min_offset
{
// if this happens something is very wrong
println!
(
"print-type-size {}field `.{}`: {} bytes,
\
offset: {} bytes,
\
alignment: {} bytes"
,
indent
,
name
,
size
,
offset
,
align
);
}
else
if
info
.packed
||
offset
==
min_offset
{
println!
(
"print-type-size {}field `.{}`: {} bytes"
,
indent
,
name
,
size
);
}
else
{
// Include field alignment in output only if it caused padding injection
println!
(
"print-type-size {}field `.{}`: {} bytes,
\
alignment: {} bytes"
,
indent
,
name
,
size
,
align
);
}
min_offset
=
offset
+
size
;
...
...
src/librustc/ty/layout.rs
浏览文件 @
15d1c4d2
...
...
@@ -12,7 +12,7 @@
pub
use
self
::
Primitive
::
*
;
use
session
::{
self
,
DataTypeKind
,
Session
};
use
ty
::{
self
,
Ty
,
TyCtxt
,
TypeFoldable
,
ReprOptions
,
ReprFlags
};
use
ty
::{
self
,
Ty
,
TyCtxt
,
TypeFoldable
,
ReprOptions
};
use
syntax
::
ast
::{
self
,
FloatTy
,
IntTy
,
UintTy
};
use
syntax
::
attr
;
...
...
@@ -344,8 +344,8 @@ fn add_assign(&mut self, other: Size) {
/// a maximum capacity of 2<sup>31</sup> - 1 or 2147483647.
#[derive(Copy,
Clone,
PartialEq,
Eq,
Hash,
Debug,
RustcEncodable,
RustcDecodable)]
pub
struct
Align
{
abi
:
u8
,
pref
:
u8
,
abi
_pow2
:
u8
,
pref
_pow2
:
u8
,
}
impl
Align
{
...
...
@@ -377,17 +377,17 @@ pub fn from_bytes(abi: u64, pref: u64) -> Result<Align, String> {
};
Ok
(
Align
{
abi
:
log2
(
abi
)
?
,
pref
:
log2
(
pref
)
?
,
abi
_pow2
:
log2
(
abi
)
?
,
pref
_pow2
:
log2
(
pref
)
?
,
})
}
pub
fn
abi
(
self
)
->
u64
{
1
<<
self
.abi
1
<<
self
.abi
_pow2
}
pub
fn
pref
(
self
)
->
u64
{
1
<<
self
.pref
1
<<
self
.pref
_pow2
}
pub
fn
abi_bits
(
self
)
->
u64
{
...
...
@@ -400,15 +400,15 @@ pub fn pref_bits(self) -> u64 {
pub
fn
min
(
self
,
other
:
Align
)
->
Align
{
Align
{
abi
:
cmp
::
min
(
self
.abi
,
other
.abi
),
pref
:
cmp
::
min
(
self
.pref
,
other
.pref
),
abi
_pow2
:
cmp
::
min
(
self
.abi_pow2
,
other
.abi_pow2
),
pref
_pow2
:
cmp
::
min
(
self
.pref_pow2
,
other
.pref_pow2
),
}
}
pub
fn
max
(
self
,
other
:
Align
)
->
Align
{
Align
{
abi
:
cmp
::
max
(
self
.abi
,
other
.abi
),
pref
:
cmp
::
max
(
self
.pref
,
other
.pref
),
abi
_pow2
:
cmp
::
max
(
self
.abi_pow2
,
other
.abi_pow2
),
pref
_pow2
:
cmp
::
max
(
self
.pref_pow2
,
other
.pref_pow2
),
}
}
}
...
...
@@ -974,6 +974,11 @@ enum StructKind {
bug!
(
"struct cannot be packed and aligned"
);
}
let
pack
=
{
let
pack
=
repr
.pack
as
u64
;
Align
::
from_bytes
(
pack
,
pack
)
.unwrap
()
};
let
mut
align
=
if
packed
{
dl
.i8_align
}
else
{
...
...
@@ -984,8 +989,7 @@ enum StructKind {
let
mut
offsets
=
vec!
[
Size
::
from_bytes
(
0
);
fields
.len
()];
let
mut
inverse_memory_index
:
Vec
<
u32
>
=
(
0
..
fields
.len
()
as
u32
)
.collect
();
// Anything with repr(C) or repr(packed) doesn't optimize.
let
mut
optimize
=
(
repr
.flags
&
ReprFlags
::
IS_UNOPTIMISABLE
)
.is_empty
();
let
mut
optimize
=
!
repr
.inhibit_struct_field_reordering_opt
();
if
let
StructKind
::
Prefixed
(
_
,
align
)
=
kind
{
optimize
&=
align
.abi
()
==
1
;
}
...
...
@@ -997,6 +1001,9 @@ enum StructKind {
fields
.len
()
};
let
optimizing
=
&
mut
inverse_memory_index
[
..
end
];
let
field_align
=
|
f
:
&
TyLayout
|
{
if
packed
{
f
.align
.min
(
pack
)
.abi
()
}
else
{
f
.align
.abi
()
}
};
match
kind
{
StructKind
::
AlwaysSized
|
StructKind
::
MaybeUnsized
=>
{
...
...
@@ -1004,11 +1011,11 @@ enum StructKind {
// Place ZSTs first to avoid "interesting offsets",
// especially with only one or two non-ZST fields.
let
f
=
&
fields
[
x
as
usize
];
(
!
f
.is_zst
(),
cmp
::
Reverse
(
f
.align
.abi
(
)))
})
(
!
f
.is_zst
(),
cmp
::
Reverse
(
f
ield_align
(
f
)))
})
;
}
StructKind
::
Prefixed
(
..
)
=>
{
optimizing
.sort_by_key
(|
&
x
|
field
s
[
x
as
usize
]
.align
.abi
(
));
optimizing
.sort_by_key
(|
&
x
|
field
_align
(
&
fields
[
x
as
usize
]
));
}
}
}
...
...
@@ -1022,7 +1029,10 @@ enum StructKind {
let
mut
offset
=
Size
::
from_bytes
(
0
);
if
let
StructKind
::
Prefixed
(
prefix_size
,
prefix_align
)
=
kind
{
if
!
packed
{
if
packed
{
let
prefix_align
=
prefix_align
.min
(
pack
);
align
=
align
.max
(
prefix_align
);
}
else
{
align
=
align
.max
(
prefix_align
);
}
offset
=
prefix_size
.abi_align
(
prefix_align
);
...
...
@@ -1044,7 +1054,12 @@ enum StructKind {
}
// Invariant: offset < dl.obj_size_bound() <= 1<<61
if
!
packed
{
if
packed
{
let
field_pack
=
field
.align
.min
(
pack
);
offset
=
offset
.abi_align
(
field_pack
);
align
=
align
.max
(
field_pack
);
}
else
{
offset
=
offset
.abi_align
(
field
.align
);
align
=
align
.max
(
field
.align
);
}
...
...
@@ -1377,7 +1392,12 @@ enum StructKind {
bug!
(
"Union cannot be packed and aligned"
);
}
let
mut
align
=
if
def
.repr
.packed
()
{
let
pack
=
{
let
pack
=
def
.repr.pack
as
u64
;
Align
::
from_bytes
(
pack
,
pack
)
.unwrap
()
};
let
mut
align
=
if
packed
{
dl
.i8_align
}
else
{
dl
.aggregate_align
...
...
@@ -1393,7 +1413,10 @@ enum StructKind {
for
field
in
&
variants
[
0
]
{
assert
!
(
!
field
.is_unsized
());
if
!
packed
{
if
packed
{
let
field_pack
=
field
.align
.min
(
pack
);
align
=
align
.max
(
field_pack
);
}
else
{
align
=
align
.max
(
field
.align
);
}
size
=
cmp
::
max
(
size
,
field
.size
);
...
...
@@ -1740,12 +1763,13 @@ fn record_layout_for_printing(self, layout: TyLayout<'tcx>) {
fn
record_layout_for_printing_outlined
(
self
,
layout
:
TyLayout
<
'tcx
>
)
{
// (delay format until we actually need it)
let
record
=
|
kind
,
opt_discr_size
,
variants
|
{
let
record
=
|
kind
,
packed
,
opt_discr_size
,
variants
|
{
let
type_desc
=
format!
(
"{:?}"
,
layout
.ty
);
self
.tcx.sess.code_stats
.borrow_mut
()
.record_type_size
(
kind
,
type_desc
,
layout
.align
,
layout
.size
,
packed
,
opt_discr_size
,
variants
);
};
...
...
@@ -1758,7 +1782,7 @@ fn record_layout_for_printing_outlined(self, layout: TyLayout<'tcx>) {
ty
::
TyClosure
(
..
)
=>
{
debug!
(
"print-type-size t: `{:?}` record closure"
,
layout
.ty
);
record
(
DataTypeKind
::
Closure
,
None
,
vec!
[]);
record
(
DataTypeKind
::
Closure
,
false
,
None
,
vec!
[]);
return
;
}
...
...
@@ -1769,6 +1793,7 @@ fn record_layout_for_printing_outlined(self, layout: TyLayout<'tcx>) {
};
let
adt_kind
=
adt_def
.adt_kind
();
let
adt_packed
=
adt_def
.repr
.packed
();
let
build_variant_info
=
|
n
:
Option
<
ast
::
Name
>
,
flds
:
&
[
ast
::
Name
],
...
...
@@ -1821,6 +1846,7 @@ fn record_layout_for_printing_outlined(self, layout: TyLayout<'tcx>) {
let
fields
:
Vec
<
_
>
=
variant_def
.fields
.iter
()
.map
(|
f
|
f
.name
)
.collect
();
record
(
adt_kind
.into
(),
adt_packed
,
None
,
vec!
[
build_variant_info
(
Some
(
variant_def
.name
),
&
fields
,
...
...
@@ -1828,7 +1854,7 @@ fn record_layout_for_printing_outlined(self, layout: TyLayout<'tcx>) {
}
else
{
// (This case arises for *empty* enums; so give it
// zero variants.)
record
(
adt_kind
.into
(),
None
,
vec!
[]);
record
(
adt_kind
.into
(),
adt_packed
,
None
,
vec!
[]);
}
}
...
...
@@ -1845,7 +1871,7 @@ fn record_layout_for_printing_outlined(self, layout: TyLayout<'tcx>) {
layout
.for_variant
(
self
,
i
))
})
.collect
();
record
(
adt_kind
.into
(),
match
layout
.variants
{
record
(
adt_kind
.into
(),
adt_packed
,
match
layout
.variants
{
Variants
::
Tagged
{
ref
discr
,
..
}
=>
Some
(
discr
.value
.size
(
self
)),
_
=>
None
},
variant_infos
);
...
...
@@ -2518,8 +2544,8 @@ fn hash_stable<W: StableHasherResult>(&self,
});
impl_stable_hash_for!
(
struct
::
ty
::
layout
::
Align
{
abi
,
pref
abi
_pow2
,
pref
_pow2
});
impl_stable_hash_for!
(
struct
::
ty
::
layout
::
Size
{
...
...
src/librustc/ty/mod.rs
浏览文件 @
15d1c4d2
...
...
@@ -1623,15 +1623,13 @@ pub enum AdtKind { Struct, Union, Enum }
#[derive(RustcEncodable,
RustcDecodable,
Default)]
pub
struct
ReprFlags
:
u8
{
const
IS_C
=
1
<<
0
;
const
IS_PACKED
=
1
<<
1
;
const
IS_SIMD
=
1
<<
2
;
const
IS_TRANSPARENT
=
1
<<
3
;
const
IS_SIMD
=
1
<<
1
;
const
IS_TRANSPARENT
=
1
<<
2
;
// Internal only for now. If true, don't reorder fields.
const
IS_LINEAR
=
1
<<
4
;
const
IS_LINEAR
=
1
<<
3
;
// Any of these flags being set prevent field reordering optimisation.
const
IS_UNOPTIMISABLE
=
ReprFlags
::
IS_C
.bits
|
ReprFlags
::
IS_PACKED
.bits
|
ReprFlags
::
IS_SIMD
.bits
|
ReprFlags
::
IS_LINEAR
.bits
;
}
...
...
@@ -1648,11 +1646,13 @@ pub struct ReprFlags: u8 {
pub
struct
ReprOptions
{
pub
int
:
Option
<
attr
::
IntType
>
,
pub
align
:
u32
,
pub
pack
:
u32
,
pub
flags
:
ReprFlags
,
}
impl_stable_hash_for!
(
struct
ReprOptions
{
align
,
pack
,
int
,
flags
});
...
...
@@ -1662,11 +1662,19 @@ pub fn new(tcx: TyCtxt, did: DefId) -> ReprOptions {
let
mut
flags
=
ReprFlags
::
empty
();
let
mut
size
=
None
;
let
mut
max_align
=
0
;
let
mut
min_pack
=
0
;
for
attr
in
tcx
.get_attrs
(
did
)
.iter
()
{
for
r
in
attr
::
find_repr_attrs
(
tcx
.sess
.diagnostic
(),
attr
)
{
flags
.insert
(
match
r
{
attr
::
ReprC
=>
ReprFlags
::
IS_C
,
attr
::
ReprPacked
=>
ReprFlags
::
IS_PACKED
,
attr
::
ReprPacked
(
pack
)
=>
{
min_pack
=
if
min_pack
>
0
{
cmp
::
min
(
pack
,
min_pack
)
}
else
{
pack
};
ReprFlags
::
empty
()
},
attr
::
ReprTransparent
=>
ReprFlags
::
IS_TRANSPARENT
,
attr
::
ReprSimd
=>
ReprFlags
::
IS_SIMD
,
attr
::
ReprInt
(
i
)
=>
{
...
...
@@ -1685,7 +1693,7 @@ pub fn new(tcx: TyCtxt, did: DefId) -> ReprOptions {
if
!
tcx
.consider_optimizing
(||
format!
(
"Reorder fields of {:?}"
,
tcx
.item_path_str
(
did
)))
{
flags
.insert
(
ReprFlags
::
IS_LINEAR
);
}
ReprOptions
{
int
:
size
,
align
:
max_align
,
flags
:
flags
}
ReprOptions
{
int
:
size
,
align
:
max_align
,
pack
:
min_pack
,
flags
:
flags
}
}
#[inline]
...
...
@@ -1693,7 +1701,7 @@ pub fn simd(&self) -> bool { self.flags.contains(ReprFlags::IS_SIMD) }
#[inline]
pub
fn
c
(
&
self
)
->
bool
{
self
.flags
.contains
(
ReprFlags
::
IS_C
)
}
#[inline]
pub
fn
packed
(
&
self
)
->
bool
{
self
.
flags
.contains
(
ReprFlags
::
IS_PACKED
)
}
pub
fn
packed
(
&
self
)
->
bool
{
self
.
pack
>
0
}
#[inline]
pub
fn
transparent
(
&
self
)
->
bool
{
self
.flags
.contains
(
ReprFlags
::
IS_TRANSPARENT
)
}
#[inline]
...
...
@@ -1709,6 +1717,12 @@ pub fn discr_type(&self) -> attr::IntType {
pub
fn
inhibit_enum_layout_opt
(
&
self
)
->
bool
{
self
.c
()
||
self
.int
.is_some
()
}
/// Returns true if this `#[repr()]` should inhibit struct field reordering
/// optimizations, such as with repr(C) or repr(packed(1)).
pub
fn
inhibit_struct_field_reordering_opt
(
&
self
)
->
bool
{
!
(
self
.flags
&
ReprFlags
::
IS_UNOPTIMISABLE
)
.is_empty
()
||
(
self
.pack
==
1
)
}
}
impl
<
'a
,
'gcx
,
'tcx
>
AdtDef
{
...
...
src/librustc_typeck/check/mod.rs
浏览文件 @
15d1c4d2
...
...
@@ -1553,8 +1553,19 @@ pub fn check_simd<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: DefId
}
fn
check_packed
<
'a
,
'tcx
>
(
tcx
:
TyCtxt
<
'a
,
'tcx
,
'tcx
>
,
sp
:
Span
,
def_id
:
DefId
)
{
if
tcx
.adt_def
(
def_id
)
.repr
.packed
()
{
if
tcx
.adt_def
(
def_id
)
.repr.align
>
0
{
let
repr
=
tcx
.adt_def
(
def_id
)
.repr
;
if
repr
.packed
()
{
for
attr
in
tcx
.get_attrs
(
def_id
)
.iter
()
{
for
r
in
attr
::
find_repr_attrs
(
tcx
.sess
.diagnostic
(),
attr
)
{
if
let
attr
::
ReprPacked
(
pack
)
=
r
{
if
pack
!=
repr
.pack
{
struct_span_err!
(
tcx
.sess
,
sp
,
E0634
,
"type has conflicting packed representation hints"
)
.emit
();
}
}
}
}
if
repr
.align
>
0
{
struct_span_err!
(
tcx
.sess
,
sp
,
E0587
,
"type has conflicting packed and align representation hints"
)
.emit
();
}
...
...
src/librustc_typeck/diagnostics.rs
浏览文件 @
15d1c4d2
...
...
@@ -4836,14 +4836,15 @@ fn is_null(self: *const Self) -> bool {
// E0563, // cannot determine a type for this `impl Trait`: {} // removed in 6383de15
E0564
,
// only named lifetimes are allowed in `impl Trait`,
// but `{}` was found in the type `{}`
E0587
,
//
struct
has conflicting packed and align representation hints
E0588
,
// packed
struct cannot transitively contain a `[repr(align)]` struct
E0587
,
//
type
has conflicting packed and align representation hints
E0588
,
// packed
type cannot transitively contain a `[repr(align)]` type
E0592
,
// duplicate definitions with name `{}`
// E0613, // Removed (merged with E0609)
E0640
,
// infer outlives
E0627
,
// yield statement outside of generator literal
E0632
,
// cannot provide explicit type parameters when `impl Trait` is used in
// argument position.
E0634
,
// type has conflicting packed representaton hints
E0641
,
// cannot cast to/from a pointer with an unknown kind
E0645
,
// trait aliases not finished
E0907
,
// type inside generator must be known in this context
...
...
src/libsyntax/attr.rs
浏览文件 @
15d1c4d2
...
...
@@ -993,7 +993,7 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr>
let
word
=
&*
mi
.ident.name
.as_str
();
let
hint
=
match
word
{
"C"
=>
Some
(
ReprC
),
"packed"
=>
Some
(
ReprPacked
),
"packed"
=>
Some
(
ReprPacked
(
1
)
),
"simd"
=>
Some
(
ReprSimd
),
"transparent"
=>
Some
(
ReprTransparent
),
_
=>
match
int_type_of_word
(
word
)
{
...
...
@@ -1009,27 +1009,41 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr>
acc
.push
(
h
);
}
}
else
if
let
Some
((
name
,
value
))
=
item
.name_value_literal
()
{
if
name
==
"align"
{
recognised
=
true
;
let
mut
align_error
=
None
;
if
let
ast
::
LitKind
::
Int
(
align
,
ast
::
LitIntType
::
Unsuffixed
)
=
value
.node
{
if
align
.is_power_of_two
()
{
let
parse_alignment
=
|
node
:
&
ast
::
LitKind
|
->
Result
<
u32
,
&
'static
str
>
{
if
let
ast
::
LitKind
::
Int
(
literal
,
ast
::
LitIntType
::
Unsuffixed
)
=
node
{
if
literal
.is_power_of_two
()
{
// rustc::ty::layout::Align restricts align to <= 2147483647
if
align
<=
2147483647
{
acc
.push
(
ReprAlign
(
align
as
u32
));
if
*
literal
<=
2147483647
{
Ok
(
*
literal
as
u32
)
}
else
{
align_error
=
Some
(
"larger than 2147483647"
);
Err
(
"larger than 2147483647"
)
}
}
else
{
align_error
=
Some
(
"not a power of two"
);
Err
(
"not a power of two"
)
}
}
else
{
align_error
=
Some
(
"not an unsuffixed integer"
);
}
if
let
Some
(
align_error
)
=
align_error
{
span_err!
(
diagnostic
,
item
.span
,
E0589
,
"invalid `repr(align)` attribute: {}"
,
align_error
);
Err
(
"not an unsuffixed integer"
)
}
};
let
mut
literal_error
=
None
;
if
name
==
"align"
{
recognised
=
true
;
match
parse_alignment
(
&
value
.node
)
{
Ok
(
literal
)
=>
acc
.push
(
ReprAlign
(
literal
)),
Err
(
message
)
=>
literal_error
=
Some
(
message
)
};
}
else
if
name
==
"packed"
{
recognised
=
true
;
match
parse_alignment
(
&
value
.node
)
{
Ok
(
literal
)
=>
acc
.push
(
ReprPacked
(
literal
)),
Err
(
message
)
=>
literal_error
=
Some
(
message
)
};
}
if
let
Some
(
literal_error
)
=
literal_error
{
span_err!
(
diagnostic
,
item
.span
,
E0589
,
"invalid `repr(align)` attribute: {}"
,
literal_error
);
}
}
if
!
recognised
{
...
...
@@ -1065,7 +1079,7 @@ fn int_type_of_word(s: &str) -> Option<IntType> {
pub
enum
ReprAttr
{
ReprInt
(
IntType
),
ReprC
,
ReprPacked
,
ReprPacked
(
u32
)
,
ReprSimd
,
ReprTransparent
,
ReprAlign
(
u32
),
...
...
src/libsyntax/feature_gate.rs
浏览文件 @
15d1c4d2
...
...
@@ -432,6 +432,9 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
// Parentheses in patterns
(
active
,
pattern_parentheses
,
"1.26.0"
,
None
,
None
),
// Allows `#[repr(packed)]` attribute on structs
(
active
,
repr_packed
,
"1.26.0"
,
Some
(
33158
),
None
),
// `use path as _;` and `extern crate c as _;`
(
active
,
underscore_imports
,
"1.26.0"
,
Some
(
48216
),
None
),
...
...
@@ -1439,11 +1442,12 @@ fn visit_attribute(&mut self, attr: &ast::Attribute) {
}
}
// allow attr_literals in #[repr(align(x))]
let
mut
is_repr_align
=
false
;
// allow attr_literals in #[repr(align(x))]
and #[repr(packed(n))]
let
mut
allow_attr_literal
=
false
;
if
attr
.path
==
"repr"
{
if
let
Some
(
content
)
=
attr
.meta_item_list
()
{
is_repr_align
=
content
.iter
()
.any
(|
c
|
c
.check_name
(
"align"
));
allow_attr_literal
=
content
.iter
()
.any
(
|
c
|
c
.check_name
(
"align"
)
||
c
.check_name
(
"packed"
));
}
}
...
...
@@ -1451,7 +1455,7 @@ fn visit_attribute(&mut self, attr: &ast::Attribute) {
return
}
if
!
is_repr_align
{
if
!
allow_attr_literal
{
let
meta
=
panictry!
(
attr
.parse_meta
(
self
.context.parse_sess
));
if
contains_novel_literal
(
&
meta
)
{
gate_feature_post!
(
&
self
,
attr_literals
,
attr
.span
,
...
...
@@ -1535,6 +1539,13 @@ fn visit_item(&mut self, i: &'a ast::Item) {
"the `#[repr(transparent)]` attribute
\
is experimental"
);
}
if
let
Some
((
name
,
_
))
=
item
.name_value_literal
()
{
if
name
==
"packed"
{
gate_feature_post!
(
&
self
,
repr_packed
,
attr
.span
,
"the `#[repr(packed(n))]` attribute
\
is experimental"
);
}
}
}
}
}
...
...
src/libsyntax_ext/deriving/generic/mod.rs
浏览文件 @
15d1c4d2
...
...
@@ -413,8 +413,12 @@ pub fn expand_ext(self,
match
*
item
{
Annotatable
::
Item
(
ref
item
)
=>
{
let
is_packed
=
item
.attrs
.iter
()
.any
(|
attr
|
{
attr
::
find_repr_attrs
(
&
cx
.parse_sess.span_diagnostic
,
attr
)
.contains
(
&
attr
::
ReprPacked
)
for
r
in
attr
::
find_repr_attrs
(
&
cx
.parse_sess.span_diagnostic
,
attr
)
{
if
let
attr
::
ReprPacked
(
_
)
=
r
{
return
true
;
}
}
false
});
let
has_no_type_params
=
match
item
.node
{
ast
::
ItemKind
::
Struct
(
_
,
ref
generics
)
|
...
...
@@ -831,7 +835,7 @@ fn find_repr_type_name(diagnostic: &Handler, type_attrs: &[ast::Attribute]) -> &
for
a
in
type_attrs
{
for
r
in
&
attr
::
find_repr_attrs
(
diagnostic
,
a
)
{
repr_type_name
=
match
*
r
{
attr
::
ReprPacked
|
attr
::
ReprSimd
|
attr
::
ReprAlign
(
_
)
|
attr
::
ReprTransparent
=>
attr
::
ReprPacked
(
_
)
|
attr
::
ReprSimd
|
attr
::
ReprAlign
(
_
)
|
attr
::
ReprTransparent
=>
continue
,
attr
::
ReprC
=>
"i32"
,
...
...
src/test/codegen/packed.rs
浏览文件 @
15d1c4d2
...
...
@@ -11,16 +11,23 @@
// compile-flags: -C no-prepopulate-passes
#![crate_type
=
"lib"
]
#![feature(repr_packed)]
#[repr(packed)]
pub
struct
Packed
{
pub
struct
Packed
1
{
dealign
:
u8
,
data
:
u32
}
// CHECK-LABEL: @write_pkd
#[repr(packed(
2
))]
pub
struct
Packed2
{
dealign
:
u8
,
data
:
u32
}
// CHECK-LABEL: @write_pkd1
#[no_mangle]
pub
fn
write_pkd
(
pkd
:
&
mut
Packed
)
->
u32
{
pub
fn
write_pkd
1
(
pkd
:
&
mut
Packed1
)
->
u32
{
// CHECK: %{{.*}} = load i32, i32* %{{.*}}, align 1
// CHECK: store i32 42, i32* %{{.*}}, align 1
let
result
=
pkd
.data
;
...
...
@@ -28,43 +35,94 @@ pub fn write_pkd(pkd: &mut Packed) -> u32 {
result
}
// CHECK-LABEL: @write_pkd2
#[no_mangle]
pub
fn
write_pkd2
(
pkd
:
&
mut
Packed2
)
->
u32
{
// CHECK: %{{.*}} = load i32, i32* %{{.*}}, align 2
// CHECK: store i32 42, i32* %{{.*}}, align 2
let
result
=
pkd
.data
;
pkd
.data
=
42
;
result
}
pub
struct
Array
([
i32
;
8
]);
#[repr(packed)]
pub
struct
BigPacked
{
pub
struct
BigPacked1
{
dealign
:
u8
,
data
:
Array
}
#[repr(packed(
2
))]
pub
struct
BigPacked2
{
dealign
:
u8
,
data
:
Array
}
// CHECK-LABEL: @call_pkd
// CHECK-LABEL: @call_pkd
1
#[no_mangle]
pub
fn
call_pkd
(
f
:
fn
()
->
Array
)
->
BigPacked
{
pub
fn
call_pkd
1
(
f
:
fn
()
->
Array
)
->
BigPacked1
{
// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
// CHECK: call void %{{.*}}(%Array* noalias nocapture sret dereferenceable(32) [[ALLOCA]])
// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 32, i32 1, i1 false)
// check that calls whose destination is a field of a packed struct
// go through an alloca rather than calling the function with an
// unaligned destination.
BigPacked
{
dealign
:
0
,
data
:
f
()
}
BigPacked1
{
dealign
:
0
,
data
:
f
()
}
}
// CHECK-LABEL: @call_pkd2
#[no_mangle]
pub
fn
call_pkd2
(
f
:
fn
()
->
Array
)
->
BigPacked2
{
// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
// CHECK: call void %{{.*}}(%Array* noalias nocapture sret dereferenceable(32) [[ALLOCA]])
// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 32, i32 2, i1 false)
// check that calls whose destination is a field of a packed struct
// go through an alloca rather than calling the function with an
// unaligned destination.
BigPacked2
{
dealign
:
0
,
data
:
f
()
}
}
#[repr(packed)]
#[derive(Copy,
Clone)]
pub
struct
PackedPair
(
u8
,
u32
);
pub
struct
Packed
1
Pair
(
u8
,
u32
);
// CHECK-LABEL: @pkd_pair
#[repr(packed(
2
))]
#[derive(Copy,
Clone)]
pub
struct
Packed2Pair
(
u8
,
u32
);
// CHECK-LABEL: @pkd1_pair
#[no_mangle]
pub
fn
pkd
_pair
(
pair1
:
&
mut
PackedPair
,
pair2
:
&
mut
Packed
Pair
)
{
pub
fn
pkd
1_pair
(
pair1
:
&
mut
Packed1Pair
,
pair2
:
&
mut
Packed1
Pair
)
{
// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 5, i32 1, i1 false)
*
pair2
=
*
pair1
;
}
// CHECK-LABEL: @pkd2_pair
#[no_mangle]
pub
fn
pkd2_pair
(
pair1
:
&
mut
Packed2Pair
,
pair2
:
&
mut
Packed2Pair
)
{
// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 6, i32 2, i1 false)
*
pair2
=
*
pair1
;
}
#[repr(packed)]
#[derive(Copy,
Clone)]
pub
struct
PackedNestedPair
((
u32
,
u32
));
pub
struct
Packed1NestedPair
((
u32
,
u32
));
#[repr(packed(
2
))]
#[derive(Copy,
Clone)]
pub
struct
Packed2NestedPair
((
u32
,
u32
));
// CHECK-LABEL: @pkd_nested_pair
// CHECK-LABEL: @pkd
1
_nested_pair
#[no_mangle]
pub
fn
pkd
_nested_pair
(
pair1
:
&
mut
PackedNestedPair
,
pair2
:
&
mut
Packed
NestedPair
)
{
pub
fn
pkd
1_nested_pair
(
pair1
:
&
mut
Packed1NestedPair
,
pair2
:
&
mut
Packed1
NestedPair
)
{
// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 8, i32 1, i1 false)
*
pair2
=
*
pair1
;
}
// CHECK-LABEL: @pkd2_nested_pair
#[no_mangle]
pub
fn
pkd2_nested_pair
(
pair1
:
&
mut
Packed2NestedPair
,
pair2
:
&
mut
Packed2NestedPair
)
{
// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 8, i32 2, i1 false)
*
pair2
=
*
pair1
;
}
src/test/compile-fail/conflicting-repr-hints.rs
浏览文件 @
15d1c4d2
...
...
@@ -9,6 +9,7 @@
// except according to those terms.
#![allow(dead_code)]
#![feature(repr_packed)]
#[repr(C)]
enum
A
{
A
}
...
...
@@ -36,6 +37,16 @@ enum D { D }
#[repr(packed)]
struct
H
(
i32
);
//~ ERROR type has conflicting packed and align representation hints
#[repr(packed,
packed(
2
))]
struct
I
(
i32
);
//~ ERROR type has conflicting packed representation hints
#[repr(packed(
2
))]
#[repr(packed)]
struct
J
(
i32
);
//~ ERROR type has conflicting packed representation hints
#[repr(packed,
packed(
1
))]
struct
K
(
i32
);
#[repr(packed,
align(
8
))]
union
X
{
//~ ERROR type has conflicting packed and align representation hints
i
:
i32
...
...
src/test/run-pass/align-struct.rs
浏览文件 @
15d1c4d2
...
...
@@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(box_syntax)]
#![feature(repr_packed)]
use
std
::
mem
;
...
...
@@ -60,6 +61,18 @@ struct AlignContainsPacked {
b
:
Packed
,
}
#[repr(C,
packed(
4
))]
struct
Packed4C
{
a
:
u32
,
b
:
u64
,
}
#[repr(align(
16
))]
struct
AlignContainsPacked4C
{
a
:
Packed4C
,
b
:
u64
,
}
// The align limit was originally smaller (2^15).
// Check that it works with big numbers.
#[repr(align(
0x10000
))]
...
...
@@ -218,6 +231,15 @@ pub fn main() {
assert_eq!
(
mem
::
size_of_val
(
&
a
),
16
);
assert
!
(
is_aligned_to
(
&
a
,
16
));
assert_eq!
(
mem
::
align_of
::
<
AlignContainsPacked4C
>
(),
16
);
assert_eq!
(
mem
::
size_of
::
<
AlignContainsPacked4C
>
(),
32
);
let
a
=
AlignContainsPacked4C
{
a
:
Packed4C
{
a
:
1
,
b
:
2
},
b
:
3
};
assert_eq!
(
mem
::
align_of_val
(
&
a
),
16
);
assert_eq!
(
mem
::
align_of_val
(
&
a
.a
),
4
);
assert_eq!
(
mem
::
align_of_val
(
&
a
.b
),
mem
::
align_of
::
<
u64
>
());
assert_eq!
(
mem
::
size_of_val
(
&
a
),
32
);
assert
!
(
is_aligned_to
(
&
a
,
16
));
let
mut
large
=
box
AlignLarge
{
stuff
:
[
0
;
0x10000
],
};
...
...
src/test/run-pass/auxiliary/packed.rs
浏览文件 @
15d1c4d2
...
...
@@ -8,8 +8,24 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(repr_packed)]
#[repr(packed)]
pub
struct
S
{
pub
struct
P1S5
{
a
:
u8
,
b
:
u32
}
#[repr(packed(
2
))]
pub
struct
P2S6
{
a
:
u8
,
b
:
u32
,
c
:
u8
}
#[repr(C,
packed(
2
))]
pub
struct
P2CS8
{
a
:
u8
,
b
:
u32
,
c
:
u8
}
src/test/run-pass/issue-48159.rs
0 → 100644
浏览文件 @
15d1c4d2
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(repr_packed)]
#![allow(non_camel_case_types)]
use
std
::
mem
;
pub
enum
c_void
{}
type
uintptr_t
=
usize
;
type
int16_t
=
u16
;
type
uint16_t
=
int16_t
;
type
uint32_t
=
u32
;
type
intptr_t
=
uintptr_t
;
#[repr(C)]
#[repr(packed(
4
))]
pub
struct
kevent
{
pub
ident
:
uintptr_t
,
pub
filter
:
int16_t
,
pub
flags
:
uint16_t
,
pub
fflags
:
uint32_t
,
pub
data
:
intptr_t
,
pub
udata
:
*
mut
c_void
,
}
fn
main
()
{
assert_eq!
(
mem
::
align_of
::
<
kevent
>
(),
4
);
}
src/test/run-pass/packed-struct-borrow-element.rs
浏览文件 @
15d1c4d2
...
...
@@ -10,15 +10,36 @@
// ignore-emscripten weird assertion?
#![feature(repr_packed)]
#[repr(packed)]
struct
Foo
{
struct
Foo1
{
bar
:
u8
,
baz
:
usize
}
#[repr(packed(
2
))]
struct
Foo2
{
bar
:
u8
,
baz
:
usize
}
#[repr(C,
packed(
4
))]
struct
Foo4C
{
bar
:
u8
,
baz
:
usize
}
pub
fn
main
()
{
let
foo
=
Foo
{
bar
:
1
,
baz
:
2
};
let
foo
=
Foo
1
{
bar
:
1
,
baz
:
2
};
let
brw
=
unsafe
{
&
foo
.baz
};
assert_eq!
(
*
brw
,
2
);
let
foo
=
Foo2
{
bar
:
1
,
baz
:
2
};
let
brw
=
unsafe
{
&
foo
.baz
};
assert_eq!
(
*
brw
,
2
);
let
foo
=
Foo4C
{
bar
:
1
,
baz
:
2
};
let
brw
=
unsafe
{
&
foo
.baz
};
assert_eq!
(
*
brw
,
2
);
}
src/test/run-pass/packed-struct-generic-size.rs
浏览文件 @
15d1c4d2
...
...
@@ -8,18 +8,45 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(repr_packed)]
use
std
::
mem
;
#[repr(packed)]
struct
S
<
T
,
S
>
{
struct
P1
<
T
,
S
>
{
a
:
T
,
b
:
u8
,
c
:
S
}
#[repr(packed(
2
))]
struct
P2
<
T
,
S
>
{
a
:
T
,
b
:
u8
,
c
:
S
}
#[repr(C,
packed(
4
))]
struct
P4C
<
T
,
S
>
{
a
:
T
,
b
:
u8
,
c
:
S
}
macro_rules!
check
{
(
$t:ty
,
$align:expr
,
$size:expr
)
=>
({
assert_eq!
(
mem
::
align_of
::
<
$t
>
(),
$align
);
assert_eq!
(
mem
::
size_of
::
<
$t
>
(),
$size
);
});
}
pub
fn
main
()
{
assert_eq!
(
mem
::
size_of
::
<
S
<
u8
,
u8
>>
(),
3
);
check!
(
P1
::
<
u8
,
u8
>
,
1
,
3
);
check!
(
P1
::
<
u64
,
u16
>
,
1
,
11
);
check!
(
P2
::
<
u8
,
u8
>
,
1
,
3
);
check!
(
P2
::
<
u64
,
u16
>
,
2
,
12
);
assert_eq!
(
mem
::
size_of
::
<
S
<
u64
,
u16
>>
(),
11
);
check!
(
P4C
::
<
u8
,
u8
>
,
1
,
3
);
check!
(
P4C
::
<
u16
,
u64
>
,
4
,
12
);
}
src/test/run-pass/packed-struct-match.rs
浏览文件 @
15d1c4d2
...
...
@@ -8,17 +8,46 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(repr_packed)]
#[repr(packed)]
struct
Foo
{
struct
Foo1
{
bar
:
u8
,
baz
:
usize
}
#[repr(packed(
2
))]
struct
Foo2
{
bar
:
u8
,
baz
:
usize
}
#[repr(C,
packed(
4
))]
struct
Foo4C
{
bar
:
u8
,
baz
:
usize
}
pub
fn
main
()
{
let
foo
=
Foo
{
bar
:
1
,
baz
:
2
};
match
foo
{
Foo
{
bar
,
baz
}
=>
{
let
foo1
=
Foo1
{
bar
:
1
,
baz
:
2
};
match
foo1
{
Foo1
{
bar
,
baz
}
=>
{
assert_eq!
(
bar
,
1
);
assert_eq!
(
baz
,
2
);
}
}
let
foo2
=
Foo2
{
bar
:
1
,
baz
:
2
};
match
foo2
{
Foo2
{
bar
,
baz
}
=>
{
assert_eq!
(
bar
,
1
);
assert_eq!
(
baz
,
2
);
}
}
let
foo4
=
Foo4C
{
bar
:
1
,
baz
:
2
};
match
foo4
{
Foo4C
{
bar
,
baz
}
=>
{
assert_eq!
(
bar
,
1
);
assert_eq!
(
baz
,
2
);
}
...
...
src/test/run-pass/packed-struct-size-xc.rs
浏览文件 @
15d1c4d2
...
...
@@ -15,6 +15,15 @@
use
std
::
mem
;
macro_rules!
check
{
(
$t:ty
,
$align:expr
,
$size:expr
)
=>
({
assert_eq!
(
mem
::
align_of
::
<
$t
>
(),
$align
);
assert_eq!
(
mem
::
size_of
::
<
$t
>
(),
$size
);
});
}
pub
fn
main
()
{
assert_eq!
(
mem
::
size_of
::
<
packed
::
S
>
(),
5
);
check!
(
packed
::
P1S5
,
1
,
5
);
check!
(
packed
::
P2S6
,
2
,
6
);
check!
(
packed
::
P2CS8
,
2
,
8
);
}
src/test/run-pass/packed-struct-size.rs
浏览文件 @
15d1c4d2
...
...
@@ -7,44 +7,116 @@
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(repr_packed)]
use
std
::
mem
;
#[repr(packed)]
struct
S4
{
struct
P1S4
{
a
:
u8
,
b
:
[
u8
;
3
],
}
#[repr(packed(
2
))]
struct
P2S4
{
a
:
u8
,
b
:
[
u8
;
3
],
}
#[repr(packed)]
struct
S5
{
struct
P1S5
{
a
:
u8
,
b
:
u32
}
#[repr(packed(
2
))]
struct
P2S2
{
a
:
u8
,
b
:
u8
}
#[repr(packed(
2
))]
struct
P2S6
{
a
:
u8
,
b
:
u32
}
#[repr(packed(
2
))]
struct
P2S12
{
a
:
u32
,
b
:
u64
}
#[repr(packed)]
struct
S13
{
struct
P1
S13
{
a
:
i64
,
b
:
f32
,
c
:
u8
,
}
#[repr(packed(
2
))]
struct
P2S14
{
a
:
i64
,
b
:
f32
,
c
:
u8
,
}
#[repr(packed(
4
))]
struct
P4S16
{
a
:
u8
,
b
:
f32
,
c
:
i64
,
d
:
u16
,
}
#[repr(C,
packed(
4
))]
struct
P4CS20
{
a
:
u8
,
b
:
f32
,
c
:
i64
,
d
:
u16
,
}
enum
Foo
{
Bar
=
1
,
Baz
=
2
}
#[repr(packed)]
struct
S3_Foo
{
struct
P1S3_Foo
{
a
:
u8
,
b
:
u16
,
c
:
Foo
}
#[repr(packed(
2
))]
struct
P2_Foo
{
a
:
Foo
,
}
#[repr(packed(
2
))]
struct
P2S3_Foo
{
a
:
u8
,
b
:
u16
,
c
:
Foo
}
#[repr(packed)]
struct
S7_Option
{
struct
P1S7_Option
{
a
:
f32
,
b
:
u8
,
c
:
u16
,
d
:
Option
<
Box
<
f64
>>
}
#[repr(packed(
2
))]
struct
P2_Option
{
a
:
Option
<
Box
<
f64
>>
}
#[repr(packed(
2
))]
struct
P2S7_Option
{
a
:
f32
,
b
:
u8
,
c
:
u16
,
...
...
@@ -52,15 +124,41 @@ struct S7_Option {
}
// Placing packed structs in statics should work
static
TEST_S4
:
S4
=
S4
{
a
:
1
,
b
:
[
2
,
3
,
4
]
};
static
TEST_S5
:
S5
=
S5
{
a
:
3
,
b
:
67
};
static
TEST_S3_Foo
:
S3_Foo
=
S3_Foo
{
a
:
1
,
b
:
2
,
c
:
Foo
::
Baz
};
static
TEST_P1S4
:
P1S4
=
P1S4
{
a
:
1
,
b
:
[
2
,
3
,
4
]
};
static
TEST_P1S5
:
P1S5
=
P1S5
{
a
:
3
,
b
:
67
};
static
TEST_P1S3_Foo
:
P1S3_Foo
=
P1S3_Foo
{
a
:
1
,
b
:
2
,
c
:
Foo
::
Baz
};
static
TEST_P2S2
:
P2S2
=
P2S2
{
a
:
1
,
b
:
2
};
static
TEST_P2S4
:
P2S4
=
P2S4
{
a
:
1
,
b
:
[
2
,
3
,
4
]
};
static
TEST_P2S6
:
P2S6
=
P2S6
{
a
:
1
,
b
:
2
};
static
TEST_P2S12
:
P2S12
=
P2S12
{
a
:
1
,
b
:
2
};
static
TEST_P4S16
:
P4S16
=
P4S16
{
a
:
1
,
b
:
2.0
,
c
:
3
,
d
:
4
};
static
TEST_P4CS20
:
P4CS20
=
P4CS20
{
a
:
1
,
b
:
2.0
,
c
:
3
,
d
:
4
};
fn
align_to
(
value
:
usize
,
align
:
usize
)
->
usize
{
(
value
+
(
align
-
1
))
&
!
(
align
-
1
)
}
macro_rules!
check
{
(
$t:ty
,
$align:expr
,
$size:expr
)
=>
({
assert_eq!
(
mem
::
align_of
::
<
$t
>
(),
$align
);
assert_eq!
(
mem
::
size_of
::
<
$t
>
(),
$size
);
});
}
pub
fn
main
()
{
assert_eq!
(
mem
::
size_of
::
<
S4
>
(),
4
);
assert_eq!
(
mem
::
size_of
::
<
S5
>
(),
5
);
assert_eq!
(
mem
::
size_of
::
<
S13
>
(),
13
);
assert_eq!
(
mem
::
size_of
::
<
S3_Foo
>
(),
3
+
mem
::
size_of
::
<
Foo
>
());
assert_eq!
(
mem
::
size_of
::
<
S7_Option
>
(),
7
+
mem
::
size_of
::
<
Option
<
Box
<
f64
>>>
());
check!
(
P1S4
,
1
,
4
);
check!
(
P1S5
,
1
,
5
);
check!
(
P1S13
,
1
,
13
);
check!
(
P1S3_Foo
,
1
,
3
+
mem
::
size_of
::
<
Foo
>
());
check!
(
P1S7_Option
,
1
,
7
+
mem
::
size_of
::
<
Option
<
Box
<
f64
>>>
());
check!
(
P2S2
,
1
,
2
);
check!
(
P2S4
,
1
,
4
);
check!
(
P2S6
,
2
,
6
);
check!
(
P2S12
,
2
,
12
);
check!
(
P2S14
,
2
,
14
);
check!
(
P4S16
,
4
,
16
);
check!
(
P4CS20
,
4
,
20
);
check!
(
P2S3_Foo
,
2
,
align_to
(
3
+
mem
::
size_of
::
<
P2_Foo
>
(),
2
));
check!
(
P2S7_Option
,
2
,
align_to
(
7
+
mem
::
size_of
::
<
P2_Option
>
(),
2
));
}
src/test/run-pass/packed-struct-vec.rs
浏览文件 @
15d1c4d2
...
...
@@ -8,28 +8,80 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(repr_packed)]
use
std
::
fmt
;
use
std
::
mem
;
#[repr(packed)]
#[derive(Copy,
Clone)]
struct
Foo
{
struct
Foo
1
{
bar
:
u8
,
baz
:
u64
}
impl
PartialEq
for
Foo
{
fn
eq
(
&
self
,
other
:
&
Foo
)
->
bool
{
impl
PartialEq
for
Foo
1
{
fn
eq
(
&
self
,
other
:
&
Foo
1
)
->
bool
{
self
.bar
==
other
.bar
&&
self
.baz
==
other
.baz
}
}
impl
fmt
::
Debug
for
Foo
{
impl
fmt
::
Debug
for
Foo
1
{
fn
fmt
(
&
self
,
f
:
&
mut
fmt
::
Formatter
)
->
fmt
::
Result
{
let
bar
=
self
.bar
;
let
baz
=
self
.baz
;
f
.debug_struct
(
"Foo"
)
f
.debug_struct
(
"Foo1"
)
.field
(
"bar"
,
&
bar
)
.field
(
"baz"
,
&
baz
)
.finish
()
}
}
#[repr(packed(
2
))]
#[derive(Copy,
Clone)]
struct
Foo2
{
bar
:
u8
,
baz
:
u64
}
impl
PartialEq
for
Foo2
{
fn
eq
(
&
self
,
other
:
&
Foo2
)
->
bool
{
self
.bar
==
other
.bar
&&
self
.baz
==
other
.baz
}
}
impl
fmt
::
Debug
for
Foo2
{
fn
fmt
(
&
self
,
f
:
&
mut
fmt
::
Formatter
)
->
fmt
::
Result
{
let
bar
=
self
.bar
;
let
baz
=
self
.baz
;
f
.debug_struct
(
"Foo2"
)
.field
(
"bar"
,
&
bar
)
.field
(
"baz"
,
&
baz
)
.finish
()
}
}
#[repr(C,
packed(
4
))]
#[derive(Copy,
Clone)]
struct
Foo4C
{
bar
:
u8
,
baz
:
u64
}
impl
PartialEq
for
Foo4C
{
fn
eq
(
&
self
,
other
:
&
Foo4C
)
->
bool
{
self
.bar
==
other
.bar
&&
self
.baz
==
other
.baz
}
}
impl
fmt
::
Debug
for
Foo4C
{
fn
fmt
(
&
self
,
f
:
&
mut
fmt
::
Formatter
)
->
fmt
::
Result
{
let
bar
=
self
.bar
;
let
baz
=
self
.baz
;
f
.debug_struct
(
"Foo4C"
)
.field
(
"bar"
,
&
bar
)
.field
(
"baz"
,
&
baz
)
.finish
()
...
...
@@ -37,15 +89,42 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
pub
fn
main
()
{
let
foos
=
[
Foo
{
bar
:
1
,
baz
:
2
};
10
];
let
foo1s
=
[
Foo1
{
bar
:
1
,
baz
:
2
};
10
];
assert_eq!
(
mem
::
align_of
::
<
[
Foo1
;
10
]
>
(),
1
);
assert_eq!
(
mem
::
size_of
::
<
[
Foo1
;
10
]
>
(),
90
);
for
i
in
0
..
10
{
assert_eq!
(
foo1s
[
i
],
Foo1
{
bar
:
1
,
baz
:
2
});
}
for
&
foo
in
&
foo1s
{
assert_eq!
(
foo
,
Foo1
{
bar
:
1
,
baz
:
2
});
}
let
foo2s
=
[
Foo2
{
bar
:
1
,
baz
:
2
};
10
];
assert_eq!
(
mem
::
align_of
::
<
[
Foo2
;
10
]
>
(),
2
);
assert_eq!
(
mem
::
size_of
::
<
[
Foo2
;
10
]
>
(),
100
);
for
i
in
0
..
10
{
assert_eq!
(
foo2s
[
i
],
Foo2
{
bar
:
1
,
baz
:
2
});
}
for
&
foo
in
&
foo2s
{
assert_eq!
(
foo
,
Foo2
{
bar
:
1
,
baz
:
2
});
}
let
foo4s
=
[
Foo4C
{
bar
:
1
,
baz
:
2
};
10
];
assert_eq!
(
mem
::
size_of
::
<
[
Foo
;
10
]
>
(),
90
);
assert_eq!
(
mem
::
align_of
::
<
[
Foo4C
;
10
]
>
(),
4
);
assert_eq!
(
mem
::
size_of
::
<
[
Foo4C
;
10
]
>
(),
120
);
for
i
in
0
..
10
{
assert_eq!
(
foo
s
[
i
],
Foo
{
bar
:
1
,
baz
:
2
});
assert_eq!
(
foo
4s
[
i
],
Foo4C
{
bar
:
1
,
baz
:
2
});
}
for
&
foo
in
&
foos
{
assert_eq!
(
foo
,
Foo
{
bar
:
1
,
baz
:
2
});
for
&
foo
in
&
foo
4
s
{
assert_eq!
(
foo
,
Foo
4C
{
bar
:
1
,
baz
:
2
});
}
}
src/test/run-pass/packed-tuple-struct-size.rs
浏览文件 @
15d1c4d2
...
...
@@ -8,18 +8,33 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(repr_packed)]
use
std
::
mem
;
#[repr(packed)]
struct
S4
(
u8
,[
u8
;
3
]);
struct
P1S4
(
u8
,[
u8
;
3
]);
#[repr(packed(
2
))]
struct
P2S4
(
u8
,[
u8
;
3
]);
#[repr(packed)]
struct
S5
(
u8
,
u32
);
struct
P1S5
(
u8
,
u32
);
#[repr(packed(
2
))]
struct
P2S6
(
u8
,
u32
);
#[repr(packed)]
struct
S13
(
i64
,
f32
,
u8
);
struct
P1S13
(
i64
,
f32
,
u8
);
#[repr(packed(
2
))]
struct
P2S14
(
i64
,
f32
,
u8
);
#[repr(packed(
4
))]
struct
P4S16
(
u8
,
f32
,
i64
,
u16
);
#[repr(C,
packed(
4
))]
struct
P4CS20
(
u8
,
f32
,
i64
,
u16
);
enum
Foo
{
Bar
=
1
,
...
...
@@ -27,21 +42,46 @@ enum Foo {
}
#[repr(packed)]
struct
S3_Foo
(
u8
,
u16
,
Foo
);
struct
P1S3_Foo
(
u8
,
u16
,
Foo
);
#[repr(packed(
2
))]
struct
P2_Foo
(
Foo
);
#[repr(packed(
2
))]
struct
P2S3_Foo
(
u8
,
u16
,
Foo
);
#[repr(packed)]
struct
S7_Option
(
f32
,
u8
,
u16
,
Option
<
Box
<
f64
>>
);
struct
P1
S7_Option
(
f32
,
u8
,
u16
,
Option
<
Box
<
f64
>>
);
pub
fn
main
()
{
assert_eq!
(
mem
::
size_of
::
<
S4
>
(),
4
);
#[repr(packed(
2
))]
struct
P2_Option
(
Option
<
Box
<
f64
>>
);
#[repr(packed(
2
))]
struct
P2S7_Option
(
f32
,
u8
,
u16
,
Option
<
Box
<
f64
>>
);
assert_eq!
(
mem
::
size_of
::
<
S5
>
(),
5
);
fn
align_to
(
value
:
usize
,
align
:
usize
)
->
usize
{
(
value
+
(
align
-
1
))
&
!
(
align
-
1
)
}
assert_eq!
(
mem
::
size_of
::
<
S13
>
(),
13
);
macro_rules!
check
{
(
$t:ty
,
$align:expr
,
$size:expr
)
=>
({
assert_eq!
(
mem
::
align_of
::
<
$t
>
(),
$align
);
assert_eq!
(
mem
::
size_of
::
<
$t
>
(),
$size
);
});
}
assert_eq!
(
mem
::
size_of
::
<
S3_Foo
>
(),
3
+
mem
::
size_of
::
<
Foo
>
());
pub
fn
main
()
{
check!
(
P1S4
,
1
,
4
);
check!
(
P1S5
,
1
,
5
);
check!
(
P1S13
,
1
,
13
);
check!
(
P1S3_Foo
,
1
,
3
+
mem
::
size_of
::
<
Foo
>
());
check!
(
P1S7_Option
,
1
,
7
+
mem
::
size_of
::
<
Option
<
Box
<
f64
>>>
());
assert_eq!
(
mem
::
size_of
::
<
S7_Option
>
(),
7
+
mem
::
size_of
::
<
Option
<
Box
<
f64
>>>
());
check!
(
P2S4
,
1
,
4
);
check!
(
P2S6
,
2
,
6
);
check!
(
P2S14
,
2
,
14
);
check!
(
P4S16
,
4
,
16
);
check!
(
P4CS20
,
4
,
20
);
check!
(
P2S3_Foo
,
2
,
align_to
(
3
+
mem
::
size_of
::
<
P2_Foo
>
(),
2
));
check!
(
P2S7_Option
,
2
,
align_to
(
7
+
mem
::
size_of
::
<
P2_Option
>
(),
2
));
}
src/test/run-pass/union/union-packed.rs
浏览文件 @
15d1c4d2
...
...
@@ -9,6 +9,7 @@
// except according to those terms.
#![feature(untagged_unions)]
#![feature(repr_packed)]
use
std
::
mem
::{
size_of
,
size_of_val
,
align_of
,
align_of_val
};
...
...
@@ -18,7 +19,13 @@ struct S {
}
#[repr(packed)]
struct
Sp
{
struct
Sp1
{
a
:
u16
,
b
:
[
u8
;
3
],
}
#[repr(packed(
2
))]
struct
Sp2
{
a
:
u16
,
b
:
[
u8
;
3
],
}
...
...
@@ -29,15 +36,30 @@ union U {
}
#[repr(packed)]
union
Up
{
union
Up1
{
a
:
u16
,
b
:
[
u8
;
3
],
}
#[repr(packed(
2
))]
union
Up2
{
a
:
u16
,
b
:
[
u8
;
3
],
}
#[repr(C,
packed(
4
))]
union
Up4c
{
a
:
u16
,
b
:
[
u8
;
3
],
}
const
CS
:
S
=
S
{
a
:
0
,
b
:
[
0
,
0
,
0
]
};
const
CSP
:
Sp
=
Sp
{
a
:
0
,
b
:
[
0
,
0
,
0
]
};
const
CSP1
:
Sp1
=
Sp1
{
a
:
0
,
b
:
[
0
,
0
,
0
]
};
const
CSP2
:
Sp2
=
Sp2
{
a
:
0
,
b
:
[
0
,
0
,
0
]
};
const
CU
:
U
=
U
{
b
:
[
0
,
0
,
0
]
};
const
CUP
:
Up
=
Up
{
b
:
[
0
,
0
,
0
]
};
const
CUP1
:
Up1
=
Up1
{
b
:
[
0
,
0
,
0
]
};
const
CUP2
:
Up2
=
Up2
{
b
:
[
0
,
0
,
0
]
};
const
CUP4C
:
Up4c
=
Up4c
{
b
:
[
0
,
0
,
0
]
};
fn
main
()
{
let
s
=
S
{
a
:
0
,
b
:
[
0
,
0
,
0
]
};
...
...
@@ -48,13 +70,21 @@ fn main() {
assert_eq!
(
align_of_val
(
&
s
),
2
);
assert_eq!
(
align_of_val
(
&
CS
),
2
);
let
sp
=
Sp
{
a
:
0
,
b
:
[
0
,
0
,
0
]
};
assert_eq!
(
size_of
::
<
Sp
>
(),
5
);
assert_eq!
(
size_of_val
(
&
sp
),
5
);
assert_eq!
(
size_of_val
(
&
CSP
),
5
);
assert_eq!
(
align_of
::
<
Sp
>
(),
1
);
assert_eq!
(
align_of_val
(
&
sp
),
1
);
assert_eq!
(
align_of_val
(
&
CSP
),
1
);
let
sp1
=
Sp1
{
a
:
0
,
b
:
[
0
,
0
,
0
]
};
assert_eq!
(
size_of
::
<
Sp1
>
(),
5
);
assert_eq!
(
size_of_val
(
&
sp1
),
5
);
assert_eq!
(
size_of_val
(
&
CSP1
),
5
);
assert_eq!
(
align_of
::
<
Sp1
>
(),
1
);
assert_eq!
(
align_of_val
(
&
sp1
),
1
);
assert_eq!
(
align_of_val
(
&
CSP1
),
1
);
let
sp2
=
Sp2
{
a
:
0
,
b
:
[
0
,
0
,
0
]
};
assert_eq!
(
size_of
::
<
Sp2
>
(),
6
);
assert_eq!
(
size_of_val
(
&
sp2
),
6
);
assert_eq!
(
size_of_val
(
&
CSP2
),
6
);
assert_eq!
(
align_of
::
<
Sp2
>
(),
2
);
assert_eq!
(
align_of_val
(
&
sp2
),
2
);
assert_eq!
(
align_of_val
(
&
CSP2
),
2
);
let
u
=
U
{
b
:
[
0
,
0
,
0
]
};
assert_eq!
(
size_of
::
<
U
>
(),
4
);
...
...
@@ -64,19 +94,35 @@ fn main() {
assert_eq!
(
align_of_val
(
&
u
),
2
);
assert_eq!
(
align_of_val
(
&
CU
),
2
);
let
up
=
Up
{
b
:
[
0
,
0
,
0
]
};
assert_eq!
(
size_of
::
<
Up
>
(),
3
);
assert_eq!
(
size_of_val
(
&
up
),
3
);
assert_eq!
(
size_of_val
(
&
CUP
),
3
);
assert_eq!
(
align_of
::
<
Up
>
(),
1
);
assert_eq!
(
align_of_val
(
&
up
),
1
);
assert_eq!
(
align_of_val
(
&
CUP
),
1
);
let
Up1
=
Up1
{
b
:
[
0
,
0
,
0
]
};
assert_eq!
(
size_of
::
<
Up1
>
(),
3
);
assert_eq!
(
size_of_val
(
&
Up1
),
3
);
assert_eq!
(
size_of_val
(
&
CUP1
),
3
);
assert_eq!
(
align_of
::
<
Up1
>
(),
1
);
assert_eq!
(
align_of_val
(
&
Up1
),
1
);
assert_eq!
(
align_of_val
(
&
CUP1
),
1
);
let
up2
=
Up2
{
b
:
[
0
,
0
,
0
]
};
assert_eq!
(
size_of
::
<
Up2
>
(),
4
);
assert_eq!
(
size_of_val
(
&
up2
),
4
);
assert_eq!
(
size_of_val
(
&
CUP2
),
4
);
assert_eq!
(
align_of
::
<
Up2
>
(),
2
);
assert_eq!
(
align_of_val
(
&
up2
),
2
);
assert_eq!
(
align_of_val
(
&
CUP2
),
2
);
let
up4c
=
Up4c
{
b
:
[
0
,
0
,
0
]
};
assert_eq!
(
size_of
::
<
Up4c
>
(),
4
);
assert_eq!
(
size_of_val
(
&
up4c
),
4
);
assert_eq!
(
size_of_val
(
&
CUP4C
),
4
);
assert_eq!
(
align_of
::
<
Up4c
>
(),
2
);
assert_eq!
(
align_of_val
(
&
up4c
),
2
);
assert_eq!
(
align_of_val
(
&
CUP4C
),
2
);
hybrid
::
check_hybrid
();
}
mod
hybrid
{
use
std
::
mem
::
size_of
;
use
std
::
mem
::
{
size_of
,
align_of
}
;
#[repr(packed)]
struct
S1
{
...
...
@@ -96,9 +142,37 @@ struct S2 {
u
:
U
,
}
#[repr(C,
packed(
2
))]
struct
S1C
{
a
:
u16
,
b
:
u8
,
}
#[repr(C,
packed(
2
))]
union
UC
{
s
:
S1
,
c
:
u16
,
}
#[repr(C,
packed(
2
))]
struct
S2C
{
d
:
u8
,
u
:
UC
,
}
pub
fn
check_hybrid
()
{
assert_eq!
(
align_of
::
<
S1
>
(),
1
);
assert_eq!
(
size_of
::
<
S1
>
(),
3
);
assert_eq!
(
align_of
::
<
U
>
(),
1
);
assert_eq!
(
size_of
::
<
U
>
(),
3
);
assert_eq!
(
align_of
::
<
S2
>
(),
1
);
assert_eq!
(
size_of
::
<
S2
>
(),
4
);
assert_eq!
(
align_of
::
<
S1C
>
(),
2
);
assert_eq!
(
size_of
::
<
S1C
>
(),
4
);
assert_eq!
(
align_of
::
<
UC
>
(),
2
);
assert_eq!
(
size_of
::
<
UC
>
(),
4
);
assert_eq!
(
align_of
::
<
S2C
>
(),
2
);
assert_eq!
(
size_of
::
<
S2C
>
(),
6
);
}
}
src/test/ui/feature-gate-repr_packed.rs
0 → 100644
浏览文件 @
15d1c4d2
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[repr(packed(
1
))]
//~ error: the `#[repr(packed(n))]` attribute is experimental
struct
Foo
(
u64
);
fn
main
()
{}
src/test/ui/feature-gate-repr_packed.stderr
0 → 100644
浏览文件 @
15d1c4d2
error[E0658]: the `#[repr(packed(n))]` attribute is experimental (see issue #33158)
--> $DIR/feature-gate-repr_packed.rs:11:1
|
LL | #[repr(packed(1))] //~ error: the `#[repr(packed(n))]` attribute is experimental
| ^^^^^^^^^^^^^^^^^^
|
= help: add #![feature(repr_packed)] to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.
src/test/ui/print_type_sizes/packed.rs
浏览文件 @
15d1c4d2
...
...
@@ -21,10 +21,34 @@
#![allow(dead_code)]
#![feature(start)]
#![feature(repr_packed)]
#[derive(Default)]
#[repr(packed)]
struct
Packed
{
struct
Packed1
{
a
:
u8
,
b
:
u8
,
g
:
i32
,
c
:
u8
,
h
:
i16
,
d
:
u8
,
}
#[derive(Default)]
#[repr(packed(
2
))]
struct
Packed2
{
a
:
u8
,
b
:
u8
,
g
:
i32
,
c
:
u8
,
h
:
i16
,
d
:
u8
,
}
#[derive(Default)]
#[repr(packed(
2
))]
#[repr(C)]
struct
Packed2C
{
a
:
u8
,
b
:
u8
,
g
:
i32
,
...
...
@@ -45,7 +69,9 @@ struct Padded {
#[start]
fn
start
(
_
:
isize
,
_
:
*
const
*
const
u8
)
->
isize
{
let
_
c
:
Packed
=
Default
::
default
();
let
_
d
:
Padded
=
Default
::
default
();
let
_
c
:
Packed1
=
Default
::
default
();
let
_
d
:
Packed2
=
Default
::
default
();
let
_
e
:
Packed2C
=
Default
::
default
();
let
_
f
:
Padded
=
Default
::
default
();
0
}
src/test/ui/print_type_sizes/packed.stdout
浏览文件 @
15d1c4d2
print-type-size type: `Packed2C`: 12 bytes, alignment: 2 bytes
print-type-size field `.a`: 1 bytes
print-type-size field `.b`: 1 bytes
print-type-size field `.g`: 4 bytes
print-type-size field `.c`: 1 bytes
print-type-size padding: 1 bytes
print-type-size field `.h`: 2 bytes
print-type-size field `.d`: 1 bytes
print-type-size end padding: 1 bytes
print-type-size type: `Padded`: 12 bytes, alignment: 4 bytes
print-type-size field `.g`: 4 bytes
print-type-size field `.h`: 2 bytes
...
...
@@ -6,10 +15,17 @@ print-type-size field `.b`: 1 bytes
print-type-size field `.c`: 1 bytes
print-type-size field `.d`: 1 bytes
print-type-size end padding: 2 bytes
print-type-size type: `Packed`: 10 bytes, alignment: 1 bytes
print-type-size type: `Packed
1
`: 10 bytes, alignment: 1 bytes
print-type-size field `.a`: 1 bytes
print-type-size field `.b`: 1 bytes
print-type-size field `.g`: 4 bytes
print-type-size field `.c`: 1 bytes
print-type-size field `.h`: 2 bytes
print-type-size field `.d`: 1 bytes
print-type-size type: `Packed2`: 10 bytes, alignment: 2 bytes
print-type-size field `.g`: 4 bytes
print-type-size field `.h`: 2 bytes
print-type-size field `.a`: 1 bytes
print-type-size field `.b`: 1 bytes
print-type-size field `.c`: 1 bytes
print-type-size field `.d`: 1 bytes
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录