ISLE: Add the overlap_errors pragma (#4981)
* Add the overlap_errors pragma to ISLE * Enable overlap errors in the x64 backend
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
;; x86-64 instruction selection and CLIF-to-MachInst lowering.
|
||||
|
||||
;; Enable overlap checking for the x64 backend
|
||||
(pragma overlap_errors)
|
||||
|
||||
;; The main lowering constructor term: takes a clif `Inst` and returns the
|
||||
;; register(s) within which the lowered instruction's result values live.
|
||||
(decl lower (Inst) InstOutput)
|
||||
|
||||
@@ -19,6 +19,5 @@ tempfile = "3"
|
||||
[features]
|
||||
default = []
|
||||
|
||||
overlap-errors = []
|
||||
logging = ["log"]
|
||||
miette-errors = ["miette"]
|
||||
|
||||
@@ -17,6 +17,7 @@ pub struct Defs {
|
||||
/// One toplevel form in an ISLE file.
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub enum Def {
|
||||
Pragma(Pragma),
|
||||
Type(Type),
|
||||
Rule(Rule),
|
||||
Extractor(Extractor),
|
||||
@@ -29,6 +30,13 @@ pub enum Def {
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct Ident(pub String, pub Pos);
|
||||
|
||||
/// Pragmas parsed with the `(pragma <ident>)` syntax.
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub enum Pragma {
|
||||
/// Enable overlap errors in the source.
|
||||
OverlapErrors,
|
||||
}
|
||||
|
||||
/// A declaration of a type.
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Type {
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::sema::{self, Rule, RuleId, Sym, TermEnv, TermId, TermKind, TypeEnv, V
|
||||
/// Check for overlap.
|
||||
pub fn check(tyenv: &TypeEnv, termenv: &TermEnv) -> Result<()> {
|
||||
let mut errors = check_overlaps(termenv).report(tyenv, termenv);
|
||||
if cfg!(feature = "overlap-errors") {
|
||||
if termenv.overlap_errors {
|
||||
errors.sort_by_key(|err| match err {
|
||||
Error::OverlapError { rules, .. } => rules.first().unwrap().1.from,
|
||||
_ => Pos::default(),
|
||||
|
||||
@@ -137,6 +137,7 @@ impl<'a> Parser<'a> {
|
||||
self.lparen()?;
|
||||
let pos = self.pos();
|
||||
let def = match &self.symbol()?[..] {
|
||||
"pragma" => Def::Pragma(self.parse_pragma()?),
|
||||
"type" => Def::Type(self.parse_type()?),
|
||||
"decl" => Def::Decl(self.parse_decl()?),
|
||||
"rule" => Def::Rule(self.parse_rule()?),
|
||||
@@ -197,6 +198,14 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_pragma(&mut self) -> Result<Pragma> {
|
||||
let ident = self.parse_ident()?;
|
||||
match ident.0.as_ref() {
|
||||
"overlap_errors" => Ok(Pragma::OverlapErrors),
|
||||
_ => Err(self.error(ident.1, format!("Unknown pragma '{}'", ident.0))),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_type(&mut self) -> Result<Type> {
|
||||
let pos = self.pos();
|
||||
let name = self.parse_ident()?;
|
||||
|
||||
@@ -200,6 +200,9 @@ pub struct TermEnv {
|
||||
/// defined implicit type-converter terms we can try to use to fit
|
||||
/// types together.
|
||||
pub converters: StableMap<(TypeId, TypeId), TermId>,
|
||||
|
||||
/// A flag indicating whether or not overlap between rules should be considered an error.
|
||||
pub overlap_errors: bool,
|
||||
}
|
||||
|
||||
/// A term.
|
||||
@@ -786,8 +789,10 @@ impl TermEnv {
|
||||
term_map: StableMap::new(),
|
||||
rules: vec![],
|
||||
converters: StableMap::new(),
|
||||
overlap_errors: false,
|
||||
};
|
||||
|
||||
env.collect_pragmas(defs);
|
||||
env.collect_term_sigs(tyenv, defs);
|
||||
env.collect_enum_variant_terms(tyenv);
|
||||
tyenv.return_errors()?;
|
||||
@@ -806,6 +811,15 @@ impl TermEnv {
|
||||
Ok(env)
|
||||
}
|
||||
|
||||
fn collect_pragmas(&mut self, defs: &ast::Defs) {
|
||||
for def in &defs.defs {
|
||||
match def {
|
||||
ast::Def::Pragma(ast::Pragma::OverlapErrors) => self.overlap_errors = true,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_term_sigs(&mut self, tyenv: &mut TypeEnv, defs: &ast::Defs) {
|
||||
for def in &defs.defs {
|
||||
match def {
|
||||
|
||||
Reference in New Issue
Block a user