Skip to content

Commit

Permalink
Raised alignment limit from 2^15 to 2^31
Browse files Browse the repository at this point in the history
  • Loading branch information
PlasmaPower committed Jul 8, 2017
1 parent 4d4d76c commit a10213f
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 21 deletions.
25 changes: 11 additions & 14 deletions src/librustc/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,11 +285,11 @@ impl Size {
}

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

impl Align {
Expand All @@ -312,39 +312,36 @@ impl Align {
}
if bytes != 1 {
Err(format!("`{}` is not a power of 2", align))
} else if pow > 0x0f {
Err(format!("`{}` is too large", align))
} else {
Ok(pow)
}
};

Ok(Align {
raw: pack(abi)? | (pack(pref)? << 4)
abi: pack(abi)?,
pref: pack(pref)?,
})
}

pub fn abi(self) -> u64 {
1 << (self.raw & 0xf)
1 << self.abi
}

pub fn pref(self) -> u64 {
1 << (self.raw >> 4)
1 << self.pref
}

pub fn min(self, other: Align) -> Align {
let abi = cmp::min(self.raw & 0x0f, other.raw & 0x0f);
let pref = cmp::min(self.raw & 0xf0, other.raw & 0xf0);
Align {
raw: abi | pref
abi: cmp::min(self.abi, other.abi),
pref: cmp::min(self.pref, other.pref),
}
}

pub fn max(self, other: Align) -> Align {
let abi = cmp::max(self.raw & 0x0f, other.raw & 0x0f);
let pref = cmp::max(self.raw & 0xf0, other.raw & 0xf0);
Align {
raw: abi | pref
abi: cmp::max(self.abi, other.abi),
pref: cmp::max(self.pref, other.pref),
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1398,7 +1398,7 @@ impl_stable_hash_for!(struct ReprFlags {
#[derive(Copy, Clone, Eq, PartialEq, RustcEncodable, RustcDecodable, Default)]
pub struct ReprOptions {
pub int: Option<attr::IntType>,
pub align: u16,
pub align: u32,
pub flags: ReprFlags,
}

Expand Down
10 changes: 5 additions & 5 deletions src/libsyntax/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -974,11 +974,11 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec<ReprAttr>
let mut align_error = None;
if let ast::LitKind::Int(align, ast::LitIntType::Unsuffixed) = value.node {
if align.is_power_of_two() {
// rustc::ty::layout::Align restricts align to <= 32768
if align <= 32768 {
acc.push(ReprAlign(align as u16));
// rustc::ty::layout::Align restricts align to <= 2147483648
if align <= 2147483648 {
acc.push(ReprAlign(align as u32));
} else {
align_error = Some("larger than 32768");
align_error = Some("larger than 2147483648");
}
} else {
align_error = Some("not a power of two");
Expand Down Expand Up @@ -1027,7 +1027,7 @@ pub enum ReprAttr {
ReprExtern,
ReprPacked,
ReprSimd,
ReprAlign(u16),
ReprAlign(u32),
}

#[derive(Eq, Hash, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/repr-align.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ struct A(i32);
#[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute: not a power of two
struct B(i32);

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

fn main() {}
17 changes: 17 additions & 0 deletions src/test/run-pass/align-struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ struct AlignContainsPacked {
b: Packed,
}

// The align limit was originally smaller (2^15).
// Check that it works with big numbers.
#[repr(align(0x10000))]
struct AlignLarge {
stuff: [u8; 0x10000],
}

impl Align16 {
// return aligned type
pub fn new(i: i32) -> Align16 {
Expand Down Expand Up @@ -193,4 +200,14 @@ pub fn main() {
assert_eq!(mem::align_of_val(&a.b), 1);
assert_eq!(mem::size_of_val(&a), 16);
assert!(is_aligned_to(&a, 16));

let mut arr = [0; 0x10000];
arr[0] = 132;
let large = AlignLarge {
stuff: arr,
};
assert_eq!(large.stuff[0], 132);
assert_eq!(mem::align_of::<AlignLarge>(), 0x10000);
assert_eq!(mem::align_of_val(&large), 0x10000);
assert!(is_aligned_to(&large, 0x10000));
}

0 comments on commit a10213f

Please sign in to comment.