[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [RFC PATCH 07/25] tools/xenbindgen: Add support for structs in TOML specs
Signed-off-by: Alejandro Vallejo <alejandro.vallejo@xxxxxxxxx> --- tools/rust/xenbindgen/src/c_lang.rs | 56 ++++++++++++++++++++++++- tools/rust/xenbindgen/src/spec.rs | 64 ++++++++++++++++++++++++++++- 2 files changed, 117 insertions(+), 3 deletions(-) diff --git a/tools/rust/xenbindgen/src/c_lang.rs b/tools/rust/xenbindgen/src/c_lang.rs index f05e36bb362f..597e0ed41362 100644 --- a/tools/rust/xenbindgen/src/c_lang.rs +++ b/tools/rust/xenbindgen/src/c_lang.rs @@ -17,9 +17,10 @@ use std::fmt::Write; -use crate::spec::OutFileDef; +use crate::spec::{OutFileDef, StructDef, Typ}; use convert_case::{Case, Casing}; +use log::{debug, trace}; /// An abstract indentation level. 0 is no indentation, 1 is [`INDENT_WIDTH`] /// and so on. @@ -29,6 +30,39 @@ struct Indentation(usize); /// Default width of each level of indentation const INDENT_WIDTH: usize = 4; +/// Create a C-compatible struct field. Without the terminating semicolon. +fn structfield(typ: &Typ, name: &str) -> String { + match typ { + Typ::Ptr(x) => { + let t: &Typ = x; + format!( + "XEN_GUEST_HANDLE_64({}) {name}", + match t { + Typ::U8 => "uint8", + Typ::U16 => "uint16", + Typ::U32 => "uint32", + Typ::U64 => "uint64_aligned_t", + Typ::I8 => "int8", + Typ::I16 => "int16", + Typ::I32 => "int32", + Typ::I64 => "int64_aligned_t", + _ => panic!("foo {t:?}"), + } + ) + } + Typ::Struct(x) => format!("struct {x} {name}"), + Typ::Array(x, len) => format!("{}{name}[{len}]", structfield(x, "")), + Typ::U8 => format!("uint8_t {name}"), + Typ::U16 => format!("uint16_t {name}"), + Typ::U32 => format!("uint32_t {name}"), + Typ::U64 => format!("uint64_aligned_t {name}"), + Typ::I8 => format!("int8_t {name}"), + Typ::I16 => format!("int16_t {name}"), + Typ::I32 => format!("int32_t {name}"), + Typ::I64 => format!("int64_aligned_t {name}"), + } +} + /// Add a comment to a struct or a field. fn comment(out: &mut String, comment: &str, ind: Indentation) { let spaces = " ".repeat(INDENT_WIDTH * ind.0); @@ -48,6 +82,22 @@ fn comment(out: &mut String, comment: &str, ind: Indentation) { } } +/// Write a C-compatible struct onto `out` +fn structgen(out: &mut String, def: &StructDef) { + debug!("struct {}", def.name); + + comment(out, &def.description, Indentation(0)); + writeln!(out, "struct {} {{", def.name.to_case(Case::Snake)).unwrap(); + for f in &def.fields { + trace!(" field {} type={:?}", f.name, f.typ); + + comment(out, &f.description, Indentation(1)); + writeln!(out, " {};", structfield(&f.typ, &f.name),).unwrap(); + } + writeln!(out, "}};").unwrap(); + writeln!(out).unwrap(); +} + /// Generates a single `.h` file. /// /// `filedef` is a language-agnostic high level description of what the output @@ -67,6 +117,10 @@ pub fn parse(filedef: &OutFileDef) -> String { writeln!(out, "#ifndef __XEN_AUTOGEN_{name}_H").unwrap(); writeln!(out, "#define __XEN_AUTOGEN_{name}_H\n").unwrap(); + for def in &filedef.structs { + structgen(&mut out, def); + } + writeln!(out, "#endif /* __XEN_AUTOGEN_{name}_H */\n").unwrap(); out diff --git a/tools/rust/xenbindgen/src/spec.rs b/tools/rust/xenbindgen/src/spec.rs index 08c4dc3a7eba..e183378329ad 100644 --- a/tools/rust/xenbindgen/src/spec.rs +++ b/tools/rust/xenbindgen/src/spec.rs @@ -17,9 +17,61 @@ use std::{fs::read_to_string, path::Path}; use log::{debug, info}; +/// An IDL type. A type may be a primitive integer, a pointer to an IDL type, +/// an array of IDL types or a struct composed of IDL types. Every integer must +/// be aligned to its size. +/// +/// FIXME: This enumerated type is recovered as-is from the `typ` field in the +/// TOML files. Ideally, that representation should be more ergonomic and the +/// parser instructed to deal with it. +#[allow(clippy::missing_docs_in_private_items)] +#[derive(Debug, serde::Deserialize, PartialEq)] +#[serde(rename_all = "lowercase", tag = "tag", content = "args")] +pub enum Typ { + Struct(String), + U8, + U16, + U32, + U64, + I8, + I16, + I32, + I64, + Ptr(Box<Typ>), + Array(Box<Typ>, usize), +} + +/// Deserialized form of a hypercall struct +#[derive(Debug, serde::Deserialize)] +pub struct StructDef { + /// Name of the struct + pub name: String, + /// Description of what the struct is for. This string is added as a comment + /// on top of the autogenerated struct. + pub description: String, + /// Fields contained in the struct. May be none, in which case it's a zero + /// length struct. + pub fields: Vec<FieldDef>, +} + +/// Deserialized form of a field within a hypercall struct (see [`StructDef`]) +#[derive(Debug, serde::Deserialize)] +pub struct FieldDef { + /// Name of the field + pub name: String, + /// Description of what the field is for. This string is added as a comment + /// on top of the autogenerated field. + pub description: String, + /// Type of the field. + pub typ: Typ, +} + /// A language-agnostic specification. #[derive(Debug, serde::Deserialize)] -struct InFileDef; +struct InFileDef { + /// List of structs described in this input specification. + structs: Option<Vec<StructDef>>, +} /// Description of an abstract output (i.e: `.rs`, `.h`, etc). /// @@ -28,6 +80,8 @@ struct InFileDef; pub struct OutFileDef { /// The name of the output file, without the final extension. pub name: String, + /// List of structs described by all input spec files merged on this file. + pub structs: Vec<StructDef>, } impl OutFileDef { @@ -40,13 +94,19 @@ impl OutFileDef { pub fn new(name: String, dir: &Path) -> Result<Self, Error> { info!("Reading {dir:?} to generate an output file"); - let ret = Self { name }; + let mut ret = Self { + name, + structs: Vec::new(), + }; for entry in from_ioerr(dir.read_dir())? { let path = from_ioerr(entry)?.path(); debug!("Reading {:?} to generate outfile={}", path, ret.name); let toml_str = from_ioerr(read_to_string(path))?; let filedef: InFileDef = toml::from_str(&toml_str).map_err(Error::Toml)?; + if let Some(structs) = filedef.structs { + ret.structs.extend(structs); + } } Ok(ret) -- 2.47.0
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |