Generate an INST_PREDICATES table for each ISA.
Instead of generating a single `check_instp()` function, create an array of individual function pointers for checking instruction predicates. This makes explicit the jump table in the old check_instp() method and it gives us a way of determining the number of instruction predicates that exists.
This commit is contained in:
@@ -101,36 +101,27 @@ def emit_instp(instp, fmt):
|
|||||||
fmt.line('return {};'.format(instp.rust_predicate(0)))
|
fmt.line('return {};'.format(instp.rust_predicate(0)))
|
||||||
|
|
||||||
|
|
||||||
def emit_instps(instps, fmt):
|
def emit_inst_predicates(instps, fmt):
|
||||||
# type: (Sequence[PredNode], srcgen.Formatter) -> None
|
# type: (Sequence[PredNode], srcgen.Formatter) -> None
|
||||||
"""
|
"""
|
||||||
Emit a function for matching instruction predicates.
|
Emit private functions for matching instruction predicates as well as a
|
||||||
|
static `INST_PREDICATES` array indexed by predicate number.
|
||||||
"""
|
"""
|
||||||
|
for instp in instps:
|
||||||
if not instps:
|
name = 'inst_predicate_{}'.format(instp.number)
|
||||||
# If the ISA has no predicates, just emit a stub.
|
|
||||||
with fmt.indented(
|
with fmt.indented(
|
||||||
'pub fn check_instp(_: &InstructionData, _: u16) ' +
|
'fn {}(inst: &InstructionData) -> bool {{'
|
||||||
'-> bool {', '}'):
|
.format(name),
|
||||||
fmt.line('unimplemented!()')
|
'}'):
|
||||||
return
|
emit_instp(instp, fmt)
|
||||||
|
fmt.line('unreachable!();')
|
||||||
|
|
||||||
|
# Generate the static table.
|
||||||
with fmt.indented(
|
with fmt.indented(
|
||||||
'pub fn check_instp(inst: &InstructionData, instp_idx: u16) ' +
|
'pub static INST_PREDICATES: [InstPredicate; {}] = ['
|
||||||
'-> bool {', '}'):
|
.format(len(instps)), '];'):
|
||||||
# The matches emitted by `emit_instp` need this.
|
for instp in instps:
|
||||||
fmt.line('use ir::instructions::InstructionFormat;')
|
fmt.format('inst_predicate_{},', instp.number)
|
||||||
with fmt.indented('match instp_idx {', '}'):
|
|
||||||
for instp in instps:
|
|
||||||
with fmt.indented('{} => {{'.format(instp.number), '}'):
|
|
||||||
emit_instp(instp, fmt)
|
|
||||||
fmt.line('_ => panic!("Invalid instruction predicate")')
|
|
||||||
|
|
||||||
# The match cases will fall through if the instruction format is wrong.
|
|
||||||
fmt.line('panic!("Bad format {:?}/{} for instp {}",')
|
|
||||||
fmt.line(' InstructionFormat::from(inst),')
|
|
||||||
fmt.line(' inst.opcode(),')
|
|
||||||
fmt.line(' instp_idx);')
|
|
||||||
|
|
||||||
|
|
||||||
def emit_recipe_predicates(recipes, fmt):
|
def emit_recipe_predicates(recipes, fmt):
|
||||||
@@ -658,8 +649,8 @@ def gen_isa(isa, fmt):
|
|||||||
# Make the `RECIPE_PREDICATES` table.
|
# Make the `RECIPE_PREDICATES` table.
|
||||||
emit_recipe_predicates(isa.all_recipes, fmt)
|
emit_recipe_predicates(isa.all_recipes, fmt)
|
||||||
|
|
||||||
# Generate the check_instp() function..
|
# Make the `INST_PREDICATES` table.
|
||||||
emit_instps(isa.all_instps, fmt)
|
emit_inst_predicates(isa.all_instps, fmt)
|
||||||
|
|
||||||
# Level1 tables, one per CPU mode
|
# Level1 tables, one per CPU mode
|
||||||
level1_tables = dict()
|
level1_tables = dict()
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
//! Encoding tables for ARM32 ISA.
|
//! Encoding tables for ARM32 ISA.
|
||||||
|
|
||||||
use ir::InstructionData;
|
|
||||||
use ir::types;
|
use ir::types;
|
||||||
use isa::EncInfo;
|
use isa::EncInfo;
|
||||||
use isa::constraints::*;
|
use isa::constraints::*;
|
||||||
|
|||||||
@@ -74,8 +74,8 @@ impl TargetIsa for Isa {
|
|||||||
Ok(Encodings::new(enclist_offset,
|
Ok(Encodings::new(enclist_offset,
|
||||||
&enc_tables::ENCLISTS[..],
|
&enc_tables::ENCLISTS[..],
|
||||||
&enc_tables::RECIPE_PREDICATES[..],
|
&enc_tables::RECIPE_PREDICATES[..],
|
||||||
|
&enc_tables::INST_PREDICATES[..],
|
||||||
inst,
|
inst,
|
||||||
enc_tables::check_instp,
|
|
||||||
self.isa_flags.predicate_view()))
|
self.isa_flags.predicate_view()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
//! Encoding tables for ARM64 ISA.
|
//! Encoding tables for ARM64 ISA.
|
||||||
|
|
||||||
use ir::InstructionData;
|
|
||||||
use ir::types;
|
use ir::types;
|
||||||
use isa::EncInfo;
|
use isa::EncInfo;
|
||||||
use isa::constraints::*;
|
use isa::constraints::*;
|
||||||
|
|||||||
@@ -67,8 +67,8 @@ impl TargetIsa for Isa {
|
|||||||
Ok(Encodings::new(enclist_offset,
|
Ok(Encodings::new(enclist_offset,
|
||||||
&enc_tables::ENCLISTS[..],
|
&enc_tables::ENCLISTS[..],
|
||||||
&enc_tables::RECIPE_PREDICATES[..],
|
&enc_tables::RECIPE_PREDICATES[..],
|
||||||
|
&enc_tables::INST_PREDICATES[..],
|
||||||
inst,
|
inst,
|
||||||
enc_tables::check_instp,
|
|
||||||
self.isa_flags.predicate_view()))
|
self.isa_flags.predicate_view()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,12 @@ use std::ops::Range;
|
|||||||
/// A None predicate is always satisfied.
|
/// A None predicate is always satisfied.
|
||||||
pub type RecipePredicate = Option<fn(PredicateView, &InstructionData) -> bool>;
|
pub type RecipePredicate = Option<fn(PredicateView, &InstructionData) -> bool>;
|
||||||
|
|
||||||
|
/// An instruction predicate.
|
||||||
|
///
|
||||||
|
/// This is a predicate function that needs to be tested in addition to the recipe predicate. It
|
||||||
|
/// can't depend on ISA settings.
|
||||||
|
pub type InstPredicate = fn(&InstructionData) -> bool;
|
||||||
|
|
||||||
/// Legalization action to perform when no encoding can be found for an instruction.
|
/// Legalization action to perform when no encoding can be found for an instruction.
|
||||||
///
|
///
|
||||||
/// This is an index into an ISA-specific table of legalization actions.
|
/// This is an index into an ISA-specific table of legalization actions.
|
||||||
@@ -152,9 +158,9 @@ pub struct Encodings<'a> {
|
|||||||
offset: usize,
|
offset: usize,
|
||||||
enclist: &'static [EncListEntry],
|
enclist: &'static [EncListEntry],
|
||||||
inst: &'a InstructionData,
|
inst: &'a InstructionData,
|
||||||
instp: fn(&InstructionData, EncListEntry) -> bool,
|
|
||||||
isa_predicates: PredicateView<'a>,
|
isa_predicates: PredicateView<'a>,
|
||||||
recipe_predicates: &'static [RecipePredicate],
|
recipe_predicates: &'static [RecipePredicate],
|
||||||
|
inst_predicates: &'static [InstPredicate],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Encodings<'a> {
|
impl<'a> Encodings<'a> {
|
||||||
@@ -176,17 +182,17 @@ impl<'a> Encodings<'a> {
|
|||||||
pub fn new(offset: usize,
|
pub fn new(offset: usize,
|
||||||
enclist: &'static [EncListEntry],
|
enclist: &'static [EncListEntry],
|
||||||
recipe_predicates: &'static [RecipePredicate],
|
recipe_predicates: &'static [RecipePredicate],
|
||||||
|
inst_predicates: &'static [InstPredicate],
|
||||||
inst: &'a InstructionData,
|
inst: &'a InstructionData,
|
||||||
instp: fn(&InstructionData, EncListEntry) -> bool,
|
|
||||||
isa_predicates: PredicateView<'a>)
|
isa_predicates: PredicateView<'a>)
|
||||||
-> Self {
|
-> Self {
|
||||||
Encodings {
|
Encodings {
|
||||||
offset,
|
offset,
|
||||||
enclist,
|
enclist,
|
||||||
inst,
|
inst,
|
||||||
instp,
|
|
||||||
isa_predicates,
|
isa_predicates,
|
||||||
recipe_predicates,
|
recipe_predicates,
|
||||||
|
inst_predicates,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,7 +214,11 @@ impl<'a> Iterator for Encodings<'a> {
|
|||||||
if pred <= CODE_ALWAYS {
|
if pred <= CODE_ALWAYS {
|
||||||
// This is an instruction predicate followed by recipe and encbits entries.
|
// This is an instruction predicate followed by recipe and encbits entries.
|
||||||
self.offset += 3;
|
self.offset += 3;
|
||||||
if pred == CODE_ALWAYS || (self.instp)(self.inst, pred) {
|
let satisfied = match self.inst_predicates.get(pred as usize) {
|
||||||
|
Some(p) => p(self.inst),
|
||||||
|
None => true,
|
||||||
|
};
|
||||||
|
if satisfied {
|
||||||
let recipe = self.enclist[self.offset - 2];
|
let recipe = self.enclist[self.offset - 2];
|
||||||
if self.check_recipe(recipe) {
|
if self.check_recipe(recipe) {
|
||||||
let encoding = Encoding::new(recipe, self.enclist[self.offset - 1]);
|
let encoding = Encoding::new(recipe, self.enclist[self.offset - 1]);
|
||||||
|
|||||||
@@ -74,8 +74,8 @@ impl TargetIsa for Isa {
|
|||||||
Ok(Encodings::new(enclist_offset,
|
Ok(Encodings::new(enclist_offset,
|
||||||
&enc_tables::ENCLISTS[..],
|
&enc_tables::ENCLISTS[..],
|
||||||
&enc_tables::RECIPE_PREDICATES[..],
|
&enc_tables::RECIPE_PREDICATES[..],
|
||||||
|
&enc_tables::INST_PREDICATES[..],
|
||||||
inst,
|
inst,
|
||||||
enc_tables::check_instp,
|
|
||||||
self.isa_flags.predicate_view()))
|
self.isa_flags.predicate_view()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,8 +74,8 @@ impl TargetIsa for Isa {
|
|||||||
Ok(Encodings::new(enclist_offset,
|
Ok(Encodings::new(enclist_offset,
|
||||||
&enc_tables::ENCLISTS[..],
|
&enc_tables::ENCLISTS[..],
|
||||||
&enc_tables::RECIPE_PREDICATES[..],
|
&enc_tables::RECIPE_PREDICATES[..],
|
||||||
|
&enc_tables::INST_PREDICATES[..],
|
||||||
inst,
|
inst,
|
||||||
enc_tables::check_instp,
|
|
||||||
self.isa_flags.predicate_view()))
|
self.isa_flags.predicate_view()))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user