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