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:
Trevor Elliott
2022-09-29 12:40:39 -07:00
committed by GitHub
parent db06e4e622
commit 7d5b2b5bb2
6 changed files with 35 additions and 2 deletions

View File

@@ -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)

View File

@@ -19,6 +19,5 @@ tempfile = "3"
[features]
default = []
overlap-errors = []
logging = ["log"]
miette-errors = ["miette"]

View File

@@ -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 {

View File

@@ -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(),

View File

@@ -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()?;

View File

@@ -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 {