1 //! Generate the ISA-specific settings. 2 3 use crate::cdsl::camel_case; 4 use crate::cdsl::settings::{ 5 BoolSetting, Predicate, Preset, Setting, SettingGroup, SpecificSetting, 6 }; 7 use crate::constant_hash::generate_table; 8 use crate::unique_table::UniqueSeqTable; 9 use cranelift_codegen_shared::constant_hash::simple_hash; 10 use cranelift_srcgen::{Formatter, Language, Match, error, fmtln}; 11 use std::collections::HashMap; 12 13 pub(crate) enum ParentGroup { 14 None, 15 Shared, 16 } 17 18 /// Emits the constructor of the Flags structure. 19 fn gen_constructor(group: &SettingGroup, parent: ParentGroup, fmt: &mut Formatter) { 20 let args = match parent { 21 ParentGroup::None => "builder: Builder", 22 ParentGroup::Shared => "shared: &settings::Flags, builder: &Builder", 23 }; 24 fmt.add_block("impl Flags", |fmt| { 25 fmt.doc_comment(format!("Create flags {} settings group.", group.name)); 26 fmtln!( 27 fmt, 28 "#[allow(unused_variables, reason = \"generated code\")]" 29 ); 30 fmt.add_block(&format!("pub fn new({args}) -> Self"), |fmt| { 31 fmtln!(fmt, "let bvec = builder.state_for(\"{}\");", group.name); 32 fmtln!( 33 fmt, 34 "let mut {} = Self {{ bytes: [0; {}] }};", 35 group.name, 36 group.byte_size() 37 ); 38 fmtln!( 39 fmt, 40 "debug_assert_eq!(bvec.len(), {});", 41 group.settings_size 42 ); 43 fmtln!( 44 fmt, 45 "{}.bytes[0..{}].copy_from_slice(&bvec);", 46 group.name, 47 group.settings_size 48 ); 49 50 // Now compute the predicates. 51 for p in &group.predicates { 52 fmt.comment(format!("Precompute #{}.", p.number)); 53 fmt.add_block(&format!("if {}", p.render(group)), |fmt| { 54 fmtln!( 55 fmt, 56 "{}.bytes[{}] |= 1 << {};", 57 group.name, 58 group.bool_start_byte_offset + p.number / 8, 59 p.number % 8 60 ); 61 }); 62 } 63 64 fmtln!(fmt, "{}", group.name); 65 }); 66 }); 67 } 68 69 /// Generates the `iter` function. 70 fn gen_iterator(group: &SettingGroup, fmt: &mut Formatter) { 71 fmt.add_block("impl Flags",|fmt| { 72 fmt.doc_comment("Iterates the setting values."); 73 fmt.add_block("pub fn iter(&self) -> impl Iterator<Item = Value> + use<>",|fmt| { 74 fmtln!(fmt, "let mut bytes = [0; {}];", group.settings_size); 75 fmtln!(fmt, "bytes.copy_from_slice(&self.bytes[0..{}]);", group.settings_size); 76 fmt.add_block("DESCRIPTORS.iter().filter_map(move |d|", |fmt| { 77 fmt.add_block("let values = match &d.detail", |fmt| { 78 fmtln!(fmt, "detail::Detail::Preset => return None,"); 79 fmtln!(fmt, "detail::Detail::Enum {{ last, enumerators }} => Some(TEMPLATE.enums(*last, *enumerators)),"); 80 fmtln!(fmt, "_ => None"); 81 }); 82 fmtln!(fmt, ";"); 83 fmtln!(fmt, "Some(Value {{ name: d.name, detail: d.detail, values, value: bytes[d.offset as usize] }})"); 84 }); 85 fmtln!(fmt, ")"); 86 }); 87 }); 88 } 89 90 /// Generates a `all()` function with all options for this enum 91 fn gen_enum_all(name: &str, values: &[&'static str], fmt: &mut Formatter) { 92 fmtln!( 93 fmt, 94 "/// Returns a slice with all possible [{}] values.", 95 name 96 ); 97 fmt.add_block(&format!("pub fn all() -> &'static [{name}]"), |fmt| { 98 fmtln!(fmt, "&["); 99 fmt.indent(|fmt| { 100 for v in values.iter() { 101 fmtln!(fmt, "Self::{},", camel_case(v)); 102 } 103 }); 104 fmtln!(fmt, "]"); 105 }); 106 } 107 108 /// Emit Display and FromStr implementations for enum settings. 109 fn gen_to_and_from_str(name: &str, values: &[&'static str], fmt: &mut Formatter) { 110 fmt.add_block(&format!("impl fmt::Display for {name}"), |fmt| { 111 fmt.add_block( 112 "fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result", 113 |fmt| { 114 fmt.add_block("f.write_str(match *self", |fmt| { 115 for v in values.iter() { 116 fmtln!(fmt, "Self::{} => \"{}\",", camel_case(v), v); 117 } 118 }); 119 fmtln!(fmt, ")"); 120 }, 121 ); 122 }); 123 124 fmt.add_block(&format!("impl core::str::FromStr for {name}"), |fmt| { 125 fmtln!(fmt, "type Err = ();"); 126 fmt.add_block("fn from_str(s: &str) -> Result<Self, Self::Err>", |fmt| { 127 fmt.add_block("match s", |fmt| { 128 for v in values.iter() { 129 fmtln!(fmt, "\"{}\" => Ok(Self::{}),", v, camel_case(v)); 130 } 131 fmtln!(fmt, "_ => Err(()),"); 132 }); 133 }); 134 }); 135 } 136 137 /// Emit real enum for the Enum settings. 138 fn gen_enum_types(group: &SettingGroup, fmt: &mut Formatter) { 139 for setting in group.settings.iter() { 140 let values = match setting.specific { 141 SpecificSetting::Bool(_) | SpecificSetting::Num(_) => continue, 142 SpecificSetting::Enum(ref values) => values, 143 }; 144 let name = camel_case(setting.name); 145 146 fmt.doc_comment(format!("Values for `{}.{}`.", group.name, setting.name)); 147 fmtln!(fmt, "#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]"); 148 fmt.add_block(&format!("pub enum {name}"), |fmt| { 149 for v in values.iter() { 150 fmt.doc_comment(format!("`{v}`.")); 151 fmtln!(fmt, "{},", camel_case(v)); 152 } 153 }); 154 155 fmt.add_block(&format!("impl {name}"), |fmt| { 156 gen_enum_all(&name, values, fmt); 157 }); 158 159 gen_to_and_from_str(&name, values, fmt); 160 } 161 } 162 163 /// Emit a getter function for `setting`. 164 fn gen_getter(setting: &Setting, fmt: &mut Formatter) { 165 fmt.doc_comment(format!("{}\n{}", setting.description, setting.comment)); 166 match setting.specific { 167 SpecificSetting::Bool(BoolSetting { 168 predicate_number, .. 169 }) => { 170 fmt.add_block(&format!("pub fn {}(&self) -> bool", setting.name), |fmt| { 171 fmtln!(fmt, "self.numbered_predicate({})", predicate_number); 172 }); 173 } 174 SpecificSetting::Enum(ref values) => { 175 let ty = camel_case(setting.name); 176 fmt.add_block( 177 &format!("pub fn {}(&self) -> {}", setting.name, ty), 178 |fmt| { 179 let mut m = Match::new(format!("self.bytes[{}]", setting.byte_offset)); 180 for (i, v) in values.iter().enumerate() { 181 m.arm_no_fields(format!("{i}"), format!("{}::{}", ty, camel_case(v))); 182 } 183 m.arm_no_fields("_", "panic!(\"Invalid enum value\")"); 184 fmt.add_match(m); 185 }, 186 ); 187 } 188 SpecificSetting::Num(_) => { 189 fmt.add_block(&format!("pub fn {}(&self) -> u8", setting.name), |fmt| { 190 fmtln!(fmt, "self.bytes[{}]", setting.byte_offset); 191 }); 192 } 193 } 194 } 195 196 fn gen_pred_getter(predicate: &Predicate, group: &SettingGroup, fmt: &mut Formatter) { 197 fmt.doc_comment(format!("Computed predicate `{}`.", predicate.render(group))); 198 fmt.add_block( 199 &format!("pub fn {}(&self) -> bool", predicate.name), 200 |fmt| { 201 fmtln!(fmt, "self.numbered_predicate({})", predicate.number); 202 }, 203 ); 204 } 205 206 /// Emits getters for each setting value. 207 fn gen_getters(group: &SettingGroup, fmt: &mut Formatter) { 208 fmt.doc_comment("User-defined settings."); 209 fmtln!(fmt, "#[allow(dead_code, reason = \"generated code\")]"); 210 fmt.add_block("impl Flags", |fmt| { 211 if !group.settings.is_empty() { 212 fmt.doc_comment("Dynamic numbered predicate getter."); 213 fmt.add_block("fn numbered_predicate(&self, p: usize) -> bool", |fmt| { 214 fmtln!( 215 fmt, 216 "self.bytes[{} + p / 8] & (1 << (p % 8)) != 0", 217 group.bool_start_byte_offset 218 ); 219 }); 220 } 221 222 for setting in &group.settings { 223 gen_getter(setting, fmt); 224 } 225 for predicate in &group.predicates { 226 gen_pred_getter(predicate, group, fmt); 227 } 228 }); 229 } 230 231 #[derive(Hash, PartialEq, Eq)] 232 enum SettingOrPreset<'a> { 233 Setting(&'a Setting), 234 Preset(&'a Preset), 235 } 236 237 impl<'a> SettingOrPreset<'a> { 238 fn name(&self) -> &str { 239 match *self { 240 SettingOrPreset::Setting(s) => s.name, 241 SettingOrPreset::Preset(p) => p.name, 242 } 243 } 244 } 245 246 /// Emits DESCRIPTORS, ENUMERATORS, HASH_TABLE and PRESETS. 247 fn gen_descriptors(group: &SettingGroup, fmt: &mut Formatter) { 248 let mut enum_table = UniqueSeqTable::new(); 249 250 let mut descriptor_index_map: HashMap<SettingOrPreset, usize> = HashMap::new(); 251 252 // Generate descriptors. 253 fmtln!( 254 fmt, 255 "static DESCRIPTORS: [detail::Descriptor; {}] = [", 256 group.settings.len() + group.presets.len() 257 ); 258 fmt.indent(|fmt| { 259 for (idx, setting) in group.settings.iter().enumerate() { 260 fmt.add_block("detail::Descriptor", |fmt| { 261 fmtln!(fmt, "name: \"{}\",", setting.name); 262 fmtln!(fmt, "description: \"{}\",", setting.description); 263 fmtln!(fmt, "offset: {},", setting.byte_offset); 264 match setting.specific { 265 SpecificSetting::Bool(BoolSetting { bit_offset, .. }) => { 266 fmtln!( 267 fmt, 268 "detail: detail::Detail::Bool {{ bit: {} }},", 269 bit_offset 270 ); 271 } 272 SpecificSetting::Enum(ref values) => { 273 let offset = enum_table.add(values); 274 fmtln!( 275 fmt, 276 "detail: detail::Detail::Enum {{ last: {}, enumerators: {} }},", 277 values.len() - 1, 278 offset 279 ); 280 } 281 SpecificSetting::Num(_) => { 282 fmtln!(fmt, "detail: detail::Detail::Num,"); 283 } 284 } 285 286 descriptor_index_map.insert(SettingOrPreset::Setting(setting), idx); 287 }); 288 fmtln!(fmt, ","); 289 } 290 291 for (idx, preset) in group.presets.iter().enumerate() { 292 fmt.add_block("detail::Descriptor", |fmt| { 293 fmtln!(fmt, "name: \"{}\",", preset.name); 294 fmtln!(fmt, "description: \"{}\",", preset.description); 295 fmtln!(fmt, "offset: {},", (idx as u8) * group.settings_size); 296 fmtln!(fmt, "detail: detail::Detail::Preset,"); 297 }); 298 fmtln!(fmt, ","); 299 300 let whole_idx = idx + group.settings.len(); 301 descriptor_index_map.insert(SettingOrPreset::Preset(preset), whole_idx); 302 } 303 }); 304 fmtln!(fmt, "];"); 305 306 // Generate enumerators. 307 fmtln!(fmt, "static ENUMERATORS: [&str; {}] = [", enum_table.len()); 308 fmt.indent(|fmt| { 309 for enum_val in enum_table.iter() { 310 fmtln!(fmt, "\"{}\",", enum_val); 311 } 312 }); 313 fmtln!(fmt, "];"); 314 315 // Generate hash table. 316 let mut hash_entries: Vec<SettingOrPreset> = Vec::new(); 317 hash_entries.extend(group.settings.iter().map(SettingOrPreset::Setting)); 318 hash_entries.extend(group.presets.iter().map(SettingOrPreset::Preset)); 319 320 let hash_table = generate_table(hash_entries.iter(), hash_entries.len(), |entry| { 321 simple_hash(entry.name()) 322 }); 323 fmtln!(fmt, "static HASH_TABLE: [u16; {}] = [", hash_table.len()); 324 fmt.indent(|fmt| { 325 for h in &hash_table { 326 match *h { 327 Some(setting_or_preset) => fmtln!( 328 fmt, 329 "{},", 330 &descriptor_index_map 331 .get(setting_or_preset) 332 .unwrap() 333 .to_string() 334 ), 335 None => fmtln!(fmt, "0xffff,"), 336 } 337 } 338 }); 339 fmtln!(fmt, "];"); 340 341 // Generate presets. 342 fmtln!( 343 fmt, 344 "static PRESETS: [(u8, u8); {}] = [", 345 group.presets.len() * (group.settings_size as usize) 346 ); 347 fmt.indent(|fmt| { 348 for preset in &group.presets { 349 fmt.comment(format!( 350 "{}: {}", 351 preset.name, 352 preset.setting_names(group).collect::<Vec<_>>().join(", ") 353 )); 354 for (mask, value) in preset.layout(group) { 355 fmtln!(fmt, "(0b{:08b}, 0b{:08b}),", mask, value); 356 } 357 } 358 }); 359 fmtln!(fmt, "];"); 360 } 361 362 fn gen_template(group: &SettingGroup, fmt: &mut Formatter) { 363 let mut default_bytes: Vec<u8> = vec![0; group.settings_size as usize]; 364 for setting in &group.settings { 365 *default_bytes.get_mut(setting.byte_offset as usize).unwrap() |= setting.default_byte(); 366 } 367 368 let default_bytes: Vec<String> = default_bytes.iter().map(|x| format!("{x:#04x}")).collect(); 369 let default_bytes_str = default_bytes.join(", "); 370 371 fmt.add_block( 372 "static TEMPLATE: detail::Template = detail::Template", 373 |fmt| { 374 fmtln!(fmt, "name: \"{}\",", group.name); 375 fmtln!(fmt, "descriptors: &DESCRIPTORS,"); 376 fmtln!(fmt, "enumerators: &ENUMERATORS,"); 377 fmtln!(fmt, "hash_table: &HASH_TABLE,"); 378 fmtln!(fmt, "defaults: &[{}],", default_bytes_str); 379 fmtln!(fmt, "presets: &PRESETS,"); 380 }, 381 ); 382 fmtln!(fmt, ";"); 383 384 fmt.doc_comment(format!( 385 "Create a `settings::Builder` for the {} settings group.", 386 group.name 387 )); 388 fmt.add_block("pub fn builder() -> Builder", |fmt| { 389 fmtln!(fmt, "Builder::new(&TEMPLATE)"); 390 }); 391 } 392 393 fn gen_display(group: &SettingGroup, fmt: &mut Formatter) { 394 fmt.add_block("impl fmt::Display for Flags", |fmt| { 395 fmt.add_block( 396 "fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result", 397 |fmt| { 398 fmtln!(fmt, "writeln!(f, \"[{}]\")?;", group.name); 399 fmt.add_block("for d in &DESCRIPTORS", |fmt| { 400 fmt.add_block("if !d.detail.is_preset()", |fmt| { 401 fmtln!(fmt, "write!(f, \"{{}} = \", d.name)?;"); 402 fmtln!( 403 fmt, 404 "TEMPLATE.format_toml_value(d.detail, self.bytes[d.offset as usize], f)?;", 405 ); 406 fmtln!(fmt, "writeln!(f)?;"); 407 }); 408 }); 409 fmtln!(fmt, "Ok(())"); 410 }, 411 ); 412 }); 413 } 414 415 fn gen_hash_key(fmt: &mut Formatter) { 416 fmt.add_block("impl Flags", |fmt| { 417 fmt.doc_comment("Get the flag values as raw bytes for hashing."); 418 fmt.add_block("pub fn hash_key(&self) -> &[u8]", |fmt| { 419 fmtln!(fmt, "&self.bytes"); 420 }); 421 }); 422 } 423 424 fn gen_group(group: &SettingGroup, parent: ParentGroup, fmt: &mut Formatter) { 425 // Generate struct. 426 fmtln!(fmt, "#[derive(Clone, PartialEq, Hash)]"); 427 fmt.doc_comment(format!("Flags group `{}`.", group.name)); 428 fmt.add_block("pub struct Flags", |fmt| { 429 fmtln!(fmt, "bytes: [u8; {}],", group.byte_size()); 430 }); 431 432 gen_constructor(group, parent, fmt); 433 gen_iterator(group, fmt); 434 gen_enum_types(group, fmt); 435 gen_getters(group, fmt); 436 gen_descriptors(group, fmt); 437 gen_template(group, fmt); 438 gen_display(group, fmt); 439 gen_hash_key(fmt); 440 } 441 442 pub(crate) fn generate( 443 settings: &SettingGroup, 444 parent_group: ParentGroup, 445 filename: &str, 446 out_dir: &std::path::Path, 447 ) -> Result<(), error::Error> { 448 let mut fmt = Formatter::new(Language::Rust); 449 gen_group(settings, parent_group, &mut fmt); 450 fmt.write(filename, out_dir)?; 451 Ok(()) 452 } 453