ISLE: Add a nodebug type attribute to disable derive(Debug)
I need this to move the x64 `Inst` definition into ISLE without losing its custom `Debug` implementation that prints the assembly for the `Inst`.
This commit is contained in:
@@ -32,6 +32,7 @@ pub struct Ident(pub String, pub Pos);
|
|||||||
pub struct Type {
|
pub struct Type {
|
||||||
pub name: Ident,
|
pub name: Ident,
|
||||||
pub is_extern: bool,
|
pub is_extern: bool,
|
||||||
|
pub is_nodebug: bool,
|
||||||
pub ty: TypeValue,
|
pub ty: TypeValue,
|
||||||
pub pos: Pos,
|
pub pos: Pos,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,6 +138,7 @@ impl<'a> Codegen<'a> {
|
|||||||
&Type::Enum {
|
&Type::Enum {
|
||||||
name,
|
name,
|
||||||
is_extern,
|
is_extern,
|
||||||
|
is_nodebug,
|
||||||
ref variants,
|
ref variants,
|
||||||
pos,
|
pos,
|
||||||
..
|
..
|
||||||
@@ -150,11 +151,20 @@ impl<'a> Codegen<'a> {
|
|||||||
pos.pretty_print_line(&self.typeenv.filenames[..])
|
pos.pretty_print_line(&self.typeenv.filenames[..])
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
// Generate the `derive`s.
|
||||||
|
let debug_derive = if is_nodebug { "" } else { ", Debug" };
|
||||||
if variants.iter().all(|v| v.fields.is_empty()) {
|
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 {
|
} else {
|
||||||
writeln!(code, "#[derive(Clone, Debug)]").unwrap();
|
writeln!(code, "#[derive(Clone{})]", debug_derive).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
writeln!(code, "pub enum {} {{", name).unwrap();
|
writeln!(code, "pub enum {} {{", name).unwrap();
|
||||||
for variant in variants {
|
for variant in variants {
|
||||||
let name = &self.typeenv.syms[variant.name.index()];
|
let name = &self.typeenv.syms[variant.name.index()];
|
||||||
|
|||||||
@@ -197,15 +197,29 @@ impl<'a> Parser<'a> {
|
|||||||
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()?;
|
||||||
|
|
||||||
let mut is_extern = false;
|
let mut is_extern = false;
|
||||||
if self.is_sym_str("extern") {
|
let mut is_nodebug = false;
|
||||||
self.symbol()?;
|
|
||||||
is_extern = true;
|
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()?;
|
let ty = self.parse_typevalue()?;
|
||||||
Ok(Type {
|
Ok(Type {
|
||||||
name,
|
name,
|
||||||
is_extern,
|
is_extern,
|
||||||
|
is_nodebug,
|
||||||
ty,
|
ty,
|
||||||
pos,
|
pos,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -109,6 +109,10 @@ pub enum Type {
|
|||||||
/// If so, ISLE will not emit a definition for it. If not, then it will
|
/// If so, ISLE will not emit a definition for it. If not, then it will
|
||||||
/// emit a Rust definition for it.
|
/// emit a Rust definition for it.
|
||||||
is_extern: bool,
|
is_extern: bool,
|
||||||
|
/// Whether this type should *not* derive `Debug`.
|
||||||
|
///
|
||||||
|
/// Incompatible with `is_extern`.
|
||||||
|
is_nodebug: bool,
|
||||||
/// The different variants for this enum.
|
/// The different variants for this enum.
|
||||||
variants: Vec<Variant>,
|
variants: Vec<Variant>,
|
||||||
/// The ISLE source position where this `enum` is defined.
|
/// The ISLE source position where this `enum` is defined.
|
||||||
@@ -607,7 +611,7 @@ impl TypeEnv {
|
|||||||
let ty = match tyenv.type_map.get(&ty) {
|
let ty = match tyenv.type_map.get(&ty) {
|
||||||
Some(ty) => *ty,
|
Some(ty) => *ty,
|
||||||
None => {
|
None => {
|
||||||
tyenv.report_error(pos, "Unknown type for constant".into());
|
tyenv.report_error(pos, "Unknown type for constant");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -635,9 +639,22 @@ impl TypeEnv {
|
|||||||
let name = self.intern(&ty.name).unwrap();
|
let name = self.intern(&ty.name).unwrap();
|
||||||
match &ty.ty {
|
match &ty.ty {
|
||||||
&ast::TypeValue::Primitive(ref id, ..) => {
|
&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))
|
Some(Type::Primitive(tid, self.intern_mut(id), ty.pos))
|
||||||
}
|
}
|
||||||
&ast::TypeValue::Enum(ref ty_variants, ..) => {
|
&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![];
|
let mut variants = vec![];
|
||||||
for variant in ty_variants {
|
for variant in ty_variants {
|
||||||
let combined_ident =
|
let combined_ident =
|
||||||
@@ -696,6 +713,7 @@ impl TypeEnv {
|
|||||||
name,
|
name,
|
||||||
id: tid,
|
id: tid,
|
||||||
is_extern: ty.is_extern,
|
is_extern: ty.is_extern,
|
||||||
|
is_nodebug: ty.is_nodebug,
|
||||||
variants,
|
variants,
|
||||||
pos: ty.pos,
|
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<String>) -> Error {
|
||||||
let e = Error::TypeError {
|
let e = Error::TypeError {
|
||||||
msg,
|
msg: msg.into(),
|
||||||
src: Source::new(
|
src: Source::new(
|
||||||
self.filenames[pos.file].clone(),
|
self.filenames[pos.file].clone(),
|
||||||
self.file_texts[pos.file].clone(),
|
self.file_texts[pos.file].clone(),
|
||||||
@@ -716,7 +734,7 @@ impl TypeEnv {
|
|||||||
e
|
e
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_error(&mut self, pos: Pos, msg: String) {
|
fn report_error(&mut self, pos: Pos, msg: impl Into<String>) {
|
||||||
let err = self.error(pos, msg);
|
let err = self.error(pos, msg);
|
||||||
self.errors.push(err);
|
self.errors.push(err);
|
||||||
}
|
}
|
||||||
@@ -987,8 +1005,7 @@ impl TermEnv {
|
|||||||
tyenv.report_error(
|
tyenv.report_error(
|
||||||
ext.pos,
|
ext.pos,
|
||||||
"Extractor macro body defined on term of incorrect kind; cannot be an \
|
"Extractor macro body defined on term of incorrect kind; cannot be an \
|
||||||
enum variant"
|
enum variant",
|
||||||
.into(),
|
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1329,10 +1346,7 @@ impl TermEnv {
|
|||||||
let ty = match expected_ty {
|
let ty = match expected_ty {
|
||||||
Some(t) => t,
|
Some(t) => t,
|
||||||
None => {
|
None => {
|
||||||
tyenv.report_error(
|
tyenv.report_error(pos, "Need an implied type for an integer constant");
|
||||||
pos,
|
|
||||||
"Need an implied type for an integer constant".into(),
|
|
||||||
);
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1353,12 +1367,12 @@ impl TermEnv {
|
|||||||
let const_ty = match tyenv.const_types.get(&val) {
|
let const_ty = match tyenv.const_types.get(&val) {
|
||||||
Some(ty) => *ty,
|
Some(ty) => *ty,
|
||||||
None => {
|
None => {
|
||||||
tyenv.report_error(pos, "Unknown constant".into());
|
tyenv.report_error(pos, "Unknown constant");
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if expected_ty.is_some() && expected_ty != Some(const_ty) {
|
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))
|
Some((Pattern::ConstPrim(const_ty, val), const_ty))
|
||||||
}
|
}
|
||||||
@@ -1366,7 +1380,7 @@ impl TermEnv {
|
|||||||
let ty = match expected_ty {
|
let ty = match expected_ty {
|
||||||
Some(t) => t,
|
Some(t) => t,
|
||||||
None => {
|
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;
|
return None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1775,7 +1789,7 @@ impl TermEnv {
|
|||||||
let const_ty = match tyenv.const_types.get(&val) {
|
let const_ty = match tyenv.const_types.get(&val) {
|
||||||
Some(ty) => *ty,
|
Some(ty) => *ty,
|
||||||
None => {
|
None => {
|
||||||
tyenv.report_error(pos, "Unknown constant".into());
|
tyenv.report_error(pos, "Unknown constant");
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1920,6 +1934,7 @@ mod test {
|
|||||||
name: sym_a,
|
name: sym_a,
|
||||||
id: TypeId(1),
|
id: TypeId(1),
|
||||||
is_extern: true,
|
is_extern: true,
|
||||||
|
is_nodebug: false,
|
||||||
variants: vec![
|
variants: vec![
|
||||||
Variant {
|
Variant {
|
||||||
name: sym_b,
|
name: sym_b,
|
||||||
|
|||||||
4
cranelift/isle/isle_examples/nodebug.isle
Normal file
4
cranelift/isle/isle_examples/nodebug.isle
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
(type DoesNotDeriveDebug nodebug
|
||||||
|
(enum A
|
||||||
|
B
|
||||||
|
C))
|
||||||
Reference in New Issue
Block a user