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