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 /// Emit Display and FromStr implementations for enum settings. 102 fn gen_to_and_from_str(name: &str, values: &[&'static str], fmt: &mut Formatter) { 103 fmtln!(fmt, "impl fmt::Display for {} {{", name); 104 fmt.indent(|fmt| { 105 fmtln!( 106 fmt, 107 "fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {" 108 ); 109 fmt.indent(|fmt| { 110 fmtln!(fmt, "f.write_str(match *self {"); 111 fmt.indent(|fmt| { 112 for v in values.iter() { 113 fmtln!(fmt, "Self::{} => \"{}\",", camel_case(v), v); 114 } 115 }); 116 fmtln!(fmt, "})"); 117 }); 118 fmtln!(fmt, "}"); 119 }); 120 fmtln!(fmt, "}"); 121 122 fmtln!(fmt, "impl core::str::FromStr for {} {{", name); 123 fmt.indent(|fmt| { 124 fmtln!(fmt, "type Err = ();"); 125 fmtln!(fmt, "fn from_str(s: &str) -> Result<Self, Self::Err> {"); 126 fmt.indent(|fmt| { 127 fmtln!(fmt, "match s {"); 128 fmt.indent(|fmt| { 129 for v in values.iter() { 130 fmtln!(fmt, "\"{}\" => Ok(Self::{}),", v, camel_case(v)); 131 } 132 fmtln!(fmt, "_ => Err(()),"); 133 }); 134 fmtln!(fmt, "}"); 135 }); 136 fmtln!(fmt, "}"); 137 }); 138 fmtln!(fmt, "}"); 139 } 140 141 /// Emit real enum for the Enum settings. 142 fn gen_enum_types(group: &SettingGroup, fmt: &mut Formatter) { 143 for setting in group.settings.iter() { 144 let values = match setting.specific { 145 SpecificSetting::Bool(_) | SpecificSetting::Num(_) => continue, 146 SpecificSetting::Enum(ref values) => values, 147 }; 148 let name = camel_case(setting.name); 149 150 fmt.doc_comment(format!("Values for `{}.{}`.", group.name, setting.name)); 151 fmtln!(fmt, "#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]"); 152 fmtln!(fmt, "pub enum {} {{", name); 153 fmt.indent(|fmt| { 154 for v in values.iter() { 155 fmt.doc_comment(format!("`{}`.", v)); 156 fmtln!(fmt, "{},", camel_case(v)); 157 } 158 }); 159 fmtln!(fmt, "}"); 160 161 gen_to_and_from_str(&name, values, fmt); 162 } 163 } 164 165 /// Emit a getter function for `setting`. 166 fn gen_getter(setting: &Setting, fmt: &mut Formatter) { 167 fmt.doc_comment(format!("{}\n{}", setting.description, setting.comment)); 168 match setting.specific { 169 SpecificSetting::Bool(BoolSetting { 170 predicate_number, .. 171 }) => { 172 fmtln!(fmt, "pub fn {}(&self) -> bool {{", setting.name); 173 fmt.indent(|fmt| { 174 fmtln!(fmt, "self.numbered_predicate({})", predicate_number); 175 }); 176 fmtln!(fmt, "}"); 177 } 178 SpecificSetting::Enum(ref values) => { 179 let ty = camel_case(setting.name); 180 fmtln!(fmt, "pub fn {}(&self) -> {} {{", setting.name, ty); 181 fmt.indent(|fmt| { 182 let mut m = Match::new(format!("self.bytes[{}]", setting.byte_offset)); 183 for (i, v) in values.iter().enumerate() { 184 m.arm_no_fields(format!("{}", i), format!("{}::{}", ty, camel_case(v))); 185 } 186 m.arm_no_fields("_", "panic!(\"Invalid enum value\")"); 187 fmt.add_match(m); 188 }); 189 fmtln!(fmt, "}"); 190 } 191 SpecificSetting::Num(_) => { 192 fmtln!(fmt, "pub fn {}(&self) -> u8 {{", setting.name); 193 fmt.indent(|fmt| { 194 fmtln!(fmt, "self.bytes[{}]", setting.byte_offset); 195 }); 196 fmtln!(fmt, "}"); 197 } 198 } 199 } 200 201 fn gen_pred_getter(predicate: &Predicate, group: &SettingGroup, fmt: &mut Formatter) { 202 fmt.doc_comment(format!("Computed predicate `{}`.", predicate.render(group))); 203 fmtln!(fmt, "pub fn {}(&self) -> bool {{", predicate.name); 204 fmt.indent(|fmt| { 205 fmtln!(fmt, "self.numbered_predicate({})", predicate.number); 206 }); 207 fmtln!(fmt, "}"); 208 } 209 210 /// Emits getters for each setting value. 211 fn gen_getters(group: &SettingGroup, fmt: &mut Formatter) { 212 fmt.doc_comment("User-defined settings."); 213 fmtln!(fmt, "#[allow(dead_code)]"); 214 fmtln!(fmt, "impl Flags {"); 215 fmt.indent(|fmt| { 216 fmt.doc_comment("Get a view of the boolean predicates."); 217 fmtln!( 218 fmt, 219 "pub fn predicate_view(&self) -> crate::settings::PredicateView {" 220 ); 221 fmt.indent(|fmt| { 222 fmtln!( 223 fmt, 224 "crate::settings::PredicateView::new(&self.bytes[{}..])", 225 group.bool_start_byte_offset 226 ); 227 }); 228 fmtln!(fmt, "}"); 229 230 if !group.settings.is_empty() { 231 fmt.doc_comment("Dynamic numbered predicate getter."); 232 fmtln!(fmt, "fn numbered_predicate(&self, p: usize) -> bool {"); 233 fmt.indent(|fmt| { 234 fmtln!( 235 fmt, 236 "self.bytes[{} + p / 8] & (1 << (p % 8)) != 0", 237 group.bool_start_byte_offset 238 ); 239 }); 240 fmtln!(fmt, "}"); 241 } 242 243 for setting in &group.settings { 244 gen_getter(&setting, fmt); 245 } 246 for predicate in &group.predicates { 247 gen_pred_getter(&predicate, &group, fmt); 248 } 249 }); 250 fmtln!(fmt, "}"); 251 } 252 253 #[derive(Hash, PartialEq, Eq)] 254 enum SettingOrPreset<'a> { 255 Setting(&'a Setting), 256 Preset(&'a Preset), 257 } 258 259 impl<'a> SettingOrPreset<'a> { 260 fn name(&self) -> &str { 261 match *self { 262 SettingOrPreset::Setting(s) => s.name, 263 SettingOrPreset::Preset(p) => p.name, 264 } 265 } 266 } 267 268 /// Emits DESCRIPTORS, ENUMERATORS, HASH_TABLE and PRESETS. 269 fn gen_descriptors(group: &SettingGroup, fmt: &mut Formatter) { 270 let mut enum_table = UniqueSeqTable::new(); 271 272 let mut descriptor_index_map: HashMap<SettingOrPreset, usize> = HashMap::new(); 273 274 // Generate descriptors. 275 fmtln!( 276 fmt, 277 "static DESCRIPTORS: [detail::Descriptor; {}] = [", 278 group.settings.len() + group.presets.len() 279 ); 280 fmt.indent(|fmt| { 281 for (idx, setting) in group.settings.iter().enumerate() { 282 fmtln!(fmt, "detail::Descriptor {"); 283 fmt.indent(|fmt| { 284 fmtln!(fmt, "name: \"{}\",", setting.name); 285 fmtln!(fmt, "description: \"{}\",", setting.description); 286 fmtln!(fmt, "offset: {},", setting.byte_offset); 287 match setting.specific { 288 SpecificSetting::Bool(BoolSetting { bit_offset, .. }) => { 289 fmtln!( 290 fmt, 291 "detail: detail::Detail::Bool {{ bit: {} }},", 292 bit_offset 293 ); 294 } 295 SpecificSetting::Enum(ref values) => { 296 let offset = enum_table.add(values); 297 fmtln!( 298 fmt, 299 "detail: detail::Detail::Enum {{ last: {}, enumerators: {} }},", 300 values.len() - 1, 301 offset 302 ); 303 } 304 SpecificSetting::Num(_) => { 305 fmtln!(fmt, "detail: detail::Detail::Num,"); 306 } 307 } 308 309 descriptor_index_map.insert(SettingOrPreset::Setting(setting), idx); 310 }); 311 fmtln!(fmt, "},"); 312 } 313 314 for (idx, preset) in group.presets.iter().enumerate() { 315 fmtln!(fmt, "detail::Descriptor {"); 316 fmt.indent(|fmt| { 317 fmtln!(fmt, "name: \"{}\",", preset.name); 318 fmtln!(fmt, "description: \"{}\",", preset.description); 319 fmtln!(fmt, "offset: {},", (idx as u8) * group.settings_size); 320 fmtln!(fmt, "detail: detail::Detail::Preset,"); 321 }); 322 fmtln!(fmt, "},"); 323 324 let whole_idx = idx + group.settings.len(); 325 descriptor_index_map.insert(SettingOrPreset::Preset(preset), whole_idx); 326 } 327 }); 328 fmtln!(fmt, "];"); 329 330 // Generate enumerators. 331 fmtln!(fmt, "static ENUMERATORS: [&str; {}] = [", enum_table.len()); 332 fmt.indent(|fmt| { 333 for enum_val in enum_table.iter() { 334 fmtln!(fmt, "\"{}\",", enum_val); 335 } 336 }); 337 fmtln!(fmt, "];"); 338 339 // Generate hash table. 340 let mut hash_entries: Vec<SettingOrPreset> = Vec::new(); 341 hash_entries.extend(group.settings.iter().map(|x| SettingOrPreset::Setting(x))); 342 hash_entries.extend(group.presets.iter().map(|x| SettingOrPreset::Preset(x))); 343 344 let hash_table = generate_table(hash_entries.iter(), hash_entries.len(), |entry| { 345 simple_hash(entry.name()) 346 }); 347 fmtln!(fmt, "static HASH_TABLE: [u16; {}] = [", hash_table.len()); 348 fmt.indent(|fmt| { 349 for h in &hash_table { 350 match *h { 351 Some(setting_or_preset) => fmtln!( 352 fmt, 353 "{},", 354 &descriptor_index_map 355 .get(setting_or_preset) 356 .unwrap() 357 .to_string() 358 ), 359 None => fmtln!(fmt, "0xffff,"), 360 } 361 } 362 }); 363 fmtln!(fmt, "];"); 364 365 // Generate presets. 366 fmtln!( 367 fmt, 368 "static PRESETS: [(u8, u8); {}] = [", 369 group.presets.len() * (group.settings_size as usize) 370 ); 371 fmt.indent(|fmt| { 372 for preset in &group.presets { 373 fmt.comment(format!( 374 "{}: {}", 375 preset.name, 376 preset.setting_names(&group).collect::<Vec<_>>().join(", ") 377 )); 378 for (mask, value) in preset.layout(&group) { 379 fmtln!(fmt, "(0b{:08b}, 0b{:08b}),", mask, value); 380 } 381 } 382 }); 383 fmtln!(fmt, "];"); 384 } 385 386 fn gen_template(group: &SettingGroup, fmt: &mut Formatter) { 387 let mut default_bytes: Vec<u8> = vec![0; group.settings_size as usize]; 388 for setting in &group.settings { 389 *default_bytes.get_mut(setting.byte_offset as usize).unwrap() |= setting.default_byte(); 390 } 391 392 let default_bytes: Vec<String> = default_bytes 393 .iter() 394 .map(|x| format!("{:#04x}", x)) 395 .collect(); 396 let default_bytes_str = default_bytes.join(", "); 397 398 fmtln!( 399 fmt, 400 "static TEMPLATE: detail::Template = detail::Template {" 401 ); 402 fmt.indent(|fmt| { 403 fmtln!(fmt, "name: \"{}\",", group.name); 404 fmtln!(fmt, "descriptors: &DESCRIPTORS,"); 405 fmtln!(fmt, "enumerators: &ENUMERATORS,"); 406 fmtln!(fmt, "hash_table: &HASH_TABLE,"); 407 fmtln!(fmt, "defaults: &[{}],", default_bytes_str); 408 fmtln!(fmt, "presets: &PRESETS,"); 409 }); 410 fmtln!(fmt, "};"); 411 412 fmt.doc_comment(format!( 413 "Create a `settings::Builder` for the {} settings group.", 414 group.name 415 )); 416 fmtln!(fmt, "pub fn builder() -> Builder {"); 417 fmt.indent(|fmt| { 418 fmtln!(fmt, "Builder::new(&TEMPLATE)"); 419 }); 420 fmtln!(fmt, "}"); 421 } 422 423 fn gen_display(group: &SettingGroup, fmt: &mut Formatter) { 424 fmtln!(fmt, "impl fmt::Display for Flags {"); 425 fmt.indent(|fmt| { 426 fmtln!( 427 fmt, 428 "fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {" 429 ); 430 fmt.indent(|fmt| { 431 fmtln!(fmt, "writeln!(f, \"[{}]\")?;", group.name); 432 fmtln!(fmt, "for d in &DESCRIPTORS {"); 433 fmt.indent(|fmt| { 434 fmtln!(fmt, "if !d.detail.is_preset() {"); 435 fmt.indent(|fmt| { 436 fmtln!(fmt, "write!(f, \"{} = \", d.name)?;"); 437 fmtln!( 438 fmt, 439 "TEMPLATE.format_toml_value(d.detail, self.bytes[d.offset as usize], f)?;", 440 ); 441 fmtln!(fmt, "writeln!(f)?;"); 442 }); 443 fmtln!(fmt, "}"); 444 }); 445 fmtln!(fmt, "}"); 446 fmtln!(fmt, "Ok(())"); 447 }); 448 fmtln!(fmt, "}") 449 }); 450 fmtln!(fmt, "}"); 451 } 452 453 fn gen_group(group: &SettingGroup, parent: ParentGroup, fmt: &mut Formatter) { 454 // Generate struct. 455 fmtln!(fmt, "#[derive(Clone, Hash)]"); 456 fmt.doc_comment(format!("Flags group `{}`.", group.name)); 457 fmtln!(fmt, "pub struct Flags {"); 458 fmt.indent(|fmt| { 459 fmtln!(fmt, "bytes: [u8; {}],", group.byte_size()); 460 }); 461 fmtln!(fmt, "}"); 462 463 gen_constructor(group, parent, fmt); 464 gen_iterator(group, fmt); 465 gen_enum_types(group, fmt); 466 gen_getters(group, fmt); 467 gen_descriptors(group, fmt); 468 gen_template(group, fmt); 469 gen_display(group, fmt); 470 } 471 472 pub(crate) fn generate( 473 settings: &SettingGroup, 474 parent_group: ParentGroup, 475 filename: &str, 476 out_dir: &str, 477 ) -> Result<(), error::Error> { 478 let mut fmt = Formatter::new(); 479 gen_group(&settings, parent_group, &mut fmt); 480 fmt.update_file(filename, out_dir)?; 481 Ok(()) 482 } 483