Permalink
Please
sign in to comment.
Showing
with
132 additions
and 68 deletions.
| @@ -0,0 +1,77 @@ | |||
| // Copyright 2016 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. | |||
|
|
|||
| use std::cmp; | |||
|
|
|||
| /// 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^15 = 32768. | |||
| #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] | |||
| pub struct Align { | |||
| raw: u8 | |||
| } | |||
|
|
|||
| impl Align { | |||
| pub fn from_bits(abi: u64, pref: u64) -> Result<Align, String> { | |||
| Align::from_bytes((abi + 7) / 8, (pref + 7) / 8) | |||
| } | |||
|
|
|||
| pub fn from_bytes(abi: u64, pref: u64) -> Result<Align, String> { | |||
| let pack = |align: u64| { | |||
| // Treat an alignment of 0 bytes like 1-byte alignment. | |||
| if align == 0 { | |||
| return Ok(0); | |||
| } | |||
|
|
|||
| let mut bytes = align; | |||
| let mut pow: u8 = 0; | |||
| while (bytes & 1) == 0 { | |||
| pow += 1; | |||
| bytes >>= 1; | |||
| } | |||
| 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) | |||
| }) | |||
| } | |||
|
|
|||
| pub fn abi(self) -> u64 { | |||
| 1 << (self.raw & 0xf) | |||
| } | |||
|
|
|||
| pub fn pref(self) -> u64 { | |||
| 1 << (self.raw >> 4) | |||
| } | |||
|
|
|||
| 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 | |||
| } | |||
| } | |||
|
|
|||
| 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 | |||
| } | |||
| } | |||
| } | |||
|
|
|||
0 comments on commit
1900786