1 // Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
12 #![feature(box_syntax)]
13 #![feature(repr_packed)]
19 #[derive(Clone, Copy, Debug)]
22 // Lowering has no effect
26 // Multiple attributes take the max
30 struct AlignMany(i32);
32 // Raising alignment may not alter size.
48 // Nested alignment - use `#[repr(C)]` to suppress field reordering for sizeof test
61 struct AlignContainsPacked
{
73 struct AlignContainsPacked4C
{
78 // The align limit was originally smaller (2^15).
79 // Check that it works with big numbers.
80 #[repr(align(0x10000))]
85 union UnionContainsAlign
{
91 // return aligned type
92 pub fn new(i
: i32) -> Align16
{
96 pub fn consume(a
: Align16
) -> i32 {
101 const CONST_ALIGN16
: Align16
= Align16(7);
102 static STATIC_ALIGN16
: Align16
= Align16(8);
104 // Check the actual address is aligned
105 fn is_aligned_to
<T
>(p
: &T
, align
: usize) -> bool
{
106 let addr
= p
as *const T
as usize;
107 (addr
& (align
- 1)) == 0
111 // check alignment and size by type and value
112 assert_eq
!(mem
::align_of
::<Align16
>(), 16);
113 assert_eq
!(mem
::size_of
::<Align16
>(), 16);
117 assert_eq
!(mem
::align_of_val(&a
), 16);
118 assert_eq
!(mem
::size_of_val(&a
), 16);
120 assert
!(is_aligned_to(&a
, 16));
122 // lowering should have no effect
123 assert_eq
!(mem
::align_of
::<Align1
>(), 4);
124 assert_eq
!(mem
::size_of
::<Align1
>(), 4);
127 assert_eq
!(mem
::align_of_val(&a
), 4);
128 assert_eq
!(mem
::size_of_val(&a
), 4);
129 assert
!(is_aligned_to(&a
, 4));
131 // when multiple attributes are specified the max should be used
132 assert_eq
!(mem
::align_of
::<AlignMany
>(), 16);
133 assert_eq
!(mem
::size_of
::<AlignMany
>(), 16);
134 let a
= AlignMany(7);
136 assert_eq
!(mem
::align_of_val(&a
), 16);
137 assert_eq
!(mem
::size_of_val(&a
), 16);
138 assert
!(is_aligned_to(&a
, 16));
140 // raising alignment should not reduce size
141 assert_eq
!(mem
::align_of
::<Align8Many
>(), 8);
142 assert_eq
!(mem
::size_of
::<Align8Many
>(), 16);
143 let a
= Align8Many { a: 1, b: 2, c: 3, d: 4 }
;
145 assert_eq
!(mem
::align_of_val(&a
), 8);
146 assert_eq
!(mem
::size_of_val(&a
), 16);
147 assert
!(is_aligned_to(&a
, 8));
150 let a
= Align16
::new(1);
151 assert_eq
!(mem
::align_of_val(&a
), 16);
152 assert_eq
!(mem
::size_of_val(&a
), 16);
154 assert
!(is_aligned_to(&a
, 16));
155 assert_eq
!(Align16
::consume(a
), 1);
157 // check const alignment, size and value
158 assert_eq
!(mem
::align_of_val(&CONST_ALIGN16
), 16);
159 assert_eq
!(mem
::size_of_val(&CONST_ALIGN16
), 16);
160 assert_eq
!(CONST_ALIGN16
.0
, 7);
161 assert
!(is_aligned_to(&CONST_ALIGN16
, 16));
163 // check global static alignment, size and value
164 assert_eq
!(mem
::align_of_val(&STATIC_ALIGN16
), 16);
165 assert_eq
!(mem
::size_of_val(&STATIC_ALIGN16
), 16);
166 assert_eq
!(STATIC_ALIGN16
.0
, 8);
167 assert
!(is_aligned_to(&STATIC_ALIGN16
, 16));
169 // Note that the size of Nested may change if struct field re-ordering is enabled
170 assert_eq
!(mem
::align_of
::<Nested
>(), 16);
171 assert_eq
!(mem
::size_of
::<Nested
>(), 48);
172 let a
= Nested{ a: 1, b: 2, c: Align16(3), d: 4}
;
173 assert_eq
!(mem
::align_of_val(&a
), 16);
174 assert_eq
!(mem
::align_of_val(&a
.b
), 4);
175 assert_eq
!(mem
::align_of_val(&a
.c
), 16);
176 assert_eq
!(mem
::size_of_val(&a
), 48);
177 assert
!(is_aligned_to(&a
, 16));
178 // check the correct fields are indexed
181 assert_eq
!(a
.c
.0, 3);
184 // enum should be aligned to max alignment
185 assert_eq
!(mem
::align_of
::<Enum
>(), 16);
186 assert_eq
!(mem
::align_of_val(&Enum
::B(Align16(0))), 16);
187 let e
= Enum
::B(Align16(15));
191 assert_eq
!(mem
::align_of_val(a
), 16);
192 assert_eq
!(mem
::size_of_val(a
), 16);
196 assert
!(is_aligned_to(&e
, 16));
198 // check union alignment
199 assert_eq
!(mem
::align_of
::<UnionContainsAlign
>(), 16);
200 assert_eq
!(mem
::size_of
::<UnionContainsAlign
>(), 16);
201 let u
= UnionContainsAlign { a: Align16(10) }
;
203 assert_eq
!(mem
::align_of_val(&u
.a
), 16);
204 assert_eq
!(mem
::size_of_val(&u
.a
), 16);
205 assert_eq
!(u
.a
.0, 10);
206 let UnionContainsAlign { a }
= u
;
210 // arrays of aligned elements should also be aligned
211 assert_eq
!(mem
::align_of
::<[Align16
;2]>(), 16);
212 assert_eq
!(mem
::size_of
::<[Align16
;2]>(), 32);
214 let a
= [Align16(0), Align16(1)];
215 assert_eq
!(mem
::align_of_val(&a
[0]), 16);
216 assert_eq
!(mem
::align_of_val(&a
[1]), 16);
217 assert
!(is_aligned_to(&a
, 16));
219 // check heap value is aligned
220 assert_eq
!(mem
::align_of_val(Box
::new(Align16(0)).as_ref()), 16);
222 // check heap array is aligned
223 let a
= vec
!(Align16(0), Align16(1));
224 assert_eq
!(mem
::align_of_val(&a
[0]), 16);
225 assert_eq
!(mem
::align_of_val(&a
[1]), 16);
227 assert_eq
!(mem
::align_of
::<AlignContainsPacked
>(), 16);
228 assert_eq
!(mem
::size_of
::<AlignContainsPacked
>(), 16);
229 let a
= AlignContainsPacked { a: Packed(1), b: Packed(2) }
;
230 assert_eq
!(mem
::align_of_val(&a
), 16);
231 assert_eq
!(mem
::align_of_val(&a
.a
), 1);
232 assert_eq
!(mem
::align_of_val(&a
.b
), 1);
233 assert_eq
!(mem
::size_of_val(&a
), 16);
234 assert
!(is_aligned_to(&a
, 16));
236 assert_eq
!(mem
::align_of
::<AlignContainsPacked4C
>(), 16);
237 assert_eq
!(mem
::size_of
::<AlignContainsPacked4C
>(), 32);
238 let a
= AlignContainsPacked4C { a: Packed4C{ a: 1, b: 2 }
, b
: 3 };
239 assert_eq
!(mem
::align_of_val(&a
), 16);
240 assert_eq
!(mem
::align_of_val(&a
.a
), 4);
241 assert_eq
!(mem
::align_of_val(&a
.b
), mem
::align_of
::<u64>());
242 assert_eq
!(mem
::size_of_val(&a
), 32);
243 assert
!(is_aligned_to(&a
, 16));
245 let mut large
= box AlignLarge
{
248 large
.stuff
[0] = 132;
249 *large
.stuff
.last_mut().unwrap() = 102;
250 assert_eq
!(large
.stuff
[0], 132);
251 assert_eq
!(large
.stuff
.last(), Some(&102));
252 assert_eq
!(mem
::align_of
::<AlignLarge
>(), 0x10000);
253 assert_eq
!(mem
::align_of_val(&*large
), 0x10000);
254 assert
!(is_aligned_to(&*large
, 0x10000));