diff --git a/cranelift/isle/isle/src/ast.rs b/cranelift/isle/isle/src/ast.rs index 57f257a892..dd69628eed 100644 --- a/cranelift/isle/isle/src/ast.rs +++ b/cranelift/isle/isle/src/ast.rs @@ -32,6 +32,7 @@ pub struct Ident(pub String, pub Pos); pub struct Type { pub name: Ident, pub is_extern: bool, + pub is_nodebug: bool, pub ty: TypeValue, pub pos: Pos, } diff --git a/cranelift/isle/isle/src/codegen.rs b/cranelift/isle/isle/src/codegen.rs index 23a76d39e7..c5de4deb66 100644 --- a/cranelift/isle/isle/src/codegen.rs +++ b/cranelift/isle/isle/src/codegen.rs @@ -138,6 +138,7 @@ impl<'a> Codegen<'a> { &Type::Enum { name, is_extern, + is_nodebug, ref variants, pos, .. @@ -150,11 +151,20 @@ impl<'a> Codegen<'a> { pos.pretty_print_line(&self.typeenv.filenames[..]) ) .unwrap(); + + // Generate the `derive`s. + let debug_derive = if is_nodebug { "" } else { ", Debug" }; if variants.iter().all(|v| v.fields.is_empty()) { - writeln!(code, "#[derive(Copy, Clone, Debug, PartialEq, Eq)]").unwrap(); + writeln!( + code, + "#[derive(Copy, Clone, PartialEq, Eq{})]", + debug_derive + ) + .unwrap(); } else { - writeln!(code, "#[derive(Clone, Debug)]").unwrap(); + writeln!(code, "#[derive(Clone{})]", debug_derive).unwrap(); } + writeln!(code, "pub enum {} {{", name).unwrap(); for variant in variants { let name = &self.typeenv.syms[variant.name.index()]; diff --git a/cranelift/isle/isle/src/parser.rs b/cranelift/isle/isle/src/parser.rs index 8d8bbad5d8..1f8de5ccff 100644 --- a/cranelift/isle/isle/src/parser.rs +++ b/cranelift/isle/isle/src/parser.rs @@ -197,15 +197,29 @@ impl<'a> Parser<'a> { fn parse_type(&mut self) -> Result { let pos = self.pos(); let name = self.parse_ident()?; + let mut is_extern = false; - if self.is_sym_str("extern") { - self.symbol()?; - is_extern = true; + let mut is_nodebug = false; + + while self.lexer.peek().map_or(false, |(_pos, tok)| tok.is_sym()) { + let sym = self.symbol()?; + if sym == "extern" { + is_extern = true; + } else if sym == "nodebug" { + is_nodebug = true; + } else { + return Err(self.error( + self.pos(), + format!("unknown type declaration modifier: {}", sym), + )); + } } + let ty = self.parse_typevalue()?; Ok(Type { name, is_extern, + is_nodebug, ty, pos, }) diff --git a/cranelift/isle/isle/src/sema.rs b/cranelift/isle/isle/src/sema.rs index fab78e6b7c..e10a5a5e71 100644 --- a/cranelift/isle/isle/src/sema.rs +++ b/cranelift/isle/isle/src/sema.rs @@ -109,6 +109,10 @@ pub enum Type { /// If so, ISLE will not emit a definition for it. If not, then it will /// emit a Rust definition for it. is_extern: bool, + /// Whether this type should *not* derive `Debug`. + /// + /// Incompatible with `is_extern`. + is_nodebug: bool, /// The different variants for this enum. variants: Vec, /// The ISLE source position where this `enum` is defined. @@ -607,7 +611,7 @@ impl TypeEnv { let ty = match tyenv.type_map.get(&ty) { Some(ty) => *ty, None => { - tyenv.report_error(pos, "Unknown type for constant".into()); + tyenv.report_error(pos, "Unknown type for constant"); continue; } }; @@ -635,9 +639,22 @@ impl TypeEnv { let name = self.intern(&ty.name).unwrap(); match &ty.ty { &ast::TypeValue::Primitive(ref id, ..) => { + if ty.is_nodebug { + self.report_error(ty.pos, "primitive types cannot be marked `nodebug`"); + return None; + } + if ty.is_extern { + self.report_error(ty.pos, "primitive types cannot be marked `extern`"); + return None; + } Some(Type::Primitive(tid, self.intern_mut(id), ty.pos)) } &ast::TypeValue::Enum(ref ty_variants, ..) => { + if ty.is_extern && ty.is_nodebug { + self.report_error(ty.pos, "external types cannot be marked `nodebug`"); + return None; + } + let mut variants = vec![]; for variant in ty_variants { let combined_ident = @@ -696,6 +713,7 @@ impl TypeEnv { name, id: tid, is_extern: ty.is_extern, + is_nodebug: ty.is_nodebug, variants, pos: ty.pos, }) @@ -703,9 +721,9 @@ impl TypeEnv { } } - fn error(&self, pos: Pos, msg: String) -> Error { + fn error(&self, pos: Pos, msg: impl Into) -> Error { let e = Error::TypeError { - msg, + msg: msg.into(), src: Source::new( self.filenames[pos.file].clone(), self.file_texts[pos.file].clone(), @@ -716,7 +734,7 @@ impl TypeEnv { e } - fn report_error(&mut self, pos: Pos, msg: String) { + fn report_error(&mut self, pos: Pos, msg: impl Into) { let err = self.error(pos, msg); self.errors.push(err); } @@ -987,8 +1005,7 @@ impl TermEnv { tyenv.report_error( ext.pos, "Extractor macro body defined on term of incorrect kind; cannot be an \ - enum variant" - .into(), + enum variant", ); continue; } @@ -1329,10 +1346,7 @@ impl TermEnv { let ty = match expected_ty { Some(t) => t, None => { - tyenv.report_error( - pos, - "Need an implied type for an integer constant".into(), - ); + tyenv.report_error(pos, "Need an implied type for an integer constant"); return None; } }; @@ -1353,12 +1367,12 @@ impl TermEnv { let const_ty = match tyenv.const_types.get(&val) { Some(ty) => *ty, None => { - tyenv.report_error(pos, "Unknown constant".into()); + tyenv.report_error(pos, "Unknown constant"); return None; } }; if expected_ty.is_some() && expected_ty != Some(const_ty) { - tyenv.report_error(pos, "Type mismatch for constant".into()); + tyenv.report_error(pos, "Type mismatch for constant"); } Some((Pattern::ConstPrim(const_ty, val), const_ty)) } @@ -1366,7 +1380,7 @@ impl TermEnv { let ty = match expected_ty { Some(t) => t, None => { - tyenv.report_error(pos, "Need an implied type for a wildcard".into()); + tyenv.report_error(pos, "Need an implied type for a wildcard"); return None; } }; @@ -1775,7 +1789,7 @@ impl TermEnv { let const_ty = match tyenv.const_types.get(&val) { Some(ty) => *ty, None => { - tyenv.report_error(pos, "Unknown constant".into()); + tyenv.report_error(pos, "Unknown constant"); return None; } }; @@ -1920,6 +1934,7 @@ mod test { name: sym_a, id: TypeId(1), is_extern: true, + is_nodebug: false, variants: vec![ Variant { name: sym_b, diff --git a/cranelift/isle/isle_examples/nodebug.isle b/cranelift/isle/isle_examples/nodebug.isle new file mode 100644 index 0000000000..71accb034f --- /dev/null +++ b/cranelift/isle/isle_examples/nodebug.isle @@ -0,0 +1,4 @@ +(type DoesNotDeriveDebug nodebug + (enum A + B + C))