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