Skip to content

Commit 39c7ae0

Browse files
author
bors-servo
authored
Auto merge of #1271 - emilio:repr-align, r=upsuper
codegen: Support repr(align) Fixes #917.
2 parents f36f4e3 + 1923985 commit 39c7ae0

14 files changed

+128
-27
lines changed

Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ name = "bindgen"
1313
readme = "README.md"
1414
repository = "https://github.com/rust-lang-nursery/rust-bindgen"
1515
documentation = "https://docs.rs/bindgen"
16-
version = "0.33.1"
16+
version = "0.34.0"
1717
build = "build.rs"
1818

1919
include = [

src/codegen/impl_partialeq.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub fn gen_partialeq_impl(
2020
&self._bindgen_opaque_blob[..] == &other._bindgen_opaque_blob[..]
2121
});
2222
} else if comp_info.kind() == CompKind::Union {
23-
assert!(!ctx.options().rust_features().untagged_union());
23+
assert!(!ctx.options().rust_features().untagged_union);
2424
tokens.push(quote! {
2525
&self.bindgen_union_field[..] == &other.bindgen_union_field[..]
2626
});

src/codegen/mod.rs

+20-4
Original file line numberDiff line numberDiff line change
@@ -1527,13 +1527,16 @@ impl CodeGenerator for CompInfo {
15271527
});
15281528
}
15291529

