pub struct Template {
    pub name: &'static str,
    pub descriptors: &'static [Descriptor],
    pub enumerators: &'static [&'static str],
    pub hash_table: &'static [u16],
    pub defaults: &'static [u8],
    pub presets: &'static [(u8, u8)],
}
Expand description

An instruction group template.

Fields§

§name: &'static str

Name of the instruction group.

§descriptors: &'static [Descriptor]

List of setting descriptors.

§enumerators: &'static [&'static str]

Union of all enumerators.

§hash_table: &'static [u16]

Hash table of settings.

§defaults: &'static [u8]

Default values.

§presets: &'static [(u8, u8)]

Pairs of (mask, value) for presets.

Implementations§

Get enumerators corresponding to a Details::Enum.

Examples found in repository?
/opt/rustwide/target/x86_64-unknown-linux-gnu/debug/build/cranelift-codegen-0715cf9fa7730334/out/settings.rs (line 25)
19
20
21
22
23
24
25
26
27
28
29
30
    pub fn iter(&self) -> impl Iterator<Item = Value> {
        let mut bytes = [0; 9];
        bytes.copy_from_slice(&self.bytes[0..9]);
        DESCRIPTORS.iter().filter_map(move |d| {
            let values = match &d.detail {
                detail::Detail::Preset => return None,
                detail::Detail::Enum { last, enumerators } => Some(TEMPLATE.enums(*last, *enumerators)),
                _ => None
            };
            Some(Value{ name: d.name, detail: d.detail, values, value: bytes[d.offset as usize] })
        })
    }
More examples
Hide additional examples
src/settings.rs (line 176)
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
    pub fn iter(&self) -> impl Iterator<Item = Setting> {
        let template = self.template;

        template.descriptors.iter().map(move |d| {
            let (kind, values) = match d.detail {
                detail::Detail::Enum { last, enumerators } => {
                    let values = template.enums(last, enumerators);
                    (SettingKind::Enum, Some(values))
                }
                detail::Detail::Num => (SettingKind::Num, None),
                detail::Detail::Bool { .. } => (SettingKind::Bool, None),
                detail::Detail::Preset => (SettingKind::Preset, None),
            };

            Setting {
                name: d.name,
                description: d.description,
                kind,
                values,
            }
        })
    }

    /// Set the value of a single bit.
    fn set_bit(&mut self, offset: usize, bit: u8, value: bool) {
        let byte = &mut self.bytes[offset];
        let mask = 1 << bit;
        if value {
            *byte |= mask;
        } else {
            *byte &= !mask;
        }
    }

    /// Apply a preset. The argument is a slice of (mask, value) bytes.
    fn apply_preset(&mut self, values: &[(u8, u8)]) {
        for (byte, &(mask, value)) in self.bytes.iter_mut().zip(values) {
            *byte = (*byte & !mask) | value;
        }
    }

    /// Look up a descriptor by name.
    fn lookup(&self, name: &str) -> SetResult<(usize, detail::Detail)> {
        match probe(self.template, name, simple_hash(name)) {
            Err(_) => Err(SetError::BadName(name.to_string())),
            Ok(entry) => {
                let d = &self.template.descriptors[self.template.hash_table[entry] as usize];
                Ok((d.offset as usize, d.detail))
            }
        }
    }
}

fn parse_bool_value(value: &str) -> SetResult<bool> {
    match value {
        "true" | "on" | "yes" | "1" => Ok(true),
        "false" | "off" | "no" | "0" => Ok(false),
        _ => Err(SetError::BadValue("bool".to_string())),
    }
}

fn parse_enum_value(value: &str, choices: &[&str]) -> SetResult<u8> {
    match choices.iter().position(|&tag| tag == value) {
        Some(idx) => Ok(idx as u8),
        None => {
            // TODO: Use `join` instead of this code, once
            // https://github.com/rust-lang/rust/issues/27747 is resolved.
            let mut all_choices = String::new();
            let mut first = true;
            for choice in choices {
                if first {
                    first = false
                } else {
                    all_choices += ", ";
                }
                all_choices += choice;
            }
            Err(SetError::BadValue(format!("any among {}", all_choices)))
        }
    }
}

impl Configurable for Builder {
    fn enable(&mut self, name: &str) -> SetResult<()> {
        use self::detail::Detail;
        let (offset, detail) = self.lookup(name)?;
        match detail {
            Detail::Bool { bit } => {
                self.set_bit(offset, bit, true);
                Ok(())
            }
            Detail::Preset => {
                self.apply_preset(&self.template.presets[offset..]);
                Ok(())
            }
            _ => Err(SetError::BadType),
        }
    }

