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.
|
;; 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
|
;; The main lowering constructor term: takes a clif `Inst` and returns the
|
||||||
;; register(s) within which the lowered instruction's result values live.
|
;; register(s) within which the lowered instruction's result values live.
|
||||||
(decl lower (Inst) InstOutput)
|
(decl lower (Inst) InstOutput)
|
||||||
|
|||||||
@@ -19,6 +19,5 @@ tempfile = "3"
|
|||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
|
|
||||||
overlap-errors = []
|
|
||||||
logging = ["log"]
|
logging = ["log"]
|
||||||
miette-errors = ["miette"]
|
miette-errors = ["miette"]
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ pub struct Defs {
|
|||||||
/// One toplevel form in an ISLE file.
|
/// One toplevel form in an ISLE file.
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum Def {
|
pub enum Def {
|
||||||
|
Pragma(Pragma),
|
||||||
Type(Type),
|
Type(Type),
|
||||||
Rule(Rule),
|
Rule(Rule),
|
||||||
Extractor(Extractor),
|
Extractor(Extractor),
|
||||||
@@ -29,6 +30,13 @@ pub enum Def {
|
|||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct Ident(pub String, pub Pos);
|
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.
|
/// A declaration of a type.
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub struct Type {
|
pub struct Type {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use crate::sema::{self, Rule, RuleId, Sym, TermEnv, TermId, TermKind, TypeEnv, V
|
|||||||
/// Check for overlap.
|
/// Check for overlap.
|
||||||
pub fn check(tyenv: &TypeEnv, termenv: &TermEnv) -> Result<()> {
|
pub fn check(tyenv: &TypeEnv, termenv: &TermEnv) -> Result<()> {
|
||||||
let mut errors = check_overlaps(termenv).report(tyenv, termenv);
|
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 {
|
errors.sort_by_key(|err| match err {
|
||||||
Error::OverlapError { rules, .. } => rules.first().unwrap().1.from,
|
Error::OverlapError { rules, .. } => rules.first().unwrap().1.from,
|
||||||
_ => Pos::default(),
|
_ => Pos::default(),
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ impl<'a> Parser<'a> {
|
|||||||
self.lparen()?;
|
self.lparen()?;
|
||||||
let pos = self.pos();
|
let pos = self.pos();
|
||||||
let def = match &self.symbol()?[..] {
|
let def = match &self.symbol()?[..] {
|
||||||
|
"pragma" => Def::Pragma(self.parse_pragma()?),
|
||||||
"type" => Def::Type(self.parse_type()?),
|
"type" => Def::Type(self.parse_type()?),
|
||||||
"decl" => Def::Decl(self.parse_decl()?),
|
"decl" => Def::Decl(self.parse_decl()?),
|
||||||
"rule" => Def::Rule(self.parse_rule()?),
|
"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> {
|
fn parse_type(&mut self) -> Result<Type> {
|
||||||
let pos = self.pos();
|
let pos = self.pos();
|
||||||
let name = self.parse_ident()?;
|
let name = self.parse_ident()?;
|
||||||
|
|||||||
@@ -200,6 +200,9 @@ pub struct TermEnv {
|
|||||||
/// defined implicit type-converter terms we can try to use to fit
|
/// defined implicit type-converter terms we can try to use to fit
|
||||||
/// types together.
|
/// types together.
|
||||||
pub converters: StableMap<(TypeId, TypeId), TermId>,
|
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.
|
/// A term.
|
||||||
@@ -786,8 +789,10 @@ impl TermEnv {
|
|||||||
term_map: StableMap::new(),
|
term_map: StableMap::new(),
|
||||||
rules: vec![],
|
rules: vec![],
|
||||||
converters: StableMap::new(),
|
converters: StableMap::new(),
|
||||||
|
overlap_errors: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
env.collect_pragmas(defs);
|
||||||
env.collect_term_sigs(tyenv, defs);
|
env.collect_term_sigs(tyenv, defs);
|
||||||
env.collect_enum_variant_terms(tyenv);
|
env.collect_enum_variant_terms(tyenv);
|
||||||
tyenv.return_errors()?;
|
tyenv.return_errors()?;
|
||||||
@@ -806,6 +811,15 @@ impl TermEnv {
|
|||||||
Ok(env)
|
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) {
|
fn collect_term_sigs(&mut self, tyenv: &mut TypeEnv, defs: &ast::Defs) {
|
||||||
for def in &defs.defs {
|
for def in &defs.defs {
|
||||||
match def {
|
match def {
|
||||||
|
|||||||
Reference in New Issue
Block a user