Implement an iterator over encodings (#96)
* Implement an iterator over encodings * Implement TargetIsa::legal_encodings * Exclude non-boolean settings of isa flags bytes * Address flake8 long line error
This commit is contained in:
committed by
Jakob Stoklund Olesen
parent
342121aba0
commit
1a480a2578
@@ -87,6 +87,10 @@ def gen_getters(sgrp, fmt):
|
|||||||
"""
|
"""
|
||||||
fmt.doc_comment("User-defined settings.")
|
fmt.doc_comment("User-defined settings.")
|
||||||
with fmt.indented('impl Flags {', '}'):
|
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('Dynamic numbered predicate getter.')
|
||||||
with fmt.indented(
|
with fmt.indented(
|
||||||
'pub fn numbered_predicate(&self, p: usize) -> bool {', '}'):
|
'pub fn numbered_predicate(&self, p: usize) -> bool {', '}'):
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ mod registers;
|
|||||||
|
|
||||||
use binemit::CodeSink;
|
use binemit::CodeSink;
|
||||||
use super::super::settings as shared_settings;
|
use super::super::settings as shared_settings;
|
||||||
use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, general_encoding};
|
use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, Encodings};
|
||||||
use isa::Builder as IsaBuilder;
|
use isa::Builder as IsaBuilder;
|
||||||
use isa::{TargetIsa, RegInfo, RegClass, EncInfo, Encoding, Legalize};
|
use isa::{TargetIsa, RegInfo, RegClass, EncInfo, Legalize};
|
||||||
use ir;
|
use ir;
|
||||||
use regalloc;
|
use regalloc;
|
||||||
|
|
||||||
@@ -61,21 +61,21 @@ impl TargetIsa for Isa {
|
|||||||
enc_tables::INFO.clone()
|
enc_tables::INFO.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode(&self,
|
fn legal_encodings<'a, 'b>(&'a self,
|
||||||
_dfg: &ir::DataFlowGraph,
|
_dfg: &'b ir::DataFlowGraph,
|
||||||
inst: &ir::InstructionData,
|
inst: &'b ir::InstructionData,
|
||||||
ctrl_typevar: ir::Type)
|
ctrl_typevar: ir::Type)
|
||||||
-> Result<Encoding, Legalize> {
|
-> Result<Encodings<'a, 'b>, Legalize> {
|
||||||
lookup_enclist(ctrl_typevar,
|
lookup_enclist(ctrl_typevar,
|
||||||
inst.opcode(),
|
inst.opcode(),
|
||||||
self.cpumode,
|
self.cpumode,
|
||||||
&enc_tables::LEVEL2[..])
|
&enc_tables::LEVEL2[..])
|
||||||
.and_then(|enclist_offset| {
|
.and_then(|enclist_offset| {
|
||||||
general_encoding(enclist_offset,
|
Ok(Encodings::new(enclist_offset,
|
||||||
&enc_tables::ENCLISTS[..],
|
&enc_tables::ENCLISTS[..],
|
||||||
|instp| enc_tables::check_instp(inst, instp),
|
inst,
|
||||||
|isap| self.isa_flags.numbered_predicate(isap as usize))
|
enc_tables::check_instp,
|
||||||
.ok_or(Legalize::Expand)
|
self.isa_flags.predicate_bytes()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ mod registers;
|
|||||||
|
|
||||||
use binemit::CodeSink;
|
use binemit::CodeSink;
|
||||||
use super::super::settings as shared_settings;
|
use super::super::settings as shared_settings;
|
||||||
use isa::enc_tables::{lookup_enclist, general_encoding};
|
use isa::enc_tables::{lookup_enclist, Encodings};
|
||||||
use isa::Builder as IsaBuilder;
|
use isa::Builder as IsaBuilder;
|
||||||
use isa::{TargetIsa, RegInfo, RegClass, EncInfo, Encoding, Legalize};
|
use isa::{TargetIsa, RegInfo, RegClass, EncInfo, Legalize};
|
||||||
use ir;
|
use ir;
|
||||||
use regalloc;
|
use regalloc;
|
||||||
|
|
||||||
@@ -54,21 +54,21 @@ impl TargetIsa for Isa {
|
|||||||
enc_tables::INFO.clone()
|
enc_tables::INFO.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode(&self,
|
fn legal_encodings<'a, 'b>(&'a self,
|
||||||
_dfg: &ir::DataFlowGraph,
|
_dfg: &'b ir::DataFlowGraph,
|
||||||
inst: &ir::InstructionData,
|
inst: &'b ir::InstructionData,
|
||||||
ctrl_typevar: ir::Type)
|
ctrl_typevar: ir::Type)
|
||||||
-> Result<Encoding, Legalize> {
|
-> Result<Encodings<'a, 'b>, Legalize> {
|
||||||
lookup_enclist(ctrl_typevar,
|
lookup_enclist(ctrl_typevar,
|
||||||
inst.opcode(),
|
inst.opcode(),
|
||||||
&enc_tables::LEVEL1_A64[..],
|
&enc_tables::LEVEL1_A64[..],
|
||||||
&enc_tables::LEVEL2[..])
|
&enc_tables::LEVEL2[..])
|
||||||
.and_then(|enclist_offset| {
|
.and_then(|enclist_offset| {
|
||||||
general_encoding(enclist_offset,
|
Ok(Encodings::new(enclist_offset,
|
||||||
&enc_tables::ENCLISTS[..],
|
&enc_tables::ENCLISTS[..],
|
||||||
|instp| enc_tables::check_instp(inst, instp),
|
inst,
|
||||||
|isap| self.isa_flags.numbered_predicate(isap as usize))
|
enc_tables::check_instp,
|
||||||
.ok_or(Legalize::Expand)
|
self.isa_flags.predicate_bytes()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
//!
|
//!
|
||||||
//! This module contains types and functions for working with the encoding tables generated by
|
//! This module contains types and functions for working with the encoding tables generated by
|
||||||
//! `lib/cretonne/meta/gen_encoding.py`.
|
//! `lib/cretonne/meta/gen_encoding.py`.
|
||||||
use ir::{Type, Opcode};
|
use ir::{Type, Opcode, InstructionData};
|
||||||
use isa::{Encoding, Legalize};
|
use isa::{Encoding, Legalize};
|
||||||
use constant_hash::{Table, probe};
|
use constant_hash::{Table, probe};
|
||||||
|
|
||||||
@@ -114,43 +114,75 @@ const CODE_ALWAYS: EncListEntry = PRED_MASK;
|
|||||||
/// The encoding list terminator.
|
/// The encoding list terminator.
|
||||||
const CODE_FAIL: EncListEntry = 0xffff;
|
const CODE_FAIL: EncListEntry = 0xffff;
|
||||||
|
|
||||||
/// Find the first applicable general encoding of `inst`.
|
/// An iterator over legal encodings for the instruction.
|
||||||
///
|
pub struct Encodings<'a, 'b> {
|
||||||
/// Given an encoding list offset as returned by `lookup_enclist` above, search the encoding list
|
offset: usize,
|
||||||
/// for the most first encoding that applies to `inst`. The encoding lists are laid out such that
|
enclist: &'b [EncListEntry],
|
||||||
/// this is the first valid entry in the list.
|
inst: &'b InstructionData,
|
||||||
///
|
instp: fn(&InstructionData, EncListEntry) -> bool,
|
||||||
/// This function takes two closures that are used to evaluate predicates:
|
isa_predicate_bytes: &'a [u8],
|
||||||
/// - `instp` is passed an instruction predicate number to be evaluated on the current instruction.
|
}
|
||||||
/// - `isap` is passed an ISA predicate number to evaluate.
|
|
||||||
///
|
impl<'a, 'b> Encodings<'a, 'b> {
|
||||||
/// Returns the corresponding encoding, or `None` if no list entries are satisfied by `inst`.
|
/// Creates a new instance of `Encodings`.
|
||||||
pub fn general_encoding<InstP, IsaP>(offset: usize,
|
///
|
||||||
enclist: &[EncListEntry],
|
/// # Parameters
|
||||||
instp: InstP,
|
///
|
||||||
isap: IsaP)
|
/// - `offset` an offset into encoding list returned by `lookup_enclist` function.
|
||||||
-> Option<Encoding>
|
/// - `inst` the current instruction.
|
||||||
where InstP: Fn(EncListEntry) -> bool,
|
/// - `enclist` a list of encoding entries.
|
||||||
IsaP: Fn(EncListEntry) -> bool
|
/// - `instp` an instruction predicate number to be evaluated on the current instruction.
|
||||||
{
|
/// - `isa_predicate_bytes` an ISA flags as a slice of bytes to evaluate an ISA predicate number
|
||||||
let mut pos = offset;
|
/// on the current instruction.
|
||||||
while enclist[pos] != CODE_FAIL {
|
///
|
||||||
let pred = enclist[pos];
|
/// This iterator provides search for encodings that applies to the given instruction. The
|
||||||
if pred <= CODE_ALWAYS {
|
/// encoding lists are laid out such that first call to `next` returns valid entry in the list
|
||||||
// This is an instruction predicate followed by recipe and encbits entries.
|
/// or `None`.
|
||||||
if pred == CODE_ALWAYS || instp(pred) {
|
pub fn new(offset: usize,
|
||||||
return Some(Encoding::new(enclist[pos + 1], enclist[pos + 2]));
|
enclist: &'b [EncListEntry],
|
||||||
}
|
inst: &'b InstructionData,
|
||||||
pos += 3;
|
instp: fn(&InstructionData, EncListEntry) -> bool,
|
||||||
} else {
|
isa_predicate_bytes: &'a [u8])
|
||||||
// This is an ISA predicate entry.
|
-> Self {
|
||||||
pos += 1;
|
Encodings {
|
||||||
if !isap(pred & PRED_MASK) {
|
offset,
|
||||||
// ISA predicate failed, skip the next N entries.
|
enclist,
|
||||||
pos += 3 * (pred >> PRED_BITS) as usize;
|
inst,
|
||||||
|
instp,
|
||||||
|
isa_predicate_bytes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b> Iterator for Encodings<'a, 'b> {
|
||||||
|
type Item = Encoding;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Encoding> {
|
||||||
|
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 {
|
||||||
|
// This is an instruction predicate followed by recipe and encbits entries.
|
||||||
|
if pred == CODE_ALWAYS || (self.instp)(self.inst, pred) {
|
||||||
|
let encoding = Encoding::new(self.enclist[self.offset + 1],
|
||||||
|
self.enclist[self.offset + 2]);
|
||||||
|
self.offset += 3;
|
||||||
|
return Some(encoding);
|
||||||
|
} else {
|
||||||
|
self.offset += 3;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// This is an ISA predicate entry.
|
||||||
|
self.offset += 1;
|
||||||
|
if !numbered_predicate(self.isa_predicate_bytes, (pred & PRED_MASK) as usize) {
|
||||||
|
// ISA predicate failed, skip the next N entries.
|
||||||
|
self.offset += 3 * (pred >> PRED_BITS) as usize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
None
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ mod registers;
|
|||||||
|
|
||||||
use binemit::CodeSink;
|
use binemit::CodeSink;
|
||||||
use super::super::settings as shared_settings;
|
use super::super::settings as shared_settings;
|
||||||
use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, general_encoding};
|
use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, Encodings};
|
||||||
use isa::Builder as IsaBuilder;
|
use isa::Builder as IsaBuilder;
|
||||||
use isa::{TargetIsa, RegInfo, RegClass, EncInfo, Encoding, Legalize};
|
use isa::{TargetIsa, RegInfo, RegClass, EncInfo, Legalize};
|
||||||
use ir;
|
use ir;
|
||||||
use regalloc;
|
use regalloc;
|
||||||
|
|
||||||
@@ -61,21 +61,21 @@ impl TargetIsa for Isa {
|
|||||||
enc_tables::INFO.clone()
|
enc_tables::INFO.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode(&self,
|
fn legal_encodings<'a, 'b>(&'a self,
|
||||||
_dfg: &ir::DataFlowGraph,
|
_dfg: &'b ir::DataFlowGraph,
|
||||||
inst: &ir::InstructionData,
|
inst: &'b ir::InstructionData,
|
||||||
ctrl_typevar: ir::Type)
|
ctrl_typevar: ir::Type)
|
||||||
-> Result<Encoding, Legalize> {
|
-> Result<Encodings<'a, 'b>, Legalize> {
|
||||||
lookup_enclist(ctrl_typevar,
|
lookup_enclist(ctrl_typevar,
|
||||||
inst.opcode(),
|
inst.opcode(),
|
||||||
self.cpumode,
|
self.cpumode,
|
||||||
&enc_tables::LEVEL2[..])
|
&enc_tables::LEVEL2[..])
|
||||||
.and_then(|enclist_offset| {
|
.and_then(|enclist_offset| {
|
||||||
general_encoding(enclist_offset,
|
Ok(Encodings::new(enclist_offset,
|
||||||
&enc_tables::ENCLISTS[..],
|
&enc_tables::ENCLISTS[..],
|
||||||
|instp| enc_tables::check_instp(inst, instp),
|
inst,
|
||||||
|isap| self.isa_flags.numbered_predicate(isap as usize))
|
enc_tables::check_instp,
|
||||||
.ok_or(Legalize::Expand)
|
self.isa_flags.predicate_bytes()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ use binemit::CodeSink;
|
|||||||
use settings;
|
use settings;
|
||||||
use ir;
|
use ir;
|
||||||
use regalloc;
|
use regalloc;
|
||||||
|
use isa::enc_tables::Encodings;
|
||||||
|
|
||||||
pub mod riscv;
|
pub mod riscv;
|
||||||
pub mod intel;
|
pub mod intel;
|
||||||
@@ -136,17 +137,27 @@ pub trait TargetIsa {
|
|||||||
/// Get a data structure describing the registers in this ISA.
|
/// Get a data structure describing the registers in this ISA.
|
||||||
fn register_info(&self) -> RegInfo;
|
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<Encodings<'a, 'b>, Legalize>;
|
||||||
|
|
||||||
/// Encode an instruction after determining it is legal.
|
/// Encode an instruction after determining it is legal.
|
||||||
///
|
///
|
||||||
/// If `inst` can legally be encoded in this ISA, produce the corresponding `Encoding` object.
|
/// If `inst` can legally be encoded in this ISA, produce the corresponding `Encoding` object.
|
||||||
/// Otherwise, return `None`.
|
/// Otherwise, return `Legalize` action.
|
||||||
///
|
///
|
||||||
/// This is also the main entry point for determining if an instruction is legal.
|
/// This is also the main entry point for determining if an instruction is legal.
|
||||||
fn encode(&self,
|
fn encode(&self,
|
||||||
dfg: &ir::DataFlowGraph,
|
dfg: &ir::DataFlowGraph,
|
||||||
inst: &ir::InstructionData,
|
inst: &ir::InstructionData,
|
||||||
ctrl_typevar: ir::Type)
|
ctrl_typevar: ir::Type)
|
||||||
-> Result<Encoding, Legalize>;
|
-> Result<Encoding, Legalize> {
|
||||||
|
self.legal_encodings(dfg, inst, ctrl_typevar)
|
||||||
|
.and_then(|mut iter| iter.next().ok_or(Legalize::Expand))
|
||||||
|
}
|
||||||
|
|
||||||
/// Get a data structure describing the instruction encodings in this ISA.
|
/// Get a data structure describing the instruction encodings in this ISA.
|
||||||
fn encoding_info(&self) -> EncInfo;
|
fn encoding_info(&self) -> EncInfo;
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ mod registers;
|
|||||||
|
|
||||||
use super::super::settings as shared_settings;
|
use super::super::settings as shared_settings;
|
||||||
use binemit::CodeSink;
|
use binemit::CodeSink;
|
||||||
use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, general_encoding};
|
use isa::enc_tables::{self as shared_enc_tables, lookup_enclist, Encodings};
|
||||||
use isa::Builder as IsaBuilder;
|
use isa::Builder as IsaBuilder;
|
||||||
use isa::{TargetIsa, RegInfo, RegClass, EncInfo, Encoding, Legalize};
|
use isa::{TargetIsa, RegInfo, RegClass, EncInfo, Legalize};
|
||||||
use ir;
|
use ir;
|
||||||
use regalloc;
|
use regalloc;
|
||||||
|
|
||||||
@@ -61,21 +61,21 @@ impl TargetIsa for Isa {
|
|||||||
enc_tables::INFO.clone()
|
enc_tables::INFO.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode(&self,
|
fn legal_encodings<'a, 'b>(&'a self,
|
||||||
_dfg: &ir::DataFlowGraph,
|
_dfg: &'b ir::DataFlowGraph,
|
||||||
inst: &ir::InstructionData,
|
inst: &'b ir::InstructionData,
|
||||||
ctrl_typevar: ir::Type)
|
ctrl_typevar: ir::Type)
|
||||||
-> Result<Encoding, Legalize> {
|
-> Result<Encodings<'a, 'b>, Legalize> {
|
||||||
lookup_enclist(ctrl_typevar,
|
lookup_enclist(ctrl_typevar,
|
||||||
inst.opcode(),
|
inst.opcode(),
|
||||||
self.cpumode,
|
self.cpumode,
|
||||||
&enc_tables::LEVEL2[..])
|
&enc_tables::LEVEL2[..])
|
||||||
.and_then(|enclist_offset| {
|
.and_then(|enclist_offset| {
|
||||||
general_encoding(enclist_offset,
|
Ok(Encodings::new(enclist_offset,
|
||||||
&enc_tables::ENCLISTS[..],
|
&enc_tables::ENCLISTS[..],
|
||||||
|instp| enc_tables::check_instp(inst, instp),
|
inst,
|
||||||
|isap| self.isa_flags.numbered_predicate(isap as usize))
|
enc_tables::check_instp,
|
||||||
.ok_or(Legalize::Expand)
|
self.isa_flags.predicate_bytes()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user