Skip to content

Commit

Permalink
Wrap the array representation of opaque types in a #[repr(C)] struct
Browse files Browse the repository at this point in the history
  • Loading branch information
GKFX authored and pvdrz committed Dec 2, 2024
1 parent b23d978 commit 0267b0e
Show file tree
Hide file tree
Showing 15 changed files with 157 additions and 23 deletions.
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);
18 changes: 15 additions & 3 deletions bindgen/codegen/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,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(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 @@ -93,7 +100,12 @@ pub(crate) fn blob(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 @@ -581,6 +581,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 @@ -2275,7 +2278,7 @@ impl CodeGenerator for CompInfo {

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

let ty = helpers::blob(l);
let ty = helpers::blob(ctx, l, false);
fields.push(quote! {
pub _bindgen_opaque_blob: #ty ,
});
Expand Down Expand Up @@ -2326,7 +2329,7 @@ impl CodeGenerator for CompInfo {
}

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

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

Expand Down Expand Up @@ -4125,7 +4129,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(layout))
Ok(helpers::blob(ctx, layout, true))
} else {
Err(Error::NoLayoutForOpaqueBlob)
}
Expand Down Expand Up @@ -5573,6 +5577,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 @@ -393,7 +393,7 @@ impl<'a> StructLayoutTracker<'a> {
}

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

self.padding_count += 1;
Expand Down
5 changes: 4 additions & 1 deletion bindgen/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,10 @@ 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) => { raw_ref_macros: #80886 },
Stable_1_51(51) => {
raw_ref_macros: #80886,
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 @@ -2607,6 +2611,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

0 comments on commit 0267b0e

Please sign in to comment.