aboutsummaryrefslogtreecommitdiff
path: root/codegen/helpers.rs
diff options
context:
space:
mode:
Diffstat (limited to 'codegen/helpers.rs')
-rw-r--r--codegen/helpers.rs317
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());