diff --git a/cranelift/codegen/src/isa/x64/lower.isle b/cranelift/codegen/src/isa/x64/lower.isle index c78c111f2b..deb4e32f74 100644 --- a/cranelift/codegen/src/isa/x64/lower.isle +++ b/cranelift/codegen/src/isa/x64/lower.isle @@ -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) diff --git a/cranelift/isle/isle/Cargo.toml b/cranelift/isle/isle/Cargo.toml index 5d462987b8..28a6c6df83 100644 --- a/cranelift/isle/isle/Cargo.toml +++ b/cranelift/isle/isle/Cargo.toml @@ -19,6 +19,5 @@ tempfile = "3" [features] default = [] -overlap-errors = [] logging = ["log"] miette-errors = ["miette"] diff --git a/cranelift/isle/isle/src/ast.rs b/cranelift/isle/isle/src/ast.rs index c6f5a50d95..6337ff5b04 100644 --- a/cranelift/isle/isle/src/ast.rs +++ b/cranelift/isle/isle/src/ast.rs @@ -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 )` 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 { diff --git a/cranelift/isle/isle/src/overlap.rs b/cranelift/isle/isle/src/overlap.rs index 1c8542c534..5861b8b5fe 100644 --- a/cranelift/isle/isle/src/overlap.rs +++ b/cranelift/isle/isle/src/overlap.rs @@ -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(), diff --git a/cranelift/isle/isle/src/parser.rs b/cranelift/isle/isle/src/parser.rs index 68fb3adb2d..cfe0444a91 100644 --- a/cranelift/isle/isle/src/parser.rs +++ b/cranelift/isle/isle/src/parser.rs @@ -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 { + 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 { let pos = self.pos(); let name = self.parse_ident()?; diff --git a/cranelift/isle/isle/src/sema.rs b/cranelift/isle/isle/src/sema.rs index 5732ba300c..7435623be9 100644 --- a/cranelift/isle/isle/src/sema.rs +++ b/cranelift/isle/isle/src/sema.rs @@ -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 {