diff --git a/cranelift/codegen/meta/src/constant_hash.rs b/cranelift/codegen/meta/src/constant_hash.rs new file mode 100644 index 0000000000..bb1d4c71f0 --- /dev/null +++ b/cranelift/codegen/meta/src/constant_hash.rs @@ -0,0 +1,64 @@ +//! Build support for precomputed constant hash tables. +//! +//! This module can generate constant hash tables using open addressing and quadratic probing. +//! +//! The hash tables are arrays that are guaranteed to: +//! +//! - Have a power-of-two size. +//! - Contain at least one empty slot. + +use std::iter; + +/// Compute an open addressed, quadratically probed hash table containing +/// `items`. The returned table is a list containing the elements of the +/// iterable `items` and `None` in unused slots. +#[allow(clippy::float_arithmetic)] +pub fn generate_table<'cont, T, I: iter::Iterator, H: Fn(&T) -> usize>( + items: I, + num_items: usize, + hash_function: H, +) -> Vec> { + let size = (1.20 * num_items as f64) as usize; + + // Probing code's stop condition relies on the table having one vacant entry at least. + let size = if size.is_power_of_two() { + size * 2 + } else { + size.next_power_of_two() + }; + + let mut table = vec![None; size]; + + for i in items { + let mut h = hash_function(&i) % size; + let mut s = 0; + while table[h].is_some() { + s += 1; + h = (h + s) % size; + } + table[h] = Some(i); + } + + table +} + +#[cfg(test)] +mod tests { + use super::generate_table; + use cranelift_codegen_shared::constant_hash::simple_hash; + + #[test] + fn test_generate_table() { + let v = vec!["Hello".to_string(), "world".to_string()]; + let table = generate_table(v.iter(), v.len(), |s| simple_hash(&s)); + assert_eq!( + table, + vec![ + None, + Some(&"Hello".to_string()), + Some(&"world".to_string()), + None + ] + ); + } +} diff --git a/cranelift/codegen/meta/src/gen_inst.rs b/cranelift/codegen/meta/src/gen_inst.rs index 4be3671447..f3c5f642a1 100644 --- a/cranelift/codegen/meta/src/gen_inst.rs +++ b/cranelift/codegen/meta/src/gen_inst.rs @@ -553,9 +553,10 @@ fn gen_opcodes(all_inst: &AllInstructions, fmt: &mut Formatter) { fmt.empty_line(); // Generate an opcode hash table for looking up opcodes by name. - let hash_table = constant_hash::generate_table(all_inst.iter(), all_inst.len(), |inst| { - constant_hash::simple_hash(&inst.name) - }); + let hash_table = + crate::constant_hash::generate_table(all_inst.iter(), all_inst.len(), |inst| { + constant_hash::simple_hash(&inst.name) + }); fmtln!( fmt, "const OPCODE_HASH_TABLE: [Option; {}] = [", diff --git a/cranelift/codegen/meta/src/gen_settings.rs b/cranelift/codegen/meta/src/gen_settings.rs index d7116cac9c..a76853b85c 100644 --- a/cranelift/codegen/meta/src/gen_settings.rs +++ b/cranelift/codegen/meta/src/gen_settings.rs @@ -1,7 +1,8 @@ //! Generate the ISA-specific settings. use std::collections::HashMap; -use cranelift_codegen_shared::constant_hash::{generate_table, simple_hash}; +use crate::constant_hash::generate_table; +use cranelift_codegen_shared::constant_hash::simple_hash; use crate::cdsl::camel_case; use crate::cdsl::settings::{ diff --git a/cranelift/codegen/meta/src/lib.rs b/cranelift/codegen/meta/src/lib.rs index 44f0c4fd85..30e5acc48c 100644 --- a/cranelift/codegen/meta/src/lib.rs +++ b/cranelift/codegen/meta/src/lib.rs @@ -11,6 +11,7 @@ mod gen_inst; mod gen_settings; mod gen_types; +mod constant_hash; mod shared; mod unique_table; diff --git a/cranelift/codegen/shared/src/constant_hash.rs b/cranelift/codegen/shared/src/constant_hash.rs index ceac8e2722..2929319656 100644 --- a/cranelift/codegen/shared/src/constant_hash.rs +++ b/cranelift/codegen/shared/src/constant_hash.rs @@ -1,16 +1,4 @@ -//! Build support for precomputed constant hash tables. -//! -//! This module can generate constant hash tables using open addressing and quadratic probing. -//! -//! The hash tables are arrays that are guaranteed to: -//! -//! - Have a power-of-two size. -//! - Contain at least one empty slot. -//! -//! This module provides build meta support for lookups in these tables, as well as the shared hash -//! function used for probing. - -use std::iter; +//! This module provides a primitive hash function. /// A primitive hash function for matching opcodes. pub fn simple_hash(s: &str) -> usize { @@ -21,61 +9,13 @@ pub fn simple_hash(s: &str) -> usize { h as usize } -/// Compute an open addressed, quadratically probed hash table containing -/// `items`. The returned table is a list containing the elements of the -/// iterable `items` and `None` in unused slots. -#[allow(clippy::float_arithmetic)] -pub fn generate_table<'cont, T, I: iter::Iterator, H: Fn(&T) -> usize>( - items: I, - num_items: usize, - hash_function: H, -) -> Vec> { - let size = (1.20 * num_items as f64) as usize; - - // Probing code's stop condition relies on the table having one vacant entry at least. - let size = if size.is_power_of_two() { - size * 2 - } else { - size.next_power_of_two() - }; - - let mut table = vec![None; size]; - - for i in items { - let mut h = hash_function(&i) % size; - let mut s = 0; - while table[h].is_some() { - s += 1; - h = (h + s) % size; - } - table[h] = Some(i); - } - - table -} - #[cfg(test)] mod tests { - use super::{generate_table, simple_hash}; + use super::simple_hash; #[test] fn basic() { assert_eq!(simple_hash("Hello"), 0x2fa70c01); assert_eq!(simple_hash("world"), 0x5b0c31d5); } - - #[test] - fn test_generate_table() { - let v = vec!["Hello".to_string(), "world".to_string()]; - let table = generate_table(v.iter(), v.len(), |s| simple_hash(&s)); - assert_eq!( - table, - vec![ - None, - Some(&"Hello".to_string()), - Some(&"world".to_string()), - None - ] - ); - } }