Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/bindgen/codegen/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 11 kB image not shown  

Quelle  helpers.rs

  Sprache: Rust
 

//! Helpers for code generation that don't need macro expansion.

use proc_macro2::{Ident, Span};

use crate::ir::context::BindgenContext;
use crate::ir::layout::Layout;
use crate::ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT;

pub(cratemod attributes {
    use proc_macro2::{Ident, Span, TokenStream};
    use std::{borrow::Cow, str::FromStr};

    pub(cratefn repr(which: &str) -> TokenStream {
        let which = Ident::new(which, Span::call_site());
        quote! {
            #[repr( #which )]
        }
    }

    pub(cratefn repr_list(which_ones: &[&str]) -> TokenStream {
        let which_ones = which_ones
            .iter()
            .map(|one| TokenStream::from_str(one).expect("repr to be valid"));
        quote! {
            #[repr( #( #which_ones ),* )]
        }
    }

    pub(cratefn derives(which_ones: &[&str]) -> TokenStream {
        let which_ones = which_ones
            .iter()
            .map(|one| TokenStream::from_str(one).expect("derive to be valid"));
        quote! {
            #[derive( #( #which_ones ),* )]
        }
    }

    pub(cratefn inline() -> TokenStream {
        quote! {
            #[inline]
        }
    }

    pub(cratefn must_use() -> TokenStream {
        quote! {
            #[must_use]
        }
    }

    pub(cratefn non_exhaustive() -> TokenStream {
        quote! {
            #[non_exhaustive]
        }
    }

    pub(cratefn doc(comment: &str) -> TokenStream {
        if comment.is_empty() {
            quote!()
        } else {
            quote!(#[doc = #comment])
        }
    }

    pub(cratefn link_name<const MANGLE: bool>(name: &str) -> TokenStream {
        // LLVM mangles the name by default but it's already mangled.
        // Prefixing the name with \u{1} should tell LLVM to not mangle it.
        let name: Cow<'_, str> = if MANGLE {
            name.into()
        } else {
            format!("\u{1}{name}").into()
        };

        quote! {
            #[link_name = #name]
        }
    }
}

/// The `ffi_safe` argument should be true if this is a type that the user might
/// reasonably use, e.g. not struct padding, where the `__BindgenOpaqueArray` is
/// just noise.
/// TODO: Should this be `MaybeUninit`, since padding bytes are effectively
/// uninitialized?
pub(cratefn blob(
    ctx: &BindgenContext,
    layout: Layout,
    ffi_safe: bool,
) -> syn::Type {
    let align = layout.align.max(1);
    // For alignments <= 4, it holds that the integer type of the same size aligns to that same
    // size. For bigger alignments that's not guaranteed, e.g. on x86 u64 is aligned to 4 bytes.
    if align <= 4 {
        let ty = Layout::known_type_for_size(align).unwrap();
        let len = layout.size / align;
        return if len == 1 {
            ty
        } else if !ffi_safe && len <= RUST_DERIVE_IN_ARRAY_LIMIT {
            syn::parse_quote! { [#ty#len] }
        } else {
            ctx.generated_opaque_array(1);
            if ctx.options().enable_cxx_namespaces {
                syn::parse_quote! { root::__BindgenOpaqueArray<[#ty#len]> }
            } else {
                syn::parse_quote! { __BindgenOpaqueArray<[#ty#len]> }
            }
        };
    }

    ctx.generated_opaque_array(align);
    let ident = format_ident!("__BindgenOpaqueArray{}", align);
    let size = layout.size;
    if ctx.options().enable_cxx_namespaces {
        syn::parse_quote! { root::#ident<[u8; #size]> }
    } else {
        syn::parse_quote! { #ident<[u8; #size]> }
    }
}

/// Integer type of the same size as the given `Layout`.
pub(cratefn integer_type(layout: Layout) -> Option<syn::Type> {
    Layout::known_type_for_size(layout.size)
}

pub(crateconst BITFIELD_UNIT: &str = "__BindgenBitfieldUnit";

/// Generates a bitfield allocation unit type for a type with the given `Layout`.
pub(cratefn bitfield_unit(ctx: &BindgenContext, layout: Layout) -> syn::Type {
    let size = layout.size;
    let bitfield_unit_name = Ident::new(BITFIELD_UNIT, Span::call_site());
    let ty = syn::parse_quote! { #bitfield_unit_name<[u8; #size]> };

    if ctx.options().enable_cxx_namespaces {
        return syn::parse_quote! { root::#ty };
    }

    ty
}

pub(cratemod ast_ty {
    use crate::ir::context::BindgenContext;
    use crate::ir::function::FunctionSig;
    use crate::ir::layout::Layout;
    use crate::ir::ty::{FloatKind, IntKind};
    use proc_macro2::TokenStream;
    use std::str::FromStr;

    pub(cratefn c_void(ctx: &BindgenContext) -> syn::Type {
        // ctypes_prefix takes precedence
        match ctx.options().ctypes_prefix {
            Some(ref prefix) => {
                let prefix = TokenStream::from_str(prefix.as_str()).unwrap();
                syn::parse_quote! { #prefix::c_void }
            }
            None => {
                if ctx.options().use_core {
                    syn::parse_quote! { ::core::ffi::c_void }
                } else {
                    syn::parse_quote! { ::std::os::raw::c_void }
                }
            }
        }
    }

    pub(cratefn raw_type(ctx: &BindgenContext, name: &str) -> syn::Type {
        let ident = ctx.rust_ident_raw(name);
        match ctx.options().ctypes_prefix {
            Some(ref prefix) => {
                let prefix = TokenStream::from_str(prefix.as_str()).unwrap();
                syn::parse_quote! { #prefix::#ident }
            }
            None => {
                if ctx.options().use_core &&
                    ctx.options().rust_features().core_ffi_c
                {
                    syn::parse_quote! { ::core::ffi::#ident }
                } else {
                    syn::parse_quote! { ::std::os::raw::#ident }
                }
            }
        }
    }

    pub(cratefn int_kind_rust_type(
        ctx: &BindgenContext,
        ik: IntKind,
        layout: Option<Layout>,
    ) -> syn::Type {
        match ik {
            IntKind::Bool => syn::parse_quote! { bool },
            IntKind::Char { .. } => raw_type(ctx, "c_char"),
            // The following is used only when an unusual command-line
            // argument is used. bindgen_cchar16_t is not a real type;
            // but this allows downstream postprocessors to distinguish
            // this case and do something special for C++ bindings
            // containing the C++ type char16_t.
            IntKind::Char16 => syn::parse_quote! { bindgen_cchar16_t },
            IntKind::SChar => raw_type(ctx, "c_schar"),
            IntKind::UChar => raw_type(ctx, "c_uchar"),
            IntKind::Short => raw_type(ctx, "c_short"),
            IntKind::UShort => raw_type(ctx, "c_ushort"),
            IntKind::Int => raw_type(ctx, "c_int"),
            IntKind::UInt => raw_type(ctx, "c_uint"),
            IntKind::Long => raw_type(ctx, "c_long"),
            IntKind::ULong => raw_type(ctx, "c_ulong"),
            IntKind::LongLong => raw_type(ctx, "c_longlong"),
            IntKind::ULongLong => raw_type(ctx, "c_ulonglong"),
            IntKind::WChar => {
                let layout =
                    layout.expect("Couldn't compute wchar_t's layout?");
                Layout::known_type_for_size(layout.size)
                    .expect("Non-representable wchar_t?")
            }

            IntKind::I8 => syn::parse_quote! { i8 },
            IntKind::U8 => syn::parse_quote! { u8 },
            IntKind::I16 => syn::parse_quote! { i16 },
            IntKind::U16 => syn::parse_quote! { u16 },
            IntKind::I32 => syn::parse_quote! { i32 },
            IntKind::U32 => syn::parse_quote! { u32 },
            IntKind::I64 => syn::parse_quote! { i64 },
            IntKind::U64 => syn::parse_quote! { u64 },
            IntKind::Custom { name, .. } => {
                syn::parse_str(name).expect("Invalid integer type.")
            }
            IntKind::U128 => {
                if true {
                    syn::parse_quote! { u128 }
                } else {
                    // Best effort thing, but wrong alignment
                    // unfortunately.
                    syn::parse_quote! { [u64; 2] }
                }
            }
            IntKind::I128 => {
                if true {
                    syn::parse_quote! { i128 }
                } else {
                    syn::parse_quote! { [u64; 2] }
                }
            }
        }
    }

    pub(cratefn float_kind_rust_type(
        ctx: &BindgenContext,
        fk: FloatKind,
        layout: Option<Layout>,
    ) -> syn::Type {
        // TODO: we probably should take the type layout into account more
        // often?
        //
        // Also, maybe this one shouldn't be the default?
        match (fk, ctx.options().convert_floats) {
            (FloatKind::Float16, _) => {
                // TODO: do f16 when rust lands it
                ctx.generated_bindgen_float16();
                if ctx.options().enable_cxx_namespaces {
                    syn::parse_quote! { root::__BindgenFloat16 }
                } else {
                    syn::parse_quote! { __BindgenFloat16 }
                }
            }
            (FloatKind::Float, true) => syn::parse_quote! { f32 },
            (FloatKind::Double, true) => syn::parse_quote! { f64 },
            (FloatKind::Float, false) => raw_type(ctx, "c_float"),
            (FloatKind::Double, false) => raw_type(ctx, "c_double"),
            (FloatKind::LongDouble, _) => {
                if let Some(layout) = layout {
                    match layout.size {
                        4 => syn::parse_quote! { f32 },
                        8 => syn::parse_quote! { f64 },
                        // TODO(emilio): If rust ever gains f128 we should
                        // use it here and below.
                        _ => super::integer_type(layout)
                            .unwrap_or(syn::parse_quote! { f64 }),
                    }
                } else {
                    debug_assert!(
                        false,
                        "How didn't we know the layout for a primitive type?"
                    );
                    syn::parse_quote! { f64 }
                }
            }
            (FloatKind::Float128, _) => {
                if true {
                    syn::parse_quote! { u128 }
                } else {
                    syn::parse_quote! { [u64; 2] }
                }
            }
        }
    }

    pub(cratefn int_expr(val: i64) -> TokenStream {
        // Don't use quote! { #val } because that adds the type suffix.
        let val = proc_macro2::Literal::i64_unsuffixed(val);
        quote!(#val)
    }

    pub(cratefn uint_expr(val: u64) -> TokenStream {
        // Don't use quote! { #val } because that adds the type suffix.
        let val = proc_macro2::Literal::u64_unsuffixed(val);
        quote!(#val)
    }

    pub(cratefn cstr_expr(mut string: String) -> TokenStream {
        string.push('\0');
        let b = proc_macro2::Literal::byte_string(string.as_bytes());
        quote! {
            #b
        }
    }

    pub(cratefn float_expr(f: f64) -> Result<TokenStream, ()> {
        if f.is_finite() {
            let val = proc_macro2::Literal::f64_unsuffixed(f);

            return Ok(quote!(#val));
        }

        if f.is_nan() {
            return Ok(quote! { f64::NAN });
        }

        if f.is_infinite() {
            let tokens = if f.is_sign_positive() {
                quote! { f64::INFINITY }
            } else {
                quote! { f64::NEG_INFINITY }
            };
            return Ok(tokens);
        }

        warn!("Unknown non-finite float number: {f:?}");
        Err(())
    }

    pub(cratefn arguments_from_signature(
        signature: &FunctionSig,
        ctx: &BindgenContext,
    ) -> Vec<TokenStream> {
        let mut unnamed_arguments = 0;
        signature
            .argument_types()
            .iter()
            .map(|&(ref name, _ty)| {
                let name = if let Some(ref name) = *name {
                    ctx.rust_ident(name)
                } else {
                    unnamed_arguments += 1;
                    ctx.rust_ident(format!("arg{unnamed_arguments}"))
                };
                quote! { #name }
            })
            .collect()
    }
}

Messung V0.5 in Prozent
C=75 H=97 G=86

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet am  2026-08-27) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.