-
Notifications
You must be signed in to change notification settings - Fork 13.3k
refactor svh #26629
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor svh #26629
Changes from all commits
ba7b47e
d7eb7a6
aff24e1
75219e1
dd41732
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -51,19 +51,26 @@ use std::hash::{Hash, SipHasher, Hasher}; | |
use syntax::ast; | ||
use syntax::visit; | ||
|
||
#[derive(Clone, PartialEq, Debug)] | ||
#[derive(Clone, PartialEq, Eq, Debug)] | ||
pub struct Svh { | ||
hash: String, | ||
raw: u64, | ||
} | ||
|
||
impl Svh { | ||
pub fn new(hash: &str) -> Svh { | ||
assert!(hash.len() == 16); | ||
Svh { hash: hash.to_string() } | ||
} | ||
// Ideally we'd just reverse the nibbles on LE machines during to_string, unfortunately | ||
// this would break the abi so I guess we're just doing this now. | ||
|
||
let s = if cfg!(target_endian = "big") { | ||
hash.to_string() | ||
} else { | ||
hash.chars().rev().collect() | ||
}; | ||
|
||
pub fn as_str<'a>(&'a self) -> &'a str { | ||
&self.hash | ||
Svh { | ||
raw: u64::from_str_radix(&s, 16).unwrap(), | ||
} | ||
} | ||
|
||
pub fn calculate(metadata: &Vec<String>, krate: &ast::Crate) -> Svh { | ||
|
@@ -100,25 +107,23 @@ impl Svh { | |
attr.node.value.hash(&mut state); | ||
} | ||
|
||
let hash = state.finish(); | ||
return Svh { | ||
hash: (0..64).step_by(4).map(|i| hex(hash >> i)).collect() | ||
}; | ||
|
||
fn hex(b: u64) -> char { | ||
let b = (b & 0xf) as u8; | ||
let b = match b { | ||
0 ... 9 => '0' as u8 + b, | ||
_ => 'a' as u8 + b - 10, | ||
}; | ||
b as char | ||
Svh { | ||
raw: state.finish(), | ||
} | ||
} | ||
} | ||
|
||
impl Hash for Svh { | ||
fn hash<H>(&self, state: &mut H) where H: Hasher { | ||
// We have to hash a &str since that's what the old implementations did, and otherwise we | ||
// break the abi | ||
&self.to_string()[..].hash(state); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why go through a string to implement a hash? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's actually possible this is not necessary any more, although I believe that the u64 and the String will hash differently. I believe this was a first guess at what was happening before when I hit the endianness bug above (My stage1 would refuse to compile anything that depended on libc or core because it believed they were out of date) |
||
} | ||
} | ||
|
||
impl fmt::Display for Svh { | ||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
f.pad(self.as_str()) | ||
f.pad(&self.to_string()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe this is an infinitely recursive function now? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it is, I have a patch on a local branch but it needs a rebase |
||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems somewhat odd, and I don't understand how endianness helps here, so could you clarify what this is doing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the to_string() impl, it walks the low nibble to the high nibble constructing the string, the net result being that without this,
Svh::new("deadbeefdeadbeef").to_string()
returnsfeebdaedfeebdaed
Unfortunately, because it's flipped nibble wise not byte wise I can't just flip the bytes in the resulting u64, but on a big endian architecture this reversing shouldn't be necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I understand that this is reversing the string, but what I don't understand is why it matters to have the same ordering across different architectures?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh right. It needs to maintain compatibility with what's emitted today to avoid breaking the abi (without flipping it on LE arches it will refuse to build a stage1, because when it goes to consume the libc and core crates it'll believe they're out of date). I believe it's safe to nop out on BE architectures since they're already in the right order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't currently maintain ABI compatibility today, so that's not too much of a worry, and I feel like if we cross endianness platforms that this is likely to be the least of our problems (I'm also not 100% sure that this is a problem). Altogether I think it's fine to omit this.