aboutsummaryrefslogtreecommitdiff
path: root/rust/qemu-api-macros
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2024-11-06 21:27:47 +0000
committerPeter Maydell <peter.maydell@linaro.org>2024-11-06 21:27:47 +0000
commita1dacb66915eb7d08a0596cc97068a37c39930d3 (patch)
treedaa33d1f6e890c744c85fc08a7b928d1d55b158a /rust/qemu-api-macros
parent63dc36944383f70f1c7a20f6104966d8560300fa (diff)
parent951f71ad67bd474aba6925529daf45b747aac86e (diff)
downloadqemu-a1dacb66915eb7d08a0596cc97068a37c39930d3.zip
qemu-a1dacb66915eb7d08a0596cc97068a37c39930d3.tar.gz
qemu-a1dacb66915eb7d08a0596cc97068a37c39930d3.tar.bz2
Merge tag 'for-upstream-rust' of https://gitlab.com/bonzini/qemu into staging
* rust: cleanups * rust: integration tests * rust/pl011: add support for migration * rust/pl011: add TYPE_PL011_LUMINARY device * rust: add support for older compilers and bindgen # -----BEGIN PGP SIGNATURE----- # # iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmcrrtIUHHBib256aW5p # QHJlZGhhdC5jb20ACgkQv/vSX3jHroPIBwf/W0Jo87UauGYufhEmoPvWG1EAQEqP # EzNTzem9Iw92VdiSTkAtED0/TSd8RBJOwDfjjusVXZtuMPwpRNgXaFhYTT5gFTMj # Nk3NZGaX/mbNrtdrukdx9mvUWeovytdZDZccTNkpc3oyiqY9NEz06wZ0tCNJEot6 # qO3dEtKXTOQTdx2R3o0oS+2OFDGEEPxZ0PuXN3sClN4iZhGfcIDsjGAWxEh6mCDy # VxqKPdax1Ig1w7M+JMclnpOsVHwcefjHiToNPwhCEGelJ9BZilkViuvBzsVRJJz3 # ptYyywBE0FT8MiKQ/wyf7U64qoizJuIgHoQnUGj98hdgvbUUiW5jcBNY3A== # =s591 # -----END PGP SIGNATURE----- # gpg: Signature made Wed 06 Nov 2024 18:00:50 GMT # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "pbonzini@redhat.com" # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full] # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * tag 'for-upstream-rust' of https://gitlab.com/bonzini/qemu: (39 commits) dockerfiles: install bindgen from cargo on Ubuntu 22.04 rust: make rustfmt optional rust: allow older version of bindgen rust: do not use --generate-cstr rust: allow version 1.63.0 of rustc rust: clean up detection of the language rust: do not use MaybeUninit::zeroed() rust: introduce alternative implementation of offset_of! rust: create a cargo workspace rust: synchronize dependencies between subprojects and Cargo.lock rust: silence unknown warnings for the sake of old compilers rust: introduce a c_str macro rust: use std::os::raw instead of core::ffi rust: fix cfgs of proc-macro2 for 1.63.0 rust: patch bilge-impl to allow compilation with 1.63.0 rust/pl011: Use correct masks for IBRD and FBRD rust/pl011: remove commented out C code rust/pl011: add TYPE_PL011_LUMINARY device rust/pl011: move CLK_NAME static to function scope rust/pl011: add support for migration ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'rust/qemu-api-macros')
-rw-r--r--rust/qemu-api-macros/Cargo.lock47
-rw-r--r--rust/qemu-api-macros/Cargo.toml5
-rw-r--r--rust/qemu-api-macros/meson.build2
-rw-r--r--rust/qemu-api-macros/src/lib.rs101
4 files changed, 78 insertions, 77 deletions
diff --git a/rust/qemu-api-macros/Cargo.lock b/rust/qemu-api-macros/Cargo.lock
deleted file mode 100644
index fdc0fce..0000000
--- a/rust/qemu-api-macros/Cargo.lock
+++ /dev/null
@@ -1,47 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.86"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
-dependencies = [
- "unicode-ident",
-]
-
-[[package]]
-name = "qemu_api_macros"
-version = "0.1.0"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.36"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "syn"
-version = "2.0.72"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "unicode-ident"
-version = "1.0.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
diff --git a/rust/qemu-api-macros/Cargo.toml b/rust/qemu-api-macros/Cargo.toml
index 144cc36..a8f7377 100644
--- a/rust/qemu-api-macros/Cargo.toml
+++ b/rust/qemu-api-macros/Cargo.toml
@@ -19,7 +19,4 @@ proc-macro = true
[dependencies]
proc-macro2 = "1"
quote = "1"
-syn = "2"
-
-# Do not include in any global workspace
-[workspace]
+syn = { version = "2", features = ["extra-traits"] }
diff --git a/rust/qemu-api-macros/meson.build b/rust/qemu-api-macros/meson.build
index 517b9a4..24325de 100644
--- a/rust/qemu-api-macros/meson.build
+++ b/rust/qemu-api-macros/meson.build
@@ -2,7 +2,7 @@ quote_dep = dependency('quote-1-rs', native: true)
syn_dep = dependency('syn-2-rs', native: true)
proc_macro2_dep = dependency('proc-macro2-1-rs', native: true)
-_qemu_api_macros_rs = import('rust').proc_macro(
+_qemu_api_macros_rs = rust.proc_macro(
'qemu_api_macros',
files('src/lib.rs'),
override_options: ['rust_std=2021', 'build.rust_std=2021'],
diff --git a/rust/qemu-api-macros/src/lib.rs b/rust/qemu-api-macros/src/lib.rs
index 59aba59..cf99ac0 100644
--- a/rust/qemu-api-macros/src/lib.rs
+++ b/rust/qemu-api-macros/src/lib.rs
@@ -3,41 +3,92 @@
// SPDX-License-Identifier: GPL-2.0-or-later
use proc_macro::TokenStream;
-use quote::{format_ident, quote};
-use syn::{parse_macro_input, DeriveInput};
+use proc_macro2::Span;
+use quote::{quote, quote_spanned};
+use syn::{
+ parse_macro_input, parse_quote, punctuated::Punctuated, token::Comma, Data, DeriveInput, Field,
+ Fields, Ident, Type, Visibility,
+};
+
+struct CompileError(String, Span);
+
+impl From<CompileError> for proc_macro2::TokenStream {
+ fn from(err: CompileError) -> Self {
+ let CompileError(msg, span) = err;
+ quote_spanned! { span => compile_error!(#msg); }
+ }
+}
+
+fn is_c_repr(input: &DeriveInput, msg: &str) -> Result<(), CompileError> {
+ let expected = parse_quote! { #[repr(C)] };
+
+ if input.attrs.iter().any(|attr| attr == &expected) {
+ Ok(())
+ } else {
+ Err(CompileError(
+ format!("#[repr(C)] required for {}", msg),
+ input.ident.span(),
+ ))
+ }
+}
#[proc_macro_derive(Object)]
pub fn derive_object(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
-
let name = input.ident;
- let module_static = format_ident!("__{}_LOAD_MODULE", name);
let expanded = quote! {
- #[allow(non_upper_case_globals)]
- #[used]
- #[cfg_attr(target_os = "linux", link_section = ".ctors")]
- #[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")]
- #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
- pub static #module_static: extern "C" fn() = {
- extern "C" fn __register() {
- unsafe {
- ::qemu_api::bindings::type_register_static(&<#name as ::qemu_api::definitions::ObjectImpl>::TYPE_INFO);
- }
+ ::qemu_api::module_init! {
+ MODULE_INIT_QOM => unsafe {
+ ::qemu_api::bindings::type_register_static(&<#name as ::qemu_api::definitions::ObjectImpl>::TYPE_INFO);
}
+ }
+ };
- extern "C" fn __load() {
- unsafe {
- ::qemu_api::bindings::register_module_init(
- Some(__register),
- ::qemu_api::bindings::module_init_type::MODULE_INIT_QOM
- );
- }
- }
+ TokenStream::from(expanded)
+}
- __load
- };
- };
+fn get_fields(input: &DeriveInput) -> Result<&Punctuated<Field, Comma>, CompileError> {
+ if let Data::Struct(s) = &input.data {
+ if let Fields::Named(fs) = &s.fields {
+ Ok(&fs.named)
+ } else {
+ Err(CompileError(
+ "Cannot generate offsets for unnamed fields.".to_string(),
+ input.ident.span(),
+ ))
+ }
+ } else {
+ Err(CompileError(
+ "Cannot generate offsets for union or enum.".to_string(),
+ input.ident.span(),
+ ))
+ }
+}
+
+#[rustfmt::skip::macros(quote)]
+fn derive_offsets_or_error(input: DeriveInput) -> Result<proc_macro2::TokenStream, CompileError> {
+ is_c_repr(&input, "#[derive(offsets)]")?;
+
+ let name = &input.ident;
+ let fields = get_fields(&input)?;
+ let field_names: Vec<&Ident> = fields.iter().map(|f| f.ident.as_ref().unwrap()).collect();
+ let field_types: Vec<&Type> = fields.iter().map(|f| &f.ty).collect();
+ let field_vis: Vec<&Visibility> = fields.iter().map(|f| &f.vis).collect();
+
+ Ok(quote! {
+ ::qemu_api::with_offsets! {
+ struct #name {
+ #(#field_vis #field_names: #field_types,)*
+ }
+ }
+ })
+}
+
+#[proc_macro_derive(offsets)]
+pub fn derive_offsets(input: TokenStream) -> TokenStream {
+ let input = parse_macro_input!(input as DeriveInput);
+ let expanded = derive_offsets_or_error(input).unwrap_or_else(Into::into);
TokenStream::from(expanded)
}