Path: blob/main/cranelift/codegen/meta/src/cdsl/settings.rs
3068 views
use std::iter;12#[derive(Clone, Copy, Hash, PartialEq, Eq)]3pub(crate) struct BoolSettingIndex(usize);45#[derive(Hash, PartialEq, Eq)]6pub(crate) struct BoolSetting {7pub default: bool,8pub bit_offset: u8,9pub predicate_number: u8,10}1112#[derive(Hash, PartialEq, Eq)]13pub(crate) enum SpecificSetting {14Bool(BoolSetting),15Enum(Vec<&'static str>),16Num(u8),17}1819#[derive(Hash, PartialEq, Eq)]20pub(crate) struct Setting {21pub name: &'static str,22pub description: &'static str,23pub comment: &'static str,24pub specific: SpecificSetting,25pub byte_offset: u8,26}2728impl Setting {29pub fn default_byte(&self) -> u8 {30match self.specific {31SpecificSetting::Bool(BoolSetting {32default,33bit_offset,34..35}) => {36if default {371 << bit_offset38} else {39040}41}42SpecificSetting::Enum(_) => 0,43SpecificSetting::Num(default) => default,44}45}4647fn byte_for_value(&self, v: bool) -> u8 {48match self.specific {49SpecificSetting::Bool(BoolSetting { bit_offset, .. }) => {50if v {511 << bit_offset52} else {53054}55}56_ => panic!("byte_for_value shouldn't be used for non-boolean settings."),57}58}5960fn byte_mask(&self) -> u8 {61match self.specific {62SpecificSetting::Bool(BoolSetting { bit_offset, .. }) => 1 << bit_offset,63_ => panic!("byte_for_value shouldn't be used for non-boolean settings."),64}65}66}6768#[derive(Hash, PartialEq, Eq, Copy, Clone)]69pub(crate) struct PresetIndex(usize);7071#[derive(Hash, PartialEq, Eq)]72pub(crate) enum PresetType {73BoolSetting(BoolSettingIndex),74OtherPreset(PresetIndex),75}7677impl From<BoolSettingIndex> for PresetType {78fn from(bool_setting_index: BoolSettingIndex) -> Self {79PresetType::BoolSetting(bool_setting_index)80}81}82impl From<PresetIndex> for PresetType {83fn from(value: PresetIndex) -> Self {84PresetType::OtherPreset(value)85}86}8788#[derive(Hash, PartialEq, Eq)]89pub(crate) struct Preset {90pub name: &'static str,91pub description: &'static str,92values: Vec<BoolSettingIndex>,93}9495impl Preset {96pub fn layout(&self, group: &SettingGroup) -> Vec<(u8, u8)> {97let mut layout: Vec<(u8, u8)> = iter::repeat((0, 0))98.take(group.settings_size as usize)99.collect();100for bool_index in &self.values {101let setting = &group.settings[bool_index.0];102let mask = setting.byte_mask();103let val = setting.byte_for_value(true);104assert!((val & !mask) == 0);105let (ref mut l_mask, ref mut l_val) =106*layout.get_mut(setting.byte_offset as usize).unwrap();107*l_mask |= mask;108*l_val = (*l_val & !mask) | val;109}110layout111}112113pub fn setting_names<'a>(114&'a self,115group: &'a SettingGroup,116) -> impl Iterator<Item = &'static str> + 'a {117self.values118.iter()119.map(|bool_index| group.settings[bool_index.0].name)120}121}122123pub(crate) struct SettingGroup {124pub name: &'static str,125pub settings: Vec<Setting>,126pub bool_start_byte_offset: u8,127pub settings_size: u8,128pub presets: Vec<Preset>,129}130131impl SettingGroup {132fn num_bool_settings(&self) -> u8 {133self.settings134.iter()135.filter(|s| matches!(s.specific, SpecificSetting::Bool(_)))136.count() as u8137}138139pub fn byte_size(&self) -> u8 {140self.bool_start_byte_offset + (self.num_bool_settings() + 7) / 8141}142}143144/// This is the basic information needed to track the specific parts of a setting when building145/// them.146pub(crate) enum ProtoSpecificSetting {147Bool(bool),148Enum(Vec<&'static str>),149Num(u8),150}151152/// This is the information provided during building for a setting.153struct ProtoSetting {154name: &'static str,155description: &'static str,156comment: &'static str,157specific: ProtoSpecificSetting,158}159160pub(crate) struct SettingGroupBuilder {161name: &'static str,162settings: Vec<ProtoSetting>,163presets: Vec<Preset>,164}165166impl SettingGroupBuilder {167pub fn new(name: &'static str) -> Self {168Self {169name,170settings: Vec::new(),171presets: Vec::new(),172}173}174175fn add_setting(176&mut self,177name: &'static str,178description: &'static str,179comment: &'static str,180specific: ProtoSpecificSetting,181) {182self.settings.push(ProtoSetting {183name,184description,185comment,186specific,187})188}189190pub fn add_bool(191&mut self,192name: &'static str,193description: &'static str,194comment: &'static str,195default: bool,196) -> BoolSettingIndex {197self.add_setting(198name,199description,200comment,201ProtoSpecificSetting::Bool(default),202);203BoolSettingIndex(self.settings.len() - 1)204}205206pub fn add_enum(207&mut self,208name: &'static str,209description: &'static str,210comment: &'static str,211values: Vec<&'static str>,212) {213self.add_setting(214name,215description,216comment,217ProtoSpecificSetting::Enum(values),218);219}220221pub fn add_num(222&mut self,223name: &'static str,224description: &'static str,225comment: &'static str,226default: u8,227) {228self.add_setting(229name,230description,231comment,232ProtoSpecificSetting::Num(default),233);234}235236pub fn add_preset(237&mut self,238name: &'static str,239description: &'static str,240args: Vec<PresetType>,241) -> PresetIndex {242let mut values = Vec::new();243for arg in args {244match arg {245PresetType::OtherPreset(index) => {246values.extend(self.presets[index.0].values.iter());247}248PresetType::BoolSetting(index) => values.push(index),249}250}251self.presets.push(Preset {252name,253description,254values,255});256PresetIndex(self.presets.len() - 1)257}258259/// Compute the layout of the byte vector used to represent this settings260/// group.261///262/// The byte vector contains the following entries in order:263///264/// 1. Byte-sized settings like `NumSetting` and `EnumSetting`.265/// 2. `BoolSetting` settings.266///267/// Set `self.settings_size` to the length of the byte vector prefix that268/// contains the settings. All bytes after that are computed, not269/// configured.270///271/// Set `self.boolean_offset` to the beginning of the numbered predicates,272/// 2. in the list above.273///274/// Assign `byte_offset` and `bit_offset` fields in all settings.275pub fn build(self) -> SettingGroup {276let mut group = SettingGroup {277name: self.name,278settings: Vec::new(),279bool_start_byte_offset: 0,280settings_size: 0,281presets: Vec::new(),282};283284let mut byte_offset = 0;285286// Assign the non-boolean settings first.287for s in &self.settings {288let specific = match s.specific {289ProtoSpecificSetting::Bool(..) => continue,290ProtoSpecificSetting::Enum(ref values) => SpecificSetting::Enum(values.clone()),291ProtoSpecificSetting::Num(default) => SpecificSetting::Num(default),292};293294group.settings.push(Setting {295name: s.name,296description: s.description,297comment: s.comment,298byte_offset,299specific,300});301302byte_offset += 1;303}304305group.bool_start_byte_offset = byte_offset;306307let mut predicate_number = 0;308309// Then the boolean settings.310for s in &self.settings {311let default = match s.specific {312ProtoSpecificSetting::Bool(default) => default,313ProtoSpecificSetting::Enum(_) | ProtoSpecificSetting::Num(_) => continue,314};315group.settings.push(Setting {316name: s.name,317description: s.description,318comment: s.comment,319byte_offset: byte_offset + predicate_number / 8,320specific: SpecificSetting::Bool(BoolSetting {321default,322bit_offset: predicate_number % 8,323predicate_number,324}),325});326predicate_number += 1;327}328329group.settings_size = group.byte_size();330331group.presets.extend(self.presets);332333group334}335}336337338