Skip to content

Commit a10213f

Browse files
committed
Raised alignment limit from 2^15 to 2^31
1 parent 4d4d76c commit a10213f

File tree

5 files changed

+35
-21
lines changed

5 files changed

+35
-21
lines changed

src/librustc/ty/layout.rs

+11-14
Original file line numberDiff line numberDiff line change
@@ -285,11 +285,11 @@ impl Size {
285285
}
286286

287287
/// Alignment of a type in bytes, both ABI-mandated and preferred.
288-
/// Since alignments are always powers of 2, we can pack both in one byte,
289-
/// giving each a nibble (4 bits) for a maximum alignment of 2<sup>15</sup> = 32768.
288+
/// Each field is a power of two.
290289
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
291290
pub struct Align {
292-
raw: u8
291+
abi: u8,
292+
pref: u8,
293293
}
294294

295295
impl Align {
@@ -312,39 +312,36 @@ impl Align {
312312
}
313313
if bytes != 1 {
314314
Err(format!("`{}` is not a power of 2", align))
315-
} else if pow > 0x0f {
316-
Err(format!("`{}` is too large", align))
317315
} else {
318316
Ok(pow)
319317
}
320318
};
321319

322320
Ok(Align {
323-
raw: pack(abi)? | (pack(pref)? << 4)
321+
abi: pack(abi)?,
322+
pref: pack(pref)?,
324323
})
325324
}
326325

327326
pub fn abi(self) -> u64 {
328-
1 << (self.raw & 0xf)
327+
1 << self.abi
329328
}
330329

331330
pub fn pref(self) -> u64 {
332-
1 << (self.raw >> 4)
331+
1 << self.pref
333332
}
334333

335334
pub fn min(self, other: Align) -> Align {
336-
let abi = cmp::min(self.raw & 0x0f, other.raw & 0x0f);
337-
let pref = cmp::min(self.raw & 0xf0, other.raw & 0xf0);
338335
Align {
339-
raw: abi | pref
336+
abi: cmp::min(self.abi, other.abi),
337+
pref: cmp::min(self.pref, other.pref),
340338
}
341339
}
342340

343341
pub fn max(self, other: Align) -> Align {
344-
let abi = cmp::max(self.raw & 0x0f, other.raw & 0x0f);
345-
let pref = cmp::max(self.raw & 0xf0, other.raw & 0xf0);
346342
Align {
347-
raw: abi | pref
343+
abi: cmp::max(self.abi, other.abi),
344+
pref: cmp::max(self.pref, other.pref),
348345
}
349346
}
350347
}

src/librustc/ty/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1398,7 +1398,7 @@ impl_stable_hash_for!(struct ReprFlags {
13981398
#[derive(Copy, Clone, Eq, PartialEq, RustcEncodable, RustcDecodable, Default)]
13991399
pub struct ReprOptions {
14001400
pub int: Option<attr::IntType>,
1401-
pub align: u16,
1401+
pub align: u32,
14021402
pub flags: ReprFlags,
14031403
}
14041404

src/libsyntax/attr.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -974,11 +974,11 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr>
974974
let mut align_error = None;
975975
if let ast::LitKind::Int(align, ast::LitIntType::Unsuffixed) = value.node {
976976
if align.is_power_of_two() {
977-
// rustc::ty::layout::Align restricts align to <= 32768
978-
if align <= 32768 {
979-
acc.push(ReprAlign(align as u16));
977+
// rustc::ty::layout::Align restricts align to <= 2147483648
978+
if align <= 2147483648 {
979+
acc.push(ReprAlign(align as u32));
980980
} else {
981-
align_error = Some("larger than 32768");
981+
align_error = Some("larger than 2147483648");
982982
}
983983
} else {
984984
align_error = Some("not a power of two");
@@ -1027,7 +1027,7 @@ pub enum ReprAttr {
10271027
ReprExtern,
10281028
ReprPacked,
10291029
ReprSimd,
1030-
ReprAlign(u16),
1030+
ReprAlign(u32),
10311031
}
10321032

10331033
#[derive(Eq, Hash, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)]

src/test/compile-fail/repr-align.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ struct A(i32);
1717
#[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute: not a power of two
1818
struct B(i32);
1919

20-
#[repr(align(65536))] //~ ERROR: invalid `repr(align)` attribute: larger than 32768
20+
#[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute: larger than 2147483648
2121
struct C(i32);
2222

2323
fn main() {}

src/test/run-pass/align-struct.rs

+17
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ struct AlignContainsPacked {
6060
b: Packed,
6161
}
6262

63+
// The align limit was originally smaller (2^15).
64+
// Check that it works with big numbers.
65+
#[repr(align(0x10000))]
66+
struct AlignLarge {
67+
stuff: [u8; 0x10000],
68+
}
69+
6370
impl Align16 {
6471
// return aligned type
6572
pub fn new(i: i32) -> Align16 {
@@ -193,4 +200,14 @@ pub fn main() {
193200
assert_eq!(mem::align_of_val(&a.b), 1);
194201
assert_eq!(mem::size_of_val(&a), 16);
195202
assert!(is_aligned_to(&a, 16));
203+
204+
let mut arr = [0; 0x10000];
205+
arr[0] = 132;
206+
let large = AlignLarge {
207+
stuff: arr,
208+
};
209+
assert_eq!(large.stuff[0], 132);
210+
assert_eq!(mem::align_of::<AlignLarge>(), 0x10000);
211+
assert_eq!(mem::align_of_val(&large), 0x10000);
212+
assert!(is_aligned_to(&large, 0x10000));
196213
}

0 commit comments

Comments
 (0)