1530+
let mut explicit_align = None;
15301531
if is_opaque {
15311532
// Opaque item should not have generated methods, fields.
15321533
debug_assert!(fields.is_empty());
15331534
debug_assert!(methods.is_empty());
15341535

15351536
match layout {
15361537
Some(l) => {
1538+
explicit_align = Some(l.align);
1539+
15371540
let ty = helpers::blob(l);
15381541
fields.push(quote! {
15391542
pub _bindgen_opaque_blob: #ty ,
@@ -1555,6 +1558,7 @@ impl CodeGenerator for CompInfo {
15551558
if layout.align == 1 {
15561559
packed = true;
15571560
} else {
1561+
explicit_align = Some(layout.align);
15581562
let ty = helpers::blob(Layout::new(0, layout.align));
15591563
fields.push(quote! {
15601564
pub __bindgen_align: #ty ,
@@ -1637,6 +1641,18 @@ impl CodeGenerator for CompInfo {
16371641
attributes.push(attributes::repr("C"));
16381642
}
16391643

1644+
if ctx.options().rust_features().repr_align {
1645+
if let Some(explicit) = explicit_align {
1646+
// Ensure that the struct has the correct alignment even in
1647+
// presence of alignas.
1648+
let explicit = helpers::ast_ty::int_expr(explicit as i64);
1649+
attributes.push(quote! {
1650+
#[repr(align(#explicit))]
1651+
});
1652+
}
1653+
}
1654+
1655+
16401656
let mut derives = vec![];
16411657
if item.can_derive_debug(ctx) {
16421658
derives.push("Debug");
@@ -1655,7 +1671,7 @@ impl CodeGenerator for CompInfo {
16551671
if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() {
16561672
derives.push("Copy");
16571673

1658-
if ctx.options().rust_features().builtin_clone_impls() ||
1674+
if ctx.options().rust_features().builtin_clone_impls ||
16591675
used_template_params.is_some()
16601676
{
16611677
// FIXME: This requires extra logic if you have a big array in a
@@ -1996,7 +2012,7 @@ impl MethodCodegen for Method {
19962012
_ => panic!("How in the world?"),
19972013
};
19982014

1999-
if let (Abi::ThisCall, false) = (signature.abi(), ctx.options().rust_features().thiscall_abi()) {
2015+
if let (Abi::ThisCall, false) = (signature.abi(), ctx.options().rust_features().thiscall_abi) {
20002016
return;
20012017
}
20022018

@@ -3167,7 +3183,7 @@ impl TryToRustTy for FunctionSig {
31673183
let abi = self.abi();
31683184

31693185
match abi {
3170-
Abi::ThisCall if !ctx.options().rust_features().thiscall_abi() => {
3186+
Abi::ThisCall if !ctx.options().rust_features().thiscall_abi => {
31713187
warn!("Skipping function with thiscall ABI that isn't supported by the configured Rust target");
31723188
Ok(quote::Tokens::new())
31733189
}
@@ -3264,7 +3280,7 @@ impl CodeGenerator for Function {
32643280
}
32653281

32663282
let abi = match signature.abi() {
3267-
Abi::ThisCall if !ctx.options().rust_features().thiscall_abi() => {
3283+
Abi::ThisCall if !ctx.options().rust_features().thiscall_abi => {
32683284
warn!("Skipping function with thiscall ABI that isn't supported by the configured Rust target");
32693285
return;
32703286
}

src/features.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ macro_rules! rust_target_base {
9292
=> Stable_1_19 => 1.19;
9393
/// Rust stable 1.21
9494
=> Stable_1_21 => 1.21;
95+
/// Rust stable 1.24
96+
=> Stable_1_24 => 1.24;
9597
/// Nightly rust
9698
=> Nightly => nightly;
9799
);
@@ -111,7 +113,10 @@ macro_rules! rust_feature_def {
111113
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
112114
pub struct RustFeatures {
113115
$(
114-
$feature: bool,
116+
$(
117+
#[$attr]
118+
)*
119+
pub $feature: bool,
115120
)*
116121
}
117122

@@ -124,15 +129,6 @@ macro_rules! rust_feature_def {
124129
)*
125130
}
126131
}
127-
128-
$(
129-
$(
130-
#[$attr]
131-
)*
132-
pub fn $feature(&self) -> bool {
133-
self.$feature
134-
}
135-
)*
136132
}
137133
}
138134
}
@@ -144,6 +140,8 @@ rust_feature_def!(
144140
=> thiscall_abi;
145141
/// builtin impls for `Clone` ([PR](https://github.com/rust-lang/rust/pull/43690))
146142
=> builtin_clone_impls;
143+
/// repr(align) https://github.com/rust-lang/rust/pull/47006
144+
=> repr_align;
147145
);
148146

149147
impl From<RustTarget> for RustFeatures {
@@ -158,6 +156,10 @@ impl From<RustTarget> for RustFeatures {
158156
features.builtin_clone_impls = true;
159157
}
160158

159+
if rust_target >= RustTarget::Stable_1_24 {
160+
features.repr_align = true;
161+
}
162+
161163
if rust_target >= RustTarget::Nightly {
162164
features.thiscall_abi = true;
163165
}

src/ir/analysis/derive_copy.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveCopy<'ctx> {
234234
}
235235

236236
if info.kind() == CompKind::Union {
237-
if !self.ctx.options().rust_features().untagged_union() {
237+
if !self.ctx.options().rust_features().untagged_union {
238238
// NOTE: If there's no template parameters we can derive
239239
// copy unconditionally, since arrays are magical for
240240
// rustc, and __BindgenUnionField always implements

src/ir/analysis/derive_debug.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
150150
});
151151
return if layout_can_derive &&
152152
!(ty.is_union() &&
153-
self.ctx.options().rust_features().untagged_union()) {
153+
self.ctx.options().rust_features().untagged_union) {
154154
trace!(" we can trivially derive Debug for the layout");
155155
ConstrainResult::Same
156156
} else {
@@ -235,7 +235,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
235235
);
236236

237237
if info.kind() == CompKind::Union {
238-
if self.ctx.options().rust_features().untagged_union() {
238+
if self.ctx.options().rust_features().untagged_union {
239239
trace!(" cannot derive Debug for Rust unions");
240240
return self.insert(id);
241241
}

src/ir/analysis/derive_default.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> {
177177
});
178178
return if layout_can_derive &&
179179
!(ty.is_union() &&
180-
self.ctx.options().rust_features().untagged_union()) {
180+
self.ctx.options().rust_features().untagged_union) {
181181
trace!(" we can trivially derive Default for the layout");
182182
ConstrainResult::Same
183183
} else {
@@ -271,7 +271,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> {
271271
}
272272

273273
if info.kind() == CompKind::Union {
274-
if self.ctx.options().rust_features().untagged_union() {
274+
if self.ctx.options().rust_features().untagged_union {
275275
trace!(" cannot derive Default for Rust unions");
276276
return self.insert(id);
277277
}

src/ir/analysis/derive_hash.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
137137
});
138138
return if layout_can_derive &&
139139
!(ty.is_union() &&
140-
self.ctx.options().rust_features().untagged_union()) {
140+
self.ctx.options().rust_features().untagged_union) {
141141
trace!(" we can trivially derive Hash for the layout");
142142
ConstrainResult::Same
143143
} else {
@@ -257,7 +257,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
257257
}
258258

259259
if info.kind() == CompKind::Union {
260-
if self.ctx.options().rust_features().untagged_union() {
260+
if self.ctx.options().rust_features().untagged_union {
261261
trace!(" cannot derive Hash for Rust unions");
262262
return self.insert(id);
263263
}

src/ir/analysis/derive_partialeq_or_partialord.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> {
119119
trace!("ty: {:?}", ty);
120120
if item.is_opaque(self.ctx, &()) {
121121
if ty.is_union()
122-
&& self.ctx.options().rust_features().untagged_union()
122+
&& self.ctx.options().rust_features().untagged_union
123123
{
124124
trace!(
125125
" cannot derive `PartialEq`/`PartialOrd` for Rust unions"
@@ -242,7 +242,7 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> {
242242
}
243243

244244
if info.kind() == CompKind::Union {
245-
if self.ctx.options().rust_features().untagged_union() {
245+
if self.ctx.options().rust_features().untagged_union {
246246
trace!(
247247
" cannot derive `PartialEq`/`PartialOrd` for Rust unions"
248248
);

src/ir/comp.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1543,7 +1543,7 @@ impl CompInfo {
15431543
/// 1. Current RustTarget allows for `untagged_union`
15441544
/// 2. Each field can derive `Copy`
15451545
pub fn can_be_rust_union(&self, ctx: &BindgenContext) -> bool {
1546-
if !ctx.options().rust_features().untagged_union() {
1546+
if !ctx.options().rust_features().untagged_union {
15471547
return false;
15481548
}
15491549

src/lib.rs

+6
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,12 @@ impl Builder {
600600
self
601601
}
602602

603+
/// Disable support for native Rust unions, if supported.
604+
pub fn disable_untagged_union(mut self) -> Self {
605+
self.options.rust_features.untagged_union = false;
606+
self
607+
}
608+
603609
/// Set the output graphviz file.
604610
pub fn emit_ir_graphviz<T: Into<String>>(mut self, path: T) -> Builder {
605611
let path = path.into();
+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
4+
5+
#[repr(C)]
6+
#[repr(align(8))]
7+
#[derive(Debug, Default, Copy, Clone)]
8+
pub struct a {
9+
pub b: ::std::os::raw::c_int,
10+
pub c: ::std::os::raw::c_int,
11+
pub __bindgen_align: [u64; 0usize],
12+
}
13+
#[test]
14+
fn bindgen_test_layout_a() {
15+
assert_eq!(
16+
::std::mem::size_of::<a>(),
17+
8usize,
18+
concat!("Size of: ", stringify!(a))
19+
);
20+
assert_eq!(
21+
::std::mem::align_of::<a>(),
22+
8usize,
23+
concat!("Alignment of ", stringify!(a))
24+
);
25+
assert_eq!(
26+
unsafe { &(*(::std::ptr::null::<a>())).b as *const _ as usize },
27+
0usize,
28+
concat!("Offset of field: ", stringify!(a), "::", stringify!(b))
29+
);
30+
assert_eq!(
31+
unsafe { &(*(::std::ptr::null::<a>())).c as *const _ as usize },
32+
4usize,
33+
concat!("Offset of field: ", stringify!(a), "::", stringify!(c))
34+
);
35+
}
36+
#[repr(C)]
37+
#[repr(align(8))]
38+
#[derive(Debug, Default, Copy, Clone)]
39+
pub struct b {
40+
pub b: ::std::os::raw::c_int,
41+
pub c: ::std::os::raw::c_int,
42+
pub __bindgen_align: [u64; 0usize],
43+
}
44+
#[test]
45+
fn bindgen_test_layout_b() {
46+
assert_eq!(
47+
::std::mem::size_of::<b>(),
48+
8usize,
49+
concat!("Size of: ", stringify!(b))
50+
);
51+
assert_eq!(
52+
::std::mem::align_of::<b>(),
53+
8usize,
54+
concat!("Alignment of ", stringify!(b))
55+
);
56+
assert_eq!(
57+
unsafe { &(*(::std::ptr::null::<b>())).b as *const _ as usize },
58+
0usize,
59+
concat!("Offset of field: ", stringify!(b), "::", stringify!(b))
60+
);
61+
assert_eq!(
62+
unsafe { &(*(::std::ptr::null::<b>())).c as *const _ as usize },
63+
4usize,
64+
concat!("Offset of field: ", stringify!(b), "::", stringify!(c))
65+
);
66+
}

tests/headers/repr-align.hpp

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// bindgen-flags: --rust-target 1.24 -- -std=c++11
2+
3+
struct alignas(8) a {
4+
int b;
5+
int c;
6+
};
7+
8+
struct alignas(double) b {
9+
int b;
10+
int c;
11+
};

0 commit comments

Comments
 (0)