    fn set(&mut self, name: &str, value: &str) -> SetResult<()> {
        use self::detail::Detail;
        let (offset, detail) = self.lookup(name)?;
        match detail {
            Detail::Bool { bit } => {
                self.set_bit(offset, bit, parse_bool_value(value)?);
            }
            Detail::Num => {
                self.bytes[offset] = value
                    .parse()
                    .map_err(|_| SetError::BadValue("number".to_string()))?;
            }
            Detail::Enum { last, enumerators } => {
                self.bytes[offset] =
                    parse_enum_value(value, self.template.enums(last, enumerators))?;
            }
            Detail::Preset => return Err(SetError::BadName(name.to_string())),
        }
        Ok(())
    }
}

/// An error produced when changing a setting.
#[derive(Debug, PartialEq, Eq)]
pub enum SetError {
    /// No setting by this name exists.
    BadName(String),

    /// Type mismatch for setting (e.g., setting an enum setting as a bool).
    BadType,

    /// This is not a valid value for this setting.
    BadValue(String),
}

impl std::error::Error for SetError {}

impl fmt::Display for SetError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            SetError::BadName(name) => write!(f, "No existing setting named '{}'", name),
            SetError::BadType => {
                write!(f, "Trying to set a setting with the wrong type")
            }
            SetError::BadValue(value) => {
                write!(f, "Unexpected value for a setting, expected {}", value)
            }
        }
    }
}

/// A result returned when changing a setting.
pub type SetResult<T> = Result<T, SetError>;

/// A reference to just the boolean predicates of a settings object.
///
/// The settings objects themselves are generated and appear in the `isa/*/settings.rs` modules.
/// Each settings object provides a `predicate_view()` method that makes it possible to query
/// ISA predicates by number.
#[derive(Clone, Copy, Hash)]
pub struct PredicateView<'a>(&'a [u8]);

impl<'a> PredicateView<'a> {
    /// Create a new view of a precomputed predicate vector.
    ///
    /// See the `predicate_view()` method on the various `Flags` types defined for each ISA.
    pub fn new(bits: &'a [u8]) -> Self {
        PredicateView(bits)
    }

    /// Check a numbered predicate.
    pub fn test(self, p: usize) -> bool {
        self.0[p / 8] & (1 << (p % 8)) != 0
    }
}

/// Implementation details for generated code.
///
/// This module holds definitions that need to be public so the can be instantiated by generated
/// code in other modules.
pub mod detail {
    use crate::constant_hash;
    use core::fmt;
    use core::hash::Hash;

    /// An instruction group template.
    #[derive(Hash)]
    pub struct Template {
        /// Name of the instruction group.
        pub name: &'static str,
        /// List of setting descriptors.
        pub descriptors: &'static [Descriptor],
        /// Union of all enumerators.
        pub enumerators: &'static [&'static str],
        /// Hash table of settings.
        pub hash_table: &'static [u16],
        /// Default values.
        pub defaults: &'static [u8],
        /// Pairs of (mask, value) for presets.
        pub presets: &'static [(u8, u8)],
    }

    impl Template {
        /// Get enumerators corresponding to a `Details::Enum`.
        pub fn enums(&self, last: u8, enumerators: u16) -> &[&'static str] {
            let from = enumerators as usize;
            let len = usize::from(last) + 1;
            &self.enumerators[from..from + len]
        }

        /// Format a setting value as a TOML string. This is mostly for use by the generated
        /// `Display` implementation.
        pub fn format_toml_value(
            &self,
            detail: Detail,
            byte: u8,
            f: &mut fmt::Formatter,
        ) -> fmt::Result {
            match detail {
                Detail::Bool { bit } => write!(f, "{}", (byte & (1 << bit)) != 0),
                Detail::Num => write!(f, "{}", byte),
                Detail::Enum { last, enumerators } => {
                    if byte <= last {
                        let tags = self.enums(last, enumerators);
                        write!(f, "\"{}\"", tags[usize::from(byte)])
                    } else {
                        write!(f, "{}", byte)
                    }
                }
                // Presets aren't printed. They are reflected in the other settings.
                Detail::Preset { .. } => Ok(()),
            }
        }

Format a setting value as a TOML string. This is mostly for use by the generated Display implementation.

Examples found in repository?
/opt/rustwide/target/x86_64-unknown-linux-gnu/debug/build/cranelift-codegen-0715cf9fa7730334/out/settings.rs (line 828)
823
824
825
826
827
828
829
830
831
832
833
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "[shared]")?;
        for d in &DESCRIPTORS {
            if !d.detail.is_preset() {
                write!(f, "{} = ", d.name)?;
                TEMPLATE.format_toml_value(d.detail, self.bytes[d.offset as usize], f)?;
                writeln!(f)?;
            }
        }
        Ok(())
    }

Trait Implementations§

Feeds this value into the given Hasher. Read more
Feeds a slice of this type into the given Hasher. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.