summaryrefslogtreecommitdiff
path: root/src/codegen/helpers.rs
diff options
context:
space:
mode:
authorChristian Poveda <christian.poveda@ferrous-systems.com>2022-09-23 21:36:14 -0500
committerChristian Poveda <christian.poveda@ferrous-systems.com>2022-10-04 20:47:17 -0500
commit0296f9e86c7756e718b6b82836ce1e09b5f8d08a (patch)
treeb5954c6680b243c0b1671a80ea973ef90877e462 /src/codegen/helpers.rs
parenta900f8f863d1313ad76603234aaeea22bb9ba7b3 (diff)
split the repo into a workspace
remove `clap` dependency :tada: update the book installation instructions
Diffstat (limited to 'src/codegen/helpers.rs')
-rw-r--r--src/codegen/helpers.rs309
1 files changed, 0 insertions, 309 deletions
diff --git a/src/codegen/helpers.rs b/src/codegen/helpers.rs
deleted file mode 100644
index 5bf36acb..00000000
--- a/src/codegen/helpers.rs
+++ /dev/null
@@ -1,309 +0,0 @@
-//! Helpers for code generation that don't need macro expansion.
-
-use crate::ir::context::BindgenContext;
-use crate::ir::layout::Layout;
-use proc_macro2::{Ident, Span, TokenStream};
-use quote::TokenStreamExt;
-
-pub mod attributes {
- use proc_macro2::{Ident, Span, TokenStream};
- use std::str::FromStr;
-
- pub fn repr(which: &str) -> TokenStream {
- let which = Ident::new(which, Span::call_site());
- quote! {
- #[repr( #which )]
- }
- }
-
- pub fn repr_list(which_ones: &[&str]) -> TokenStream {
- let which_ones = which_ones
- .iter()
- .cloned()
- .map(|one| TokenStream::from_str(one).expect("repr to be valid"));
- quote! {
- #[repr( #( #which_ones ),* )]
- }
- }
-
- pub fn derives(which_ones: &[&str]) -> TokenStream {
- let which_ones = which_ones
- .iter()
- .cloned()
- .map(|one| TokenStream::from_str(one).expect("derive to be valid"));
- quote! {
- #[derive( #( #which_ones ),* )]
- }
- }
-
- pub fn inline() -> TokenStream {
- quote! {
- #[inline]
- }
- }
-
- pub fn must_use() -> TokenStream {
- quote! {
- #[must_use]
- }
- }
-
- pub fn non_exhaustive() -> TokenStream {
- quote! {
- #[non_exhaustive]
- }
- }
-
- pub fn doc(comment: String) -> TokenStream {
- // NOTE(emilio): By this point comments are already preprocessed and in
- // `///` form. Quote turns them into `#[doc]` comments, but oh well.
- TokenStream::from_str(&comment).unwrap()
- }
-
- pub fn link_name(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 = format!("\u{1}{}", name);
- quote! {
- #[link_name = #name]
- }
- }
-}
-
-/// 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 fn blob(ctx: &BindgenContext, layout: Layout) -> TokenStream {
- 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) {
- Some(ty) => ty,
- None => {
- warn!("Found unknown alignment on code generation!");
- "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
- }
- } else {
- quote! {
- [ #ty_name ; #data_len ]
- }
- }
-}
-
-/// Integer type of the same size as the given `Layout`.
-pub 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 })
-}
-
-/// Generates a bitfield allocation unit type for a type with the given `Layout`.
-pub fn bitfield_unit(ctx: &BindgenContext, layout: Layout) -> TokenStream {
- let mut tokens = quote! {};
-
- if ctx.options().enable_cxx_namespaces {
- tokens.append_all(quote! { root:: });
- }
-
- let size = layout.size;
- tokens.append_all(quote! {
- __BindgenBitfieldUnit<[u8; #size]>
- });
-
- tokens
-}
-
-pub mod ast_ty {
- use crate::ir::context::BindgenContext;
- use crate::ir::function::FunctionSig;
- use crate::ir::layout::Layout;
- use crate::ir::ty::FloatKind;
- use proc_macro2::{self, TokenStream};
- use std::str::FromStr;
-
- pub fn c_void(ctx: &BindgenContext) -> TokenStream {
- // 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
- }
- }
- None => {
- if ctx.options().use_core &&
- ctx.options().rust_features.core_ffi_c_void
- {
- quote! { ::core::ffi::c_void }
- } else {
- quote! { ::std::os::raw::c_void }
- }
- }
- }
- }
-
- pub fn raw_type(ctx: &BindgenContext, name: &str) -> TokenStream {
- 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
- }
- }
- None => {
- if ctx.options().use_core &&
- ctx.options().rust_features().core_ffi_c
- {
- quote! {
- ::core::ffi::#ident
- }
- } else {
- quote! {
- ::std::os::raw::#ident
- }
- }
- }
- }
- }
-
- pub fn float_kind_rust_type(
- ctx: &BindgenContext,
- fk: FloatKind,
- layout: Option<Layout>,
- ) -> TokenStream {
- // 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, 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 },
- // TODO(emilio): If rust ever gains f128 we should
- // use it here and below.
- _ => super::integer_type(ctx, layout)
- .unwrap_or(quote! { f64 }),
- }
- }
- None => {
- debug_assert!(
- false,
- "How didn't we know the layout for a primitive type?"
- );
- quote! { f64 }
- }
- }
- }
- (FloatKind::Float128, _) => {
- if ctx.options().rust_features.i128_and_u128 {
- quote! { u128 }
- } else {
- quote! { [u64; 2] }
- }
- }
- }
- }
-
- pub 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 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 fn byte_array_expr(bytes: &[u8]) -> TokenStream {
- let mut bytes: Vec<_> = bytes.to_vec();
- bytes.push(0);
- quote! { [ #(#bytes),* ] }
- }
-
- pub fn cstr_expr(mut string: String) -> TokenStream {
- string.push('\0');
- let b = proc_macro2::Literal::byte_string(string.as_bytes());
- quote! {
- #b
- }
- }
-
- pub fn float_expr(ctx: &BindgenContext, f: f64) -> Result<TokenStream, ()> {
- if f.is_finite() {
- let val = proc_macro2::Literal::f64_unsuffixed(f);
-
- return Ok(quote!(#val));
- }
-
- let prefix = ctx.trait_prefix();
-
- if f.is_nan() {
- return Ok(quote! {
- ::#prefix::f64::NAN
- });
- }
-
- if f.is_infinite() {
- return Ok(if f.is_sign_positive() {
- quote! {
- ::#prefix::f64::INFINITY
- }
- } else {
- quote! {
- ::#prefix::f64::NEG_INFINITY
- }
- });
- }
-
- warn!("Unknown non-finite float number: {:?}", f);
- Err(())
- }
-
- pub fn arguments_from_signature(
- signature: &FunctionSig,
- ctx: &BindgenContext,
- ) -> Vec<TokenStream> {
- let mut unnamed_arguments = 0;
- signature
- .argument_types()
- .iter()
- .map(|&(ref name, _ty)| match *name {
- Some(ref name) => {
- let name = ctx.rust_ident(name);
- quote! { #name }
- }
- None => {
- unnamed_arguments += 1;
- let name =
- ctx.rust_ident(format!("arg{}", unnamed_arguments));
- quote! { #name }
- }
- })
- .collect()
- }
-}