1 // run-pass
2 #![allow(dead_code)]
3 #![feature(box_syntax)]
4
5 use std::mem;
6
7 // Raising alignment
8 #[repr(align(16))]
9 #[derive(Clone, Copy, Debug)]
10 struct Align16(i32);
11
12 // Lowering has no effect
13 #[repr(align(1))]
14 struct Align1(i32);
15
16 // Multiple attributes take the max
17 #[repr(align(4))]
18 #[repr(align(16))]
19 #[repr(align(8))]
20 struct AlignMany(i32);
21
22 // Raising alignment may not alter size.
23 #[repr(align(8))]
24 #[allow(dead_code)]
25 struct Align8Many {
26 a: i32,
27 b: i32,
28 c: i32,
29 d: u8,
30 }
31
32 enum Enum {
33 #[allow(dead_code)]
34 A(i32),
35 B(Align16)
36 }
37
38 // Nested alignment - use `#[repr(C)]` to suppress field reordering for sizeof test
39 #[repr(C)]
40 struct Nested {
41 a: i32,
42 b: i32,
43 c: Align16,
44 d: i8,
45 }
46
47 #[repr(packed)]
48 struct Packed(i32);
49
50 #[repr(align(16))]
51 struct AlignContainsPacked {
52 a: Packed,
53 b: Packed,
54 }
55
56 #[repr(C, packed(4))]
57 struct Packed4C {
58 a: u32,
59 b: u64,
60 }
61
62 #[repr(align(16))]
63 struct AlignContainsPacked4C {
64 a: Packed4C,
65 b: u64,
66 }
67
68 // The align limit was originally smaller (2^15).
69 // Check that it works with big numbers.
70 #[repr(align(0x10000))]
71 struct AlignLarge {
72 stuff: [u8; 0x10000],
73 }
74
75 union UnionContainsAlign {
76 a: Align16,
77 b: f32
78 }
79
80 impl Align16 {
81 // return aligned type
new(i: i32) -> Align1682 pub fn new(i: i32) -> Align16 {
83 Align16(i)
84 }
85 // pass aligned type
consume(a: Align16) -> i3286 pub fn consume(a: Align16) -> i32 {
87 a.0
88 }
89 }
90
91 const CONST_ALIGN16: Align16 = Align16(7);
92 static STATIC_ALIGN16: Align16 = Align16(8);
93
94 // Check the actual address is aligned
is_aligned_to<T>(p: &T, align: usize) -> bool95 fn is_aligned_to<T>(p: &T, align: usize) -> bool {
96 let addr = p as *const T as usize;
97 (addr & (align - 1)) == 0
98 }
99
main()100 pub fn main() {
101 // check alignment and size by type and value
102 assert_eq!(mem::align_of::<Align16>(), 16);
103 assert_eq!(mem::size_of::<Align16>(), 16);
104
105 let a = Align16(7);
106 assert_eq!(a.0, 7);
107 assert_eq!(mem::align_of_val(&a), 16);
108 assert_eq!(mem::size_of_val(&a), 16);
109
110 assert!(is_aligned_to(&a, 16));
111
112 // lowering should have no effect
113 assert_eq!(mem::align_of::<Align1>(), 4);
114 assert_eq!(mem::size_of::<Align1>(), 4);
115 let a = Align1(7);
116 assert_eq!(a.0, 7);
117 assert_eq!(mem::align_of_val(&a), 4);
118 assert_eq!(mem::size_of_val(&a), 4);
119 assert!(is_aligned_to(&a, 4));
120
121 // when multiple attributes are specified the max should be used
122 assert_eq!(mem::align_of::<AlignMany>(), 16);
123 assert_eq!(mem::size_of::<AlignMany>(), 16);
124 let a = AlignMany(7);
125 assert_eq!(a.0, 7);
126 assert_eq!(mem::align_of_val(&a), 16);
127 assert_eq!(mem::size_of_val(&a), 16);
128 assert!(is_aligned_to(&a, 16));
129
130 // raising alignment should not reduce size
131 assert_eq!(mem::align_of::<Align8Many>(), 8);
132 assert_eq!(mem::size_of::<Align8Many>(), 16);
133 let a = Align8Many { a: 1, b: 2, c: 3, d: 4 };
134 assert_eq!(a.a, 1);
135 assert_eq!(mem::align_of_val(&a), 8);
136 assert_eq!(mem::size_of_val(&a), 16);
137 assert!(is_aligned_to(&a, 8));
138
139 // return type
140 let a = Align16::new(1);
141 assert_eq!(mem::align_of_val(&a), 16);
142 assert_eq!(mem::size_of_val(&a), 16);
143 assert_eq!(a.0, 1);
144 assert!(is_aligned_to(&a, 16));
145 assert_eq!(Align16::consume(a), 1);
146
147 // check const alignment, size and value
148 assert_eq!(mem::align_of_val(&CONST_ALIGN16), 16);
149 assert_eq!(mem::size_of_val(&CONST_ALIGN16), 16);
150 assert_eq!(CONST_ALIGN16.0, 7);
151 assert!(is_aligned_to(&CONST_ALIGN16, 16));
152
153 // check global static alignment, size and value
154 assert_eq!(mem::align_of_val(&STATIC_ALIGN16), 16);
155 assert_eq!(mem::size_of_val(&STATIC_ALIGN16), 16);
156 assert_eq!(STATIC_ALIGN16.0, 8);
157 assert!(is_aligned_to(&STATIC_ALIGN16, 16));
158
159 // Note that the size of Nested may change if struct field re-ordering is enabled
160 assert_eq!(mem::align_of::<Nested>(), 16);
161 assert_eq!(mem::size_of::<Nested>(), 48);
162 let a = Nested{ a: 1, b: 2, c: Align16(3), d: 4};
163 assert_eq!(mem::align_of_val(&a), 16);
164 assert_eq!(mem::align_of_val(&a.b), 4);
165 assert_eq!(mem::align_of_val(&a.c), 16);
166 assert_eq!(mem::size_of_val(&a), 48);
167 assert!(is_aligned_to(&a, 16));
168 // check the correct fields are indexed
169 assert_eq!(a.a, 1);
170 assert_eq!(a.b, 2);
171 assert_eq!(a.c.0, 3);
172 assert_eq!(a.d, 4);
173
174 // enum should be aligned to max alignment
175 assert_eq!(mem::align_of::<Enum>(), 16);
176 assert_eq!(mem::align_of_val(&Enum::B(Align16(0))), 16);
177 let e = Enum::B(Align16(15));
178 match e {
179 Enum::B(ref a) => {
180 assert_eq!(a.0, 15);
181 assert_eq!(mem::align_of_val(a), 16);
182 assert_eq!(mem::size_of_val(a), 16);
183 },
184 _ => ()
185 }
186 assert!(is_aligned_to(&e, 16));
187
188 // check union alignment
189 assert_eq!(mem::align_of::<UnionContainsAlign>(), 16);
190 assert_eq!(mem::size_of::<UnionContainsAlign>(), 16);
191 let u = UnionContainsAlign { a: Align16(10) };
192 unsafe {
193 assert_eq!(mem::align_of_val(&u.a), 16);
194 assert_eq!(mem::size_of_val(&u.a), 16);
195 assert_eq!(u.a.0, 10);
196 let UnionContainsAlign { a } = u;
197 assert_eq!(a.0, 10);
198 }
199
200 // arrays of aligned elements should also be aligned
201 assert_eq!(mem::align_of::<[Align16;2]>(), 16);
202 assert_eq!(mem::size_of::<[Align16;2]>(), 32);
203
204 let a = [Align16(0), Align16(1)];
205 assert_eq!(mem::align_of_val(&a[0]), 16);
206 assert_eq!(mem::align_of_val(&a[1]), 16);
207 assert!(is_aligned_to(&a, 16));
208
209 // check heap value is aligned
210 assert_eq!(mem::align_of_val(Box::new(Align16(0)).as_ref()), 16);
211
212 // check heap array is aligned
213 let a = vec!(Align16(0), Align16(1));
214 assert_eq!(mem::align_of_val(&a[0]), 16);
215 assert_eq!(mem::align_of_val(&a[1]), 16);
216
217 assert_eq!(mem::align_of::<AlignContainsPacked>(), 16);
218 assert_eq!(mem::size_of::<AlignContainsPacked>(), 16);
219 let a = AlignContainsPacked { a: Packed(1), b: Packed(2) };
220 assert_eq!(mem::align_of_val(&a), 16);
221 assert_eq!(mem::align_of_val(&a.a), 1);
222 assert_eq!(mem::align_of_val(&a.b), 1);
223 assert_eq!(mem::size_of_val(&a), 16);
224 assert!(is_aligned_to(&a, 16));
225
226 assert_eq!(mem::align_of::<AlignContainsPacked4C>(), 16);
227 assert_eq!(mem::size_of::<AlignContainsPacked4C>(), 32);
228 let a = AlignContainsPacked4C { a: Packed4C{ a: 1, b: 2 }, b: 3 };
229 assert_eq!(mem::align_of_val(&a), 16);
230 assert_eq!(mem::align_of_val(&a.a), 4);
231 assert_eq!(mem::align_of_val(&a.b), mem::align_of::<u64>());
232 assert_eq!(mem::size_of_val(&a), 32);
233 assert!(is_aligned_to(&a, 16));
234
235 let mut large = box AlignLarge {
236 stuff: [0; 0x10000],
237 };
238 large.stuff[0] = 132;
239 *large.stuff.last_mut().unwrap() = 102;
240 assert_eq!(large.stuff[0], 132);
241 assert_eq!(large.stuff.last(), Some(&102));
242 assert_eq!(mem::align_of::<AlignLarge>(), 0x10000);
243 assert_eq!(mem::align_of_val(&*large), 0x10000);
244 assert!(is_aligned_to(&*large, 0x10000));
245 }
246