Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrap the array representation of opaque types in a #[repr(C)] struct #2880

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bindgen-integration/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ fn test_item_rename() {
#[test]
fn test_matching_with_rename() {
assert_eq!(bindings::enum_to_be_constified_THREE, 3);
assert_eq!(unsafe { bindings::TEMPLATED_CONST_VALUE.len() }, 30);
assert_eq!(unsafe { bindings::TEMPLATED_CONST_VALUE.0.len() }, 30);
}

#[test]
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 13 additions & 3 deletions bindgen-tests/tests/expectations/tests/non-type-params.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 11 additions & 1 deletion bindgen-tests/tests/expectations/tests/nsBaseHashtable.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 11 additions & 1 deletion bindgen-tests/tests/expectations/tests/size_t_template.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions bindgen-tests/tests/expectations/tests/va_list_aarch64_linux.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions bindgen-tests/tests/headers/va_list_aarch64_linux.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// bindgen-flags: -- --target=aarch64-unknown-linux-gnu

typedef __builtin_va_list va_list;
int vprintf(const char* format, va_list vlist);
16 changes: 15 additions & 1 deletion bindgen/codegen/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,16 @@ pub(crate) mod attributes {

/// 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) -> syn::Type {
/// 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 opaque = layout.opaque();

// FIXME(emilio, #412): We fall back to byte alignment, but there are
Expand All @@ -98,7 +107,12 @@ pub(crate) fn blob(ctx: &BindgenContext, layout: Layout) -> syn::Type {

if data_len == 1 {
ty
} else if ffi_safe && ctx.options().rust_features().min_const_generics {
ctx.generated_opaque_array();
syn::parse_quote! { __BindgenOpaqueArray<#ty, #data_len> }
} else {
// This is not FFI safe as an argument; the struct above is
// preferable.
syn::parse_quote! { [ #ty ; #data_len ] }
}
}
Expand Down
35 changes: 29 additions & 6 deletions bindgen/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,9 @@ impl CodeGenerator for Module {
if ctx.need_bindgen_complex_type() {
utils::prepend_complex_type(&mut *result);
}
if ctx.need_opaque_array_type() {
utils::prepend_opaque_array_type(&mut *result);
}
if result.saw_objc {
utils::prepend_objc_header(ctx, &mut *result);
}
Expand Down Expand Up @@ -2162,7 +2165,7 @@ impl CodeGenerator for CompInfo {

if has_address {
let layout = Layout::new(1, 1);
let ty = helpers::blob(ctx, Layout::new(1, 1));
let ty = helpers::blob(ctx, Layout::new(1, 1), false);
struct_layout.saw_field_with_layout(
"_address",
layout,
Expand All @@ -2179,7 +2182,7 @@ impl CodeGenerator for CompInfo {
Some(l) => {
explicit_align = Some(l.align);

let ty = helpers::blob(ctx, l);
let ty = helpers::blob(ctx, l, false);
fields.push(quote! {
pub _bindgen_opaque_blob: #ty ,
});
Expand All @@ -2205,6 +2208,7 @@ impl CodeGenerator for CompInfo {
let ty = helpers::blob(
ctx,
Layout::new(0, layout.align),
false,
);
fields.push(quote! {
pub __bindgen_align: #ty ,
Expand All @@ -2222,7 +2226,7 @@ impl CodeGenerator for CompInfo {
}

if !struct_layout.is_rust_union() {
let ty = helpers::blob(ctx, layout);
let ty = helpers::blob(ctx, layout, false);
fields.push(quote! {
pub bindgen_union_field: #ty ,
})
Expand Down Expand Up @@ -3903,7 +3907,7 @@ pub(crate) trait TryToOpaque {
extra: &Self::Extra,
) -> error::Result<syn::Type> {
self.try_get_layout(ctx, extra)
.map(|layout| helpers::blob(ctx, layout))
.map(|layout| helpers::blob(ctx, layout, true))
}
}

Expand All @@ -3929,7 +3933,7 @@ pub(crate) trait ToOpaque: TryToOpaque {
extra: &Self::Extra,
) -> syn::Type {
let layout = self.get_layout(ctx, extra);
helpers::blob(ctx, layout)
helpers::blob(ctx, layout, true)
}
}

Expand Down Expand Up @@ -3980,7 +3984,7 @@ where
) -> error::Result<syn::Type> {
self.try_to_rust_ty(ctx, extra).or_else(|_| {
if let Ok(layout) = self.try_get_layout(ctx, extra) {
Ok(helpers::blob(ctx, layout))
Ok(helpers::blob(ctx, layout, true))
} else {
Err(error::Error::NoLayoutForOpaqueBlob)
}
Expand Down Expand Up @@ -5438,6 +5442,25 @@ pub(crate) mod utils {
result.extend(old_items);
}

pub(crate) fn prepend_opaque_array_type(
result: &mut Vec<proc_macro2::TokenStream>,
) {
let ty = quote! {
/// If Bindgen could only determine the size and alignment of a
/// type, it is represented like this.
#[derive(PartialEq, Copy, Clone, Debug, Hash)]
#[repr(C)]
pub struct __BindgenOpaqueArray<T: Copy, const N: usize>(pub [T; N]);
impl<T: Copy + Default, const N: usize> Default for __BindgenOpaqueArray<T, N> {
fn default() -> Self {
Self([<T as Default>::default(); N])
}
}
};

result.insert(0, ty);
}

pub(crate) fn build_path(
item: &Item,
ctx: &BindgenContext,
Expand Down
2 changes: 1 addition & 1 deletion bindgen/codegen/struct_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ impl<'a> StructLayoutTracker<'a> {
}

fn padding_field(&mut self, layout: Layout) -> proc_macro2::TokenStream {
let ty = helpers::blob(self.ctx, layout);
let ty = helpers::blob(self.ctx, layout, false);
let padding_count = self.padding_count;

self.padding_count += 1;
Expand Down
1 change: 1 addition & 0 deletions bindgen/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ define_rust_targets! {
Stable_1_71(71) => { c_unwind_abi: #106075 },
Stable_1_68(68) => { abi_efiapi: #105795 },
Stable_1_64(64) => { core_ffi_c: #94503 },
Stable_1_51(51) => { min_const_generics: #74878 },
Stable_1_59(59) => { const_cstr: #54745 },
Stable_1_47(47) => { larger_arrays: #74060 },
Stable_1_43(43) => { associated_constants: #68952 },
Expand Down
14 changes: 14 additions & 0 deletions bindgen/ir/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,9 @@ pub(crate) struct BindgenContext {
/// The options given by the user via cli or other medium.
options: BindgenOptions,

/// Whether an opaque array was generated
generated_opaque_array: Cell<bool>,

/// Whether a bindgen complex was generated
generated_bindgen_complex: Cell<bool>,

Expand Down Expand Up @@ -595,6 +598,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
options,
generated_bindgen_complex: Cell::new(false),
generated_bindgen_float16: Cell::new(false),
generated_opaque_array: Cell::new(false),
allowlisted: None,
blocklisted_types_implement_traits: Default::default(),
codegen_items: None,
Expand Down Expand Up @@ -2646,6 +2650,16 @@ If you encounter an error missing from this list, please file an issue or a PR!"
}
}

/// Call if an opaque array is generated
pub(crate) fn generated_opaque_array(&self) {
self.generated_opaque_array.set(true)
}

/// Whether we need to generate the opaque array type
pub(crate) fn need_opaque_array_type(&self) -> bool {
self.generated_opaque_array.get()
}

/// Call if a bindgen complex is generated
pub(crate) fn generated_bindgen_complex(&self) {
self.generated_bindgen_complex.set(true)
Expand Down
2 changes: 1 addition & 1 deletion bindgen/ir/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ pub(crate) enum TypeKind {
/// A compound type, that is, a class, struct, or union.
Comp(CompInfo),

/// An opaque type that we just don't understand. All usage of this shoulf
/// An opaque type that we just don't understand. All usage of this should
/// result in an opaque blob of bytes generated from the containing type's
/// layout.
Opaque,
Expand Down