diff --git a/lib/cretonne/meta/gen_settings.py b/lib/cretonne/meta/gen_settings.py index c56cc4df41..1a79026c36 100644 --- a/lib/cretonne/meta/gen_settings.py +++ b/lib/cretonne/meta/gen_settings.py @@ -87,16 +87,20 @@ def gen_getters(sgrp, fmt): """ fmt.doc_comment("User-defined settings.") with fmt.indented('impl Flags {', '}'): - fmt.doc_comment('Returns inner slice of bytes.') - fmt.doc_comment('The byte-sized settings are not included.') - with fmt.indented('pub fn predicate_bytes(&self) -> &[u8] {', '}'): - fmt.line('&self.bytes[{}..]'.format(sgrp.boolean_offset)) - fmt.doc_comment('Dynamic numbered predicate getter.') + fmt.doc_comment('Get a view of the boolean predicates.') with fmt.indented( - 'pub fn numbered_predicate(&self, p: usize) -> bool {', '}'): - fmt.line( - 'self.bytes[{} + p/8] & (1 << (p%8)) != 0' - .format(sgrp.boolean_offset)) + 'pub fn predicate_view(&self) -> ::settings::PredicateView {', + '}'): + fmt.format( + '::settings::PredicateView::new(&self.bytes[{}..])', + sgrp.boolean_offset) + if sgrp.settings: + fmt.doc_comment('Dynamic numbered predicate getter.') + with fmt.indented( + 'fn numbered_predicate(&self, p: usize) -> bool {', '}'): + fmt.line( + 'self.bytes[{} + p / 8] & (1 << (p % 8)) != 0' + .format(sgrp.boolean_offset)) for setting in sgrp.settings: gen_getter(setting, sgrp, fmt) for pred in sgrp.named_predicates: diff --git a/lib/cretonne/src/isa/arm32/mod.rs b/lib/cretonne/src/isa/arm32/mod.rs index 769adc376d..5675d19d7a 100644 --- a/lib/cretonne/src/isa/arm32/mod.rs +++ b/lib/cretonne/src/isa/arm32/mod.rs @@ -61,11 +61,11 @@ impl TargetIsa for Isa { enc_tables::INFO.clone() } - fn legal_encodings<'a, 'b>(&'a self, - _dfg: &'b ir::DataFlowGraph, - inst: &'b ir::InstructionData, - ctrl_typevar: ir::Type) - -> Result, Legalize> { + fn legal_encodings<'a>(&'a self, + _dfg: &'a ir::DataFlowGraph, + inst: &'a ir::InstructionData, + ctrl_typevar: ir::Type) + -> Result, Legalize> { lookup_enclist(ctrl_typevar, inst.opcode(), self.cpumode, @@ -75,7 +75,7 @@ impl TargetIsa for Isa { &enc_tables::ENCLISTS[..], inst, enc_tables::check_instp, - self.isa_flags.predicate_bytes())) + self.isa_flags.predicate_view())) }) } diff --git a/lib/cretonne/src/isa/arm64/mod.rs b/lib/cretonne/src/isa/arm64/mod.rs index a1b0ac2478..e9aea5aacf 100644 --- a/lib/cretonne/src/isa/arm64/mod.rs +++ b/lib/cretonne/src/isa/arm64/mod.rs @@ -54,11 +54,11 @@ impl TargetIsa for Isa { enc_tables::INFO.clone() } - fn legal_encodings<'a, 'b>(&'a self, - _dfg: &'b ir::DataFlowGraph, - inst: &'b ir::InstructionData, - ctrl_typevar: ir::Type) - -> Result, Legalize> { + fn legal_encodings<'a>(&'a self, + _dfg: &'a ir::DataFlowGraph, + inst: &'a ir::InstructionData, + ctrl_typevar: ir::Type) + -> Result, Legalize> { lookup_enclist(ctrl_typevar, inst.opcode(), &enc_tables::LEVEL1_A64[..], @@ -68,7 +68,7 @@ impl TargetIsa for Isa { &enc_tables::ENCLISTS[..], inst, enc_tables::check_instp, - self.isa_flags.predicate_bytes())) + self.isa_flags.predicate_view())) }) } diff --git a/lib/cretonne/src/isa/enc_tables.rs b/lib/cretonne/src/isa/enc_tables.rs index b53e80036e..1c6645002e 100644 --- a/lib/cretonne/src/isa/enc_tables.rs +++ b/lib/cretonne/src/isa/enc_tables.rs @@ -2,9 +2,11 @@ //! //! This module contains types and functions for working with the encoding tables generated by //! `lib/cretonne/meta/gen_encoding.py`. + +use constant_hash::{Table, probe}; use ir::{Type, Opcode, InstructionData}; use isa::{Encoding, Legalize}; -use constant_hash::{Table, probe}; +use settings::PredicateView; use std::ops::Range; /// Level 1 hash table entry. @@ -127,15 +129,15 @@ const CODE_ALWAYS: EncListEntry = PRED_MASK; const CODE_FAIL: EncListEntry = 0xffff; /// An iterator over legal encodings for the instruction. -pub struct Encodings<'a, 'b> { +pub struct Encodings<'a> { offset: usize, - enclist: &'b [EncListEntry], - inst: &'b InstructionData, + enclist: &'static [EncListEntry], + inst: &'a InstructionData, instp: fn(&InstructionData, EncListEntry) -> bool, - isa_predicate_bytes: &'a [u8], + isa_predicates: PredicateView<'a>, } -impl<'a, 'b> Encodings<'a, 'b> { +impl<'a> Encodings<'a> { /// Creates a new instance of `Encodings`. /// /// # Parameters @@ -151,29 +153,25 @@ impl<'a, 'b> Encodings<'a, 'b> { /// encoding lists are laid out such that first call to `next` returns valid entry in the list /// or `None`. pub fn new(offset: usize, - enclist: &'b [EncListEntry], - inst: &'b InstructionData, + enclist: &'static [EncListEntry], + inst: &'a InstructionData, instp: fn(&InstructionData, EncListEntry) -> bool, - isa_predicate_bytes: &'a [u8]) + isa_predicates: PredicateView<'a>) -> Self { Encodings { offset, enclist, inst, instp, - isa_predicate_bytes, + isa_predicates, } } } -impl<'a, 'b> Iterator for Encodings<'a, 'b> { +impl<'a> Iterator for Encodings<'a> { type Item = Encoding; fn next(&mut self) -> Option { - fn numbered_predicate(bytes: &[u8], p: usize) -> bool { - bytes[p / 8] & (1 << (p % 8)) != 0 - } - while self.enclist[self.offset] != CODE_FAIL { let pred = self.enclist[self.offset]; if pred <= CODE_ALWAYS { @@ -189,7 +187,7 @@ impl<'a, 'b> Iterator for Encodings<'a, 'b> { } else { // This is an ISA predicate entry. self.offset += 1; - if !numbered_predicate(self.isa_predicate_bytes, (pred & PRED_MASK) as usize) { + if !self.isa_predicates.test((pred & PRED_MASK) as usize) { // ISA predicate failed, skip the next N entries. self.offset += 3 * (pred >> PRED_BITS) as usize; } diff --git a/lib/cretonne/src/isa/intel/mod.rs b/lib/cretonne/src/isa/intel/mod.rs index 93a2ed2c09..35d339a740 100644 --- a/lib/cretonne/src/isa/intel/mod.rs +++ b/lib/cretonne/src/isa/intel/mod.rs @@ -61,11 +61,11 @@ impl TargetIsa for Isa { enc_tables::INFO.clone() } - fn legal_encodings<'a, 'b>(&'a self, - _dfg: &'b ir::DataFlowGraph, - inst: &'b ir::InstructionData, - ctrl_typevar: ir::Type) - -> Result, Legalize> { + fn legal_encodings<'a>(&'a self, + _dfg: &'a ir::DataFlowGraph, + inst: &'a ir::InstructionData, + ctrl_typevar: ir::Type) + -> Result, Legalize> { lookup_enclist(ctrl_typevar, inst.opcode(), self.cpumode, @@ -75,7 +75,7 @@ impl TargetIsa for Isa { &enc_tables::ENCLISTS[..], inst, enc_tables::check_instp, - self.isa_flags.predicate_bytes())) + self.isa_flags.predicate_view())) }) } diff --git a/lib/cretonne/src/isa/mod.rs b/lib/cretonne/src/isa/mod.rs index 6665de5f42..100c901ec0 100644 --- a/lib/cretonne/src/isa/mod.rs +++ b/lib/cretonne/src/isa/mod.rs @@ -138,11 +138,11 @@ pub trait TargetIsa { fn register_info(&self) -> RegInfo; /// Returns an iterartor over legal encodings for the instruction. - fn legal_encodings<'a, 'b>(&'a self, - dfg: &'b ir::DataFlowGraph, - inst: &'b ir::InstructionData, - ctrl_typevar: ir::Type) - -> Result, Legalize>; + fn legal_encodings<'a>(&'a self, + dfg: &'a ir::DataFlowGraph, + inst: &'a ir::InstructionData, + ctrl_typevar: ir::Type) + -> Result, Legalize>; /// Encode an instruction after determining it is legal. /// diff --git a/lib/cretonne/src/isa/riscv/mod.rs b/lib/cretonne/src/isa/riscv/mod.rs index b70f6185b8..869ea4c9cb 100644 --- a/lib/cretonne/src/isa/riscv/mod.rs +++ b/lib/cretonne/src/isa/riscv/mod.rs @@ -61,11 +61,11 @@ impl TargetIsa for Isa { enc_tables::INFO.clone() } - fn legal_encodings<'a, 'b>(&'a self, - _dfg: &'b ir::DataFlowGraph, - inst: &'b ir::InstructionData, - ctrl_typevar: ir::Type) - -> Result, Legalize> { + fn legal_encodings<'a>(&'a self, + _dfg: &'a ir::DataFlowGraph, + inst: &'a ir::InstructionData, + ctrl_typevar: ir::Type) + -> Result, Legalize> { lookup_enclist(ctrl_typevar, inst.opcode(), self.cpumode, @@ -75,7 +75,7 @@ impl TargetIsa for Isa { &enc_tables::ENCLISTS[..], inst, enc_tables::check_instp, - self.isa_flags.predicate_bytes())) + self.isa_flags.predicate_view())) }) } diff --git a/lib/cretonne/src/settings.rs b/lib/cretonne/src/settings.rs index be5140ef34..660c833a4a 100644 --- a/lib/cretonne/src/settings.rs +++ b/lib/cretonne/src/settings.rs @@ -162,6 +162,28 @@ pub enum Error { /// A result returned when changing a setting. pub type Result = result::Result; +/// 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)] +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]) -> PredicateView { + 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