diff options
Diffstat (limited to 'codegen/helpers.rs')
-rw-r--r-- | codegen/helpers.rs | 317 |
1 files changed, 86 insertions, 231 deletions
diff --git a/codegen/helpers.rs b/codegen/helpers.rs index 113e93d..7ef44fe 100644 --- a/codegen/helpers.rs +++ b/codegen/helpers.rs @@ -1,11 +1,7 @@ //! Helpers for code generation that don't need macro expansion. -use crate::ir::comp::SpecialMemberKind; -use crate::ir::function::Visibility; +use crate::ir::context::BindgenContext; use crate::ir::layout::Layout; -use crate::{ir::context::BindgenContext, BindgenOptions}; -use proc_macro2::{Ident, Span, TokenStream}; -use quote::TokenStreamExt; pub(crate) mod attributes { use proc_macro2::{Ident, Span, TokenStream}; @@ -79,202 +75,29 @@ pub(crate) mod attributes { } } -pub trait CppSemanticAttributeCreator { - fn do_add(&mut self, ts: TokenStream); - fn is_enabled(&self) -> bool; - - fn add(&mut self, tokens: TokenStream) { - if self.is_enabled() { - self.do_add(quote! { - #[cpp_semantics(#tokens)] - }) - } - } - - fn add_ident(&mut self, desc: &str) { - if self.is_enabled() { - let id = Ident::new(desc, Span::call_site()); - self.add(quote! { #id }) - } - } - - fn special_member(&mut self, kind: SpecialMemberKind) { - let kind_str = match kind { - SpecialMemberKind::DefaultConstructor => "default_ctor", - SpecialMemberKind::CopyConstructor => "copy_ctor", - SpecialMemberKind::MoveConstructor => "move_ctor", - SpecialMemberKind::Destructor => "dtor", - SpecialMemberKind::AssignmentOperator => "assignment_operator", - }; - self.add(quote! { - special_member(#kind_str) - }) - } - - fn original_name(&mut self, name: &str) { - self.add(quote! { - original_name(#name) - }) - } - - fn ret_type_reference(&mut self) { - self.add_ident("ret_type_reference") - } - - fn ret_type_rvalue_reference(&mut self) { - self.add_ident("ret_type_rvalue_reference") - } - - fn arg_type_reference(&mut self, arg_name: &Ident) { - self.add(quote! { - arg_type_reference(#arg_name) - }) - } - - fn field_type_reference(&mut self) { - self.add_ident("reference") - } - - fn field_type_rvalue_reference(&mut self) { - self.add_ident("rvalue_reference") - } - - fn is_virtual(&mut self) { - self.add_ident("bindgen_virtual") - } - - fn arg_type_rvalue_reference(&mut self, arg_name: &Ident) { - self.add(quote! { - arg_type_rvalue_reference(#arg_name) - }) - } - - fn is_pure_virtual(&mut self) { - self.add_ident("pure_virtual") - } - - fn visibility(&mut self, visibility: Visibility) { - match visibility { - Visibility::Protected => self.add_ident("visibility_protected"), - Visibility::Private => self.add_ident("visibility_private"), - _ => {} - } - } - - fn incomprehensible_param_in_arg_or_return(&mut self) { - self.add_ident("incomprehensible_param_in_arg_or_return") - } - - fn discards_template_param(&mut self) { - self.add_ident("unused_template_param") - } - - fn deleted_fn(&mut self) { - self.add_ident("deleted") - } - - fn defaulted_fn(&mut self) { - self.add_ident("defaulted") - } - - fn layout(&mut self, layout: &Layout) { - let sz = ast_ty::int_expr(layout.size as i64); - let align = ast_ty::int_expr(layout.align as i64); - let packed = if layout.packed { - quote! { true } - } else { - quote! { false } - }; - self.add(quote! { - layout(#sz, #align, #packed) - }) - } -} - -pub struct CppSemanticAttributeAdder<'a> { - enabled: bool, - attrs: &'a mut Vec<TokenStream>, -} - -impl<'a> CppSemanticAttributeAdder<'a> { - pub(crate) fn new( - opts: &BindgenOptions, - attrs: &'a mut Vec<TokenStream>, - ) -> Self { - Self { - enabled: opts.cpp_semantic_attributes, - attrs, - } - } -} - -impl<'a> CppSemanticAttributeCreator for CppSemanticAttributeAdder<'a> { - fn do_add(&mut self, ts: TokenStream) { - self.attrs.push(ts) - } - - fn is_enabled(&self) -> bool { - self.enabled - } -} - -pub struct CppSemanticAttributeSingle { - enabled: bool, - attr: TokenStream, -} - -impl CppSemanticAttributeSingle { - pub(crate) fn new(opts: &BindgenOptions) -> Self { - Self { - enabled: opts.cpp_semantic_attributes, - attr: quote! {}, - } - } - - pub(crate) fn result(self) -> TokenStream { - self.attr - } -} - -impl CppSemanticAttributeCreator for CppSemanticAttributeSingle { - fn do_add(&mut self, ts: TokenStream) { - self.attr = ts; - } - - fn is_enabled(&self) -> bool { - self.enabled - } -} - /// Generates a proper type for a field or type with a given `Layout`, that is, /// a type with the correct size and alignment restrictions. -pub(crate) fn blob(ctx: &BindgenContext, layout: Layout) -> TokenStream { +pub(crate) fn blob(ctx: &BindgenContext, layout: Layout) -> syn::Type { let opaque = layout.opaque(); // FIXME(emilio, #412): We fall back to byte alignment, but there are // some things that legitimately are more than 8-byte aligned. // // Eventually we should be able to `unwrap` here, but... - let ty_name = match opaque.known_rust_type_for_array(ctx) { + let ty = match opaque.known_rust_type_for_array(ctx) { Some(ty) => ty, None => { warn!("Found unknown alignment on code generation!"); - "u8" + syn::parse_quote! { u8 } } }; - let ty_name = Ident::new(ty_name, Span::call_site()); - let data_len = opaque.array_size(ctx).unwrap_or(layout.size); if data_len == 1 { - quote! { - #ty_name - } + ty } else { - quote! { - [ #ty_name ; #data_len ] - } + syn::parse_quote! { [ #ty ; #data_len ] } } } @@ -282,80 +105,118 @@ pub(crate) fn blob(ctx: &BindgenContext, layout: Layout) -> TokenStream { pub(crate) fn integer_type( ctx: &BindgenContext, layout: Layout, -) -> Option<TokenStream> { - let name = Layout::known_type_for_size(ctx, layout.size)?; - let name = Ident::new(name, Span::call_site()); - Some(quote! { #name }) +) -> Option<syn::Type> { + Layout::known_type_for_size(ctx, layout.size) } /// Generates a bitfield allocation unit type for a type with the given `Layout`. -pub(crate) fn bitfield_unit( - ctx: &BindgenContext, - layout: Layout, -) -> TokenStream { - let mut tokens = quote! {}; +pub(crate) fn bitfield_unit(ctx: &BindgenContext, layout: Layout) -> syn::Type { + let size = layout.size; + let ty = syn::parse_quote! { __BindgenBitfieldUnit<[u8; #size]> }; if ctx.options().enable_cxx_namespaces { - tokens.append_all(quote! { root:: }); + return syn::parse_quote! { root::#ty }; } - let size = layout.size; - tokens.append_all(quote! { - __BindgenBitfieldUnit<[u8; #size]> - }); - - tokens + ty } pub(crate) mod ast_ty { use crate::ir::context::BindgenContext; use crate::ir::function::FunctionSig; use crate::ir::layout::Layout; - use crate::ir::ty::FloatKind; + use crate::ir::ty::{FloatKind, IntKind}; use proc_macro2::{self, TokenStream}; use std::str::FromStr; - pub(crate) fn c_void(ctx: &BindgenContext) -> TokenStream { + pub(crate) fn 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(); - quote! { - #prefix::c_void - } + syn::parse_quote! { #prefix::c_void } } None => { if ctx.options().use_core && ctx.options().rust_features.core_ffi_c_void { - quote! { ::core::ffi::c_void } + syn::parse_quote! { ::core::ffi::c_void } } else { - quote! { ::std::os::raw::c_void } + syn::parse_quote! { ::std::os::raw::c_void } } } } } - pub(crate) fn raw_type(ctx: &BindgenContext, name: &str) -> TokenStream { + pub(crate) fn 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(); - quote! { - #prefix::#ident - } + syn::parse_quote! { #prefix::#ident } } None => { if ctx.options().use_core && ctx.options().rust_features().core_ffi_c { - quote! { - ::core::ffi::#ident - } + syn::parse_quote! { ::core::ffi::#ident } } else { - quote! { - ::std::os::raw::#ident - } + syn::parse_quote! { ::std::os::raw::#ident } + } + } + } + } + + 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"), + 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(ctx, 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 ctx.options().rust_features.i128_and_u128 { + syn::parse_quote! { u128 } + } else { + // Best effort thing, but wrong alignment + // unfortunately. + syn::parse_quote! { [u64; 2] } + } + } + IntKind::I128 => { + if ctx.options().rust_features.i128_and_u128 { + syn::parse_quote! { i128 } + } else { + syn::parse_quote! { [u64; 2] } } } } @@ -365,26 +226,26 @@ pub(crate) mod ast_ty { ctx: &BindgenContext, fk: FloatKind, layout: Option<Layout>, - ) -> TokenStream { + ) -> 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::Float, true) => quote! { f32 }, - (FloatKind::Double, true) => quote! { f64 }, + (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, _) => { match layout { Some(layout) => { match layout.size { - 4 => quote! { f32 }, - 8 => quote! { f64 }, + 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(ctx, layout) - .unwrap_or(quote! { f64 }), + .unwrap_or(syn::parse_quote! { f64 }), } } None => { @@ -392,15 +253,15 @@ pub(crate) mod ast_ty { false, "How didn't we know the layout for a primitive type?" ); - quote! { f64 } + syn::parse_quote! { f64 } } } } (FloatKind::Float128, _) => { if ctx.options().rust_features.i128_and_u128 { - quote! { u128 } + syn::parse_quote! { u128 } } else { - quote! { [u64; 2] } + syn::parse_quote! { [u64; 2] } } } } @@ -418,12 +279,6 @@ pub(crate) mod ast_ty { quote!(#val) } - pub(crate) fn byte_array_expr(bytes: &[u8]) -> TokenStream { - let mut bytes: Vec<_> = bytes.to_vec(); - bytes.push(0); - quote! { [ #(#bytes),* ] } - } - pub(crate) fn cstr_expr(mut string: String) -> TokenStream { string.push('\0'); let b = proc_macro2::Literal::byte_string(string.as_bytes()); |