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