Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/cranelift/codegen/meta/src/cdsl/settings.rs
3068 views
1
use std::iter;
2
3
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
4
pub(crate) struct BoolSettingIndex(usize);
5
6
#[derive(Hash, PartialEq, Eq)]
7
pub(crate) struct BoolSetting {
8
pub default: bool,
9
pub bit_offset: u8,
10
pub predicate_number: u8,
11
}
12
13
#[derive(Hash, PartialEq, Eq)]
14
pub(crate) enum SpecificSetting {
15
Bool(BoolSetting),
16
Enum(Vec<&'static str>),
17
Num(u8),
18
}
19
20
#[derive(Hash, PartialEq, Eq)]
21
pub(crate) struct Setting {
22
pub name: &'static str,
23
pub description: &'static str,
24
pub comment: &'static str,
25
pub specific: SpecificSetting,
26
pub byte_offset: u8,
27
}
28
29
impl Setting {
30
pub fn default_byte(&self) -> u8 {
31
match self.specific {
32
SpecificSetting::Bool(BoolSetting {
33
default,
34
bit_offset,
35
..
36
}) => {
37
if default {
38
1 << bit_offset
39
} else {
40
0
41
}
42
}
43
SpecificSetting::Enum(_) => 0,
44
SpecificSetting::Num(default) => default,
45
}
46
}
47
48
fn byte_for_value(&self, v: bool) -> u8 {
49
match self.specific {
50
SpecificSetting::Bool(BoolSetting { bit_offset, .. }) => {
51
if v {
52
1 << bit_offset
53
} else {
54
0
55
}
56
}
57
_ => panic!("byte_for_value shouldn't be used for non-boolean settings."),
58
}
59
}
60
61
fn byte_mask(&self) -> u8 {
62
match self.specific {
63
SpecificSetting::Bool(BoolSetting { bit_offset, .. }) => 1 << bit_offset,
64
_ => panic!("byte_for_value shouldn't be used for non-boolean settings."),
65
}
66
}
67
}
68
69
#[derive(Hash, PartialEq, Eq, Copy, Clone)]
70
pub(crate) struct PresetIndex(usize);
71
72
#[derive(Hash, PartialEq, Eq)]
73
pub(crate) enum PresetType {
74
BoolSetting(BoolSettingIndex),
75
OtherPreset(PresetIndex),
76
}
77
78
impl From<BoolSettingIndex> for PresetType {
79
fn from(bool_setting_index: BoolSettingIndex) -> Self {
80
PresetType::BoolSetting(bool_setting_index)
81
}
82
}
83
impl From<PresetIndex> for PresetType {
84
fn from(value: PresetIndex) -> Self {
85
PresetType::OtherPreset(value)
86
}
87
}
88
89
#[derive(Hash, PartialEq, Eq)]
90
pub(crate) struct Preset {
91
pub name: &'static str,
92
pub description: &'static str,
93
values: Vec<BoolSettingIndex>,
94
}
95
96
impl Preset {
97
pub fn layout(&self, group: &SettingGroup) -> Vec<(u8, u8)> {
98
let mut layout: Vec<(u8, u8)> = iter::repeat((0, 0))
99
.take(group.settings_size as usize)
100
.collect();
101
for bool_index in &self.values {
102
let setting = &group.settings[bool_index.0];
103
let mask = setting.byte_mask();
104
let val = setting.byte_for_value(true);
105
assert!((val & !mask) == 0);
106
let (ref mut l_mask, ref mut l_val) =
107
*layout.get_mut(setting.byte_offset as usize).unwrap();
108
*l_mask |= mask;
109
*l_val = (*l_val & !mask) | val;
110
}
111
layout
112
}
113
114
pub fn setting_names<'a>(
115
&'a self,
116
group: &'a SettingGroup,
117
) -> impl Iterator<Item = &'static str> + 'a {
118
self.values
119
.iter()
120
.map(|bool_index| group.settings[bool_index.0].name)
121
}
122
}
123
124
pub(crate) struct SettingGroup {
125
pub name: &'static str,
126
pub settings: Vec<Setting>,
127
pub bool_start_byte_offset: u8,
128
pub settings_size: u8,
129
pub presets: Vec<Preset>,
130
}
131
132
impl SettingGroup {
133
fn num_bool_settings(&self) -> u8 {
134
self.settings
135
.iter()
136
.filter(|s| matches!(s.specific, SpecificSetting::Bool(_)))
137
.count() as u8
138
}
139
140
pub fn byte_size(&self) -> u8 {
141
self.bool_start_byte_offset + (self.num_bool_settings() + 7) / 8
142
}
143
}
144
145
/// This is the basic information needed to track the specific parts of a setting when building
146
/// them.
147
pub(crate) enum ProtoSpecificSetting {
148
Bool(bool),
149
Enum(Vec<&'static str>),
150
Num(u8),
151
}
152
153
/// This is the information provided during building for a setting.
154
struct ProtoSetting {
155
name: &'static str,
156
description: &'static str,
157
comment: &'static str,
158
specific: ProtoSpecificSetting,
159
}
160
161
pub(crate) struct SettingGroupBuilder {
162
name: &'static str,
163
settings: Vec<ProtoSetting>,
164
presets: Vec<Preset>,
165
}
166
167
impl SettingGroupBuilder {
168
pub fn new(name: &'static str) -> Self {
169
Self {
170
name,
171
settings: Vec::new(),
172
presets: Vec::new(),
173
}
174
}
175
176
fn add_setting(
177
&mut self,
178
name: &'static str,
179
description: &'static str,
180
comment: &'static str,
181
specific: ProtoSpecificSetting,
182
) {
183
self.settings.push(ProtoSetting {
184
name,
185
description,
186
comment,
187
specific,
188
})
189
}
190
191
pub fn add_bool(
192
&mut self,
193
name: &'static str,
194
description: &'static str,
195
comment: &'static str,
196
default: bool,
197
) -> BoolSettingIndex {
198
self.add_setting(
199
name,
200
description,
201
comment,
202
ProtoSpecificSetting::Bool(default),
203
);
204
BoolSettingIndex(self.settings.len() - 1)
205
}
206
207
pub fn add_enum(
208
&mut self,
209
name: &'static str,
210
description: &'static str,
211
comment: &'static str,
212
values: Vec<&'static str>,
213
) {
214
self.add_setting(
215
name,
216
description,
217
comment,
218
ProtoSpecificSetting::Enum(values),
219
);
220
}
221
222
pub fn add_num(
223
&mut self,
224
name: &'static str,
225
description: &'static str,
226
comment: &'static str,
227
default: u8,
228
) {
229
self.add_setting(
230
name,
231
description,
232
comment,
233
ProtoSpecificSetting::Num(default),
234
);
235
}
236
237
pub fn add_preset(
238
&mut self,
239
name: &'static str,
240
description: &'static str,
241
args: Vec<PresetType>,
242
) -> PresetIndex {
243
let mut values = Vec::new();
244
for arg in args {
245
match arg {
246
PresetType::OtherPreset(index) => {
247
values.extend(self.presets[index.0].values.iter());
248
}
249
PresetType::BoolSetting(index) => values.push(index),
250
}
251
}
252
self.presets.push(Preset {
253
name,
254
description,
255
values,
256
});
257
PresetIndex(self.presets.len() - 1)
258
}
259
260
/// Compute the layout of the byte vector used to represent this settings
261
/// group.
262
///
263
/// The byte vector contains the following entries in order:
264
///
265
/// 1. Byte-sized settings like `NumSetting` and `EnumSetting`.
266
/// 2. `BoolSetting` settings.
267
///
268
/// Set `self.settings_size` to the length of the byte vector prefix that
269
/// contains the settings. All bytes after that are computed, not
270
/// configured.
271
///
272
/// Set `self.boolean_offset` to the beginning of the numbered predicates,
273
/// 2. in the list above.
274
///
275
/// Assign `byte_offset` and `bit_offset` fields in all settings.
276
pub fn build(self) -> SettingGroup {
277
let mut group = SettingGroup {
278
name: self.name,
279
settings: Vec::new(),
280
bool_start_byte_offset: 0,
281
settings_size: 0,
282
presets: Vec::new(),
283
};
284
285
let mut byte_offset = 0;
286
287
// Assign the non-boolean settings first.
288
for s in &self.settings {
289
let specific = match s.specific {
290
ProtoSpecificSetting::Bool(..) => continue,
291
ProtoSpecificSetting::Enum(ref values) => SpecificSetting::Enum(values.clone()),
292
ProtoSpecificSetting::Num(default) => SpecificSetting::Num(default),
293
};
294
295
group.settings.push(Setting {
296
name: s.name,
297
description: s.description,
298
comment: s.comment,
299
byte_offset,
300
specific,
301
});
302
303
byte_offset += 1;
304
}
305
306
group.bool_start_byte_offset = byte_offset;
307
308
let mut predicate_number = 0;
309
310
// Then the boolean settings.
311
for s in &self.settings {
312
let default = match s.specific {
313
ProtoSpecificSetting::Bool(default) => default,
314
ProtoSpecificSetting::Enum(_) | ProtoSpecificSetting::Num(_) => continue,
315
};
316
group.settings.push(Setting {
317
name: s.name,
318
description: s.description,
319
comment: s.comment,
320
byte_offset: byte_offset + predicate_number / 8,
321
specific: SpecificSetting::Bool(BoolSetting {
322
default,
323
bit_offset: predicate_number % 8,
324
predicate_number,
325
}),
326
});
327
predicate_number += 1;
328
}
329
330
group.settings_size = group.byte_size();
331
332
group.presets.extend(self.presets);
333
334
group
335
}
336
}
337
338