pub(crate) fn 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(crate) fn 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; returnif len == 1 {
ty
} elseif !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(crate) fn integer_type(layout: Layout) -> Option<syn::Type> {
Layout::known_type_for_size(layout.size)
}
/// Generates a bitfield allocation unit type for a type with the given `Layout`. pub(crate) fn 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(crate) mod ast_ty { usecrate::ir::context::BindgenContext; usecrate::ir::function::FunctionSig; usecrate::ir::layout::Layout; usecrate::ir::ty::{FloatKind, IntKind}; use proc_macro2::TokenStream; use std::str::FromStr;
pub(crate) fn 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?")
}
pub(crate) fn 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, _) => { iflet 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, _) => { iftrue {
syn::parse_quote! { u128 }
} else {
syn::parse_quote! { [u64; 2] }
}
}
}
}
pub(crate) fn 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(crate) fn 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(crate) fn cstr_expr(mut string: String) -> TokenStream {
string.push('\0'); let b = proc_macro2::Literal::byte_string(string.as_bytes());
quote! { #b
}
}
pub(crate) fn 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);
}
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.