Skip to content

Commit 6fc0a31

Browse files
author
bors-servo
authored
Auto merge of #1391 - emilio:u128, r=fitzgen
codegen: Generate u128 / i128 when available. This is the first step to fix #1370 / #1338 / etc. Fix for that will build up on this.
2 parents a54a9dc + c09c74e commit 6fc0a31

20 files changed

+250
-104
lines changed

src/codegen/helpers.rs

+38-15
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,14 @@ pub mod attributes {
5959

6060
/// Generates a proper type for a field or type with a given `Layout`, that is,
6161
/// a type with the correct size and alignment restrictions.
62-
pub fn blob(layout: Layout) -> quote::Tokens {
62+
pub fn blob(ctx: &BindgenContext, layout: Layout) -> quote::Tokens {
6363
let opaque = layout.opaque();
6464

6565
// FIXME(emilio, #412): We fall back to byte alignment, but there are
6666
// some things that legitimately are more than 8-byte aligned.
6767
//
6868
// Eventually we should be able to `unwrap` here, but...
69-
let ty_name = match opaque.known_rust_type_for_array() {
69+
let ty_name = match opaque.known_rust_type_for_array(ctx) {
7070
Some(ty) => ty,
7171
None => {
7272
warn!("Found unknown alignment on code generation!");
@@ -76,7 +76,7 @@ pub fn blob(layout: Layout) -> quote::Tokens {
7676

7777
let ty_name = Term::new(ty_name, Span::call_site());
7878

79-
let data_len = opaque.array_size().unwrap_or(layout.size);
79+
let data_len = opaque.array_size(ctx).unwrap_or(layout.size);
8080

8181
if data_len == 1 {
8282
quote! {
@@ -90,8 +90,8 @@ pub fn blob(layout: Layout) -> quote::Tokens {
9090
}
9191

9292
/// Integer type of the same size as the given `Layout`.
93-
pub fn integer_type(layout: Layout) -> Option<quote::Tokens> {
94-
let name = Layout::known_type_for_size(layout.size)?;
93+
pub fn integer_type(ctx: &BindgenContext, layout: Layout) -> Option<quote::Tokens> {
94+
let name = Layout::known_type_for_size(ctx, layout.size)?;
9595
let name = Term::new(name, Span::call_site());
9696
Some(quote! { #name })
9797
}
@@ -122,6 +122,7 @@ pub fn bitfield_unit(ctx: &BindgenContext, layout: Layout) -> quote::Tokens {
122122
pub mod ast_ty {
123123
use ir::context::BindgenContext;
124124
use ir::function::FunctionSig;
125+
use ir::layout::Layout;
125126
use ir::ty::FloatKind;
126127
use quote;
127128
use proc_macro2;
@@ -144,22 +145,44 @@ pub mod ast_ty {
144145
pub fn float_kind_rust_type(
145146
ctx: &BindgenContext,
146147
fk: FloatKind,
148+
layout: Option<Layout>,
147149
) -> quote::Tokens {
148-
// TODO: we probably should just take the type layout into
149-
// account?
150+
// TODO: we probably should take the type layout into account more
151+
// often?
150152
//
151153
// Also, maybe this one shouldn't be the default?
152-
//
153-
// FIXME: `c_longdouble` doesn't seem to be defined in some
154-
// systems, so we use `c_double` directly.
155154
match (fk, ctx.options().convert_floats) {
156155
(FloatKind::Float, true) => quote! { f32 },
157-
(FloatKind::Double, true) |
158-
(FloatKind::LongDouble, true) => quote! { f64 },
156+
(FloatKind::Double, true) => quote! { f64 },
159157
(FloatKind::Float, false) => raw_type(ctx, "c_float"),
160-
(FloatKind::Double, false) |
161-
(FloatKind::LongDouble, false) => raw_type(ctx, "c_double"),
162-
(FloatKind::Float128, _) => quote! { [u8; 16] },
158+
(FloatKind::Double, false) => raw_type(ctx, "c_double"),
159+
(FloatKind::LongDouble, _) => {
160+
match layout {
161+
Some(layout) => {
162+
match layout.size {
163+
4 => quote! { f32 },
164+
8 => quote! { f64 },
165+
// TODO(emilio): If rust ever gains f128 we should
166+
// use it here and below.
167+
_ => super::integer_type(ctx, layout).unwrap_or(quote! { f64 }),
168+
}
169+
}
170+
None => {
171+
debug_assert!(
172+
false,
173+
"How didn't we know the layout for a primitive type?"
174+
);
175+
quote! { f64 }
176+
}
177+
}
178+
}
179+
(FloatKind::Float128, _) => {
180+
if ctx.options().rust_features.i128_and_u128 {
181+
quote! { u128 }
182+
} else {
183+
quote! { [u64; 2] }
184+
}
185+
}
163186
}
164187
}
165188

src/codegen/impl_debug.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ impl<'a> ImplDebug<'a> for Item {
236236
let inner_type = ctx.resolve_type(inner).canonical_type(ctx);
237237
match *inner_type.kind() {
238238
TypeKind::Function(ref sig)
239-
if !sig.can_trivially_derive_debug() => {
239+
if !sig.can_trivially_derive_debug(ctx) => {
240240
Some((format!("{}: FunctionPointer", name), vec![]))
241241
}
242242
_ => debug_print(name, quote! { #name_ident }),

src/codegen/mod.rs

+27-17
Original file line numberDiff line numberDiff line change
@@ -1185,7 +1185,7 @@ impl Bitfield {
11851185
let bitfield_ty_layout = bitfield_ty.layout(ctx).expect(
11861186
"Bitfield without layout? Gah!",
11871187
);
1188-
let bitfield_int_ty = helpers::blob(bitfield_ty_layout);
1188+
let bitfield_int_ty = helpers::blob(ctx, bitfield_ty_layout);
11891189

11901190
let offset = self.offset_into_unit();
11911191
let width = self.width() as u8;
@@ -1367,7 +1367,7 @@ impl<'a> FieldCodegen<'a> for Bitfield {
13671367
let bitfield_ty_layout = bitfield_ty.layout(ctx).expect(
13681368
"Bitfield without layout? Gah!",
13691369
);
1370-
let bitfield_int_ty = match helpers::integer_type(bitfield_ty_layout) {
1370+
let bitfield_int_ty = match helpers::integer_type(ctx, bitfield_ty_layout) {
13711371
Some(int_ty) => {
13721372
*bitfield_representable_as_int = true;
13731373
int_ty
@@ -1547,7 +1547,7 @@ impl CodeGenerator for CompInfo {
15471547
}
15481548

15491549
let layout = layout.expect("Unable to get layout information?");
1550-
let ty = helpers::blob(layout);
1550+
let ty = helpers::blob(ctx, layout);
15511551

15521552
fields.push(if self.can_be_rust_union(ctx) {
15531553
quote! {
@@ -1572,7 +1572,7 @@ impl CodeGenerator for CompInfo {
15721572
Some(l) => {
15731573
explicit_align = Some(l.align);
15741574

1575-
let ty = helpers::blob(l);
1575+
let ty = helpers::blob(ctx, l);
15761576
fields.push(quote! {
15771577
pub _bindgen_opaque_blob: #ty ,
15781578
});
@@ -1595,7 +1595,7 @@ impl CodeGenerator for CompInfo {
15951595
} else {
15961596
explicit_align = Some(layout.align);
15971597
if !ctx.options().rust_features.repr_align {
1598-
let ty = helpers::blob(Layout::new(0, layout.align));
1598+
let ty = helpers::blob(ctx, Layout::new(0, layout.align));
15991599
fields.push(quote! {
16001600
pub __bindgen_align: #ty ,
16011601
});
@@ -1629,7 +1629,7 @@ impl CodeGenerator for CompInfo {
16291629
};
16301630

16311631
if has_address {
1632-
let ty = helpers::blob(Layout::new(1, 1));
1632+
let ty = helpers::blob(ctx, Layout::new(1, 1));
16331633
fields.push(quote! {
16341634
pub _address: #ty,
16351635
});
@@ -2800,7 +2800,7 @@ trait TryToOpaque {
28002800
extra: &Self::Extra,
28012801
) -> error::Result<quote::Tokens> {
28022802
self.try_get_layout(ctx, extra).map(|layout| {
2803-
helpers::blob(layout)
2803+
helpers::blob(ctx, layout)
28042804
})
28052805
}
28062806
}
@@ -2827,7 +2827,7 @@ trait ToOpaque: TryToOpaque {
28272827
extra: &Self::Extra,
28282828
) -> quote::Tokens {
28292829
let layout = self.get_layout(ctx, extra);
2830-
helpers::blob(layout)
2830+
helpers::blob(ctx, layout)
28312831
}
28322832
}
28332833

@@ -2885,7 +2885,7 @@ where
28852885
|_| if let Ok(layout) =
28862886
self.try_get_layout(ctx, extra)
28872887
{
2888-
Ok(helpers::blob(layout))
2888+
Ok(helpers::blob(ctx, layout))
28892889
} else {
28902890
Err(error::Error::NoLayoutForOpaqueBlob)
28912891
},
@@ -3037,7 +3037,7 @@ impl TryToRustTy for Type {
30373037
IntKind::LongLong => Ok(raw_type(ctx, "c_longlong")),
30383038
IntKind::ULongLong => Ok(raw_type(ctx, "c_ulonglong")),
30393039
IntKind::WChar { size } => {
3040-
let ty = Layout::known_type_for_size(size)
3040+
let ty = Layout::known_type_for_size(ctx, size)
30413041
.expect("Non-representable wchar_t?");
30423042
let ident = ctx.rust_ident_raw(ty);
30433043
Ok(quote! { #ident })
@@ -3059,17 +3059,27 @@ impl TryToRustTy for Type {
30593059
#ident
30603060
})
30613061
}
3062-
// FIXME: This doesn't generate the proper alignment, but we
3063-
// can't do better right now. We should be able to use
3064-
// i128/u128 when they're available.
3065-
IntKind::U128 | IntKind::I128 => {
3066-
Ok(quote! { [u64; 2] })
3062+
IntKind::U128 => {
3063+
Ok(if ctx.options().rust_features.i128_and_u128 {
3064+
quote! { u128 }
3065+
} else {
3066+
// Best effort thing, but wrong alignment
3067+
// unfortunately.
3068+
quote! { [u64; 2] }
3069+
})
3070+
}
3071+
IntKind::I128 => {
3072+
Ok(if ctx.options().rust_features.i128_and_u128 {
3073+
quote! { i128 }
3074+
} else {
3075+
quote! { [u64; 2] }
3076+
})
30673077
}
30683078
}
30693079
}
3070-
TypeKind::Float(fk) => Ok(float_kind_rust_type(ctx, fk)),
3080+
TypeKind::Float(fk) => Ok(float_kind_rust_type(ctx, fk, self.layout(ctx))),
30713081
TypeKind::Complex(fk) => {
3072-
let float_path = float_kind_rust_type(ctx, fk);
3082+
let float_path = float_kind_rust_type(ctx, fk, self.layout(ctx));
30733083

30743084
ctx.generated_bindgen_complex();
30753085
Ok(if ctx.options().enable_cxx_namespaces {

src/codegen/struct_layout.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -287,26 +287,31 @@ impl<'a> StructLayoutTracker<'a> {
287287
}
288288

289289
pub fn requires_explicit_align(&self, layout: Layout) -> bool {
290+
let repr_align = self.ctx.options().rust_features().repr_align;
291+
292+
// Always force explicit repr(align) for stuff more than 16-byte aligned
293+
// to work-around https://github.com/rust-lang/rust/issues/54341.
294+
//
295+
// Worst-case this just generates redundant alignment attributes.
296+
if repr_align && self.max_field_align >= 16 {
297+
return true;
298+
}
299+
290300
if self.max_field_align >= layout.align {
291301
return false;
292302
}
293-
// At this point we require explicit alignment, but we may not be able
294-
// to generate the right bits, let's double check.
295-
if self.ctx.options().rust_features().repr_align {
296-
return true;
297-
}
298303

299304
// We can only generate up-to a word of alignment unless we support
300305
// repr(align).
301-
layout.align <= self.ctx.target_pointer_size()
306+
repr_align || layout.align <= self.ctx.target_pointer_size()
302307
}
303308

304309
fn padding_bytes(&self, layout: Layout) -> usize {
305310
align_to(self.latest_offset, layout.align) - self.latest_offset
306311
}
307312

308313
fn padding_field(&mut self, layout: Layout) -> quote::Tokens {
309-
let ty = helpers::blob(layout);
314+
let ty = helpers::blob(self.ctx, layout);
310315
let padding_count = self.padding_count;
311316

312317
self.padding_count += 1;

src/features.rs

+6
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ macro_rules! rust_target_base {
9696
=> Stable_1_21 => 1.21;
9797
/// Rust stable 1.25
9898
=> Stable_1_25 => 1.25;
99+
/// Rust stable 1.26
100+
=> Stable_1_26 => 1.26;
99101
/// Nightly rust
100102
=> Nightly => nightly;
101103
);
@@ -172,6 +174,10 @@ rust_feature_def!(
172174
/// repr(align) ([PR](https://github.com/rust-lang/rust/pull/47006))
173175
=> repr_align;
174176
}
177+
Stable_1_26 {
178+
/// [i128 / u128 support](https://doc.rust-lang.org/std/primitive.i128.html)
179+
=> i128_and_u128;
180+
}
175181
Nightly {
176182
/// `thiscall` calling convention ([Tracking issue](https://github.com/rust-lang/rust/issues/42202))
177183
=> thiscall_abi;

src/ir/analysis/derive_copy.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveCopy<'ctx> {
149149

150150
if item.is_opaque(self.ctx, &()) {
151151
let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| {
152-
l.opaque().can_trivially_derive_copy()
152+
l.opaque().can_trivially_derive_copy(self.ctx)
153153
});
154154
return if layout_can_derive {
155155
trace!(" we can trivially derive Copy for the layout");

src/ir/analysis/derive_debug.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
146146

147147
if item.is_opaque(self.ctx, &()) {
148148
let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| {
149-
l.opaque().can_trivially_derive_debug()
149+
l.opaque().can_trivially_derive_debug(self.ctx)
150150
});
151151
return if layout_can_derive &&
152152
!(ty.is_union() &&
@@ -242,7 +242,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
242242
}
243243

244244
if ty.layout(self.ctx).map_or(true, |l| {
245-
l.opaque().can_trivially_derive_debug()
245+
l.opaque().can_trivially_derive_debug(self.ctx)
246246
})
247247
{
248248
trace!(" union layout can trivially derive Debug");
@@ -299,7 +299,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
299299
let inner_type =
300300
self.ctx.resolve_type(inner).canonical_type(self.ctx);
301301
if let TypeKind::Function(ref sig) = *inner_type.kind() {
302-
if !sig.can_trivially_derive_debug() {
302+
if !sig.can_trivially_derive_debug(self.ctx) {
303303
trace!(
304304
" function pointer that can't trivially derive Debug"
305305
);

src/ir/analysis/derive_default.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> {
173173

174174
if item.is_opaque(self.ctx, &()) {
175175
let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| {
176-
l.opaque().can_trivially_derive_default()
176+
l.opaque().can_trivially_derive_default(self.ctx)
177177
});
178178
return if layout_can_derive &&
179179
!(ty.is_union() &&
@@ -278,7 +278,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> {
278278
}
279279

280280
if ty.layout(self.ctx).map_or(true, |l| {
281-
l.opaque().can_trivially_derive_default()
281+
l.opaque().can_trivially_derive_default(self.ctx)
282282
})
283283
{
284284
trace!(" union layout can trivially derive Default");

src/ir/analysis/derive_hash.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
133133

134134
if item.is_opaque(self.ctx, &()) {
135135
let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| {
136-
l.opaque().can_trivially_derive_hash()
136+
l.opaque().can_trivially_derive_hash(self.ctx)
137137
});
138138
return if layout_can_derive &&
139139
!(ty.is_union() &&
@@ -218,7 +218,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
218218
let inner_type =
219219
self.ctx.resolve_type(inner).canonical_type(self.ctx);
220220
if let TypeKind::Function(ref sig) = *inner_type.kind() {
221-
if !sig.can_trivially_derive_hash() {
221+
if !sig.can_trivially_derive_hash(self.ctx) {
222222
trace!(
223223
" function pointer that can't trivially derive Hash"
224224
);
@@ -230,7 +230,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
230230
}
231231

232232
TypeKind::Function(ref sig) => {
233-
if !sig.can_trivially_derive_hash() {
233+
if !sig.can_trivially_derive_hash(self.ctx) {
234234
trace!(" function that can't trivially derive Hash");
235235
return self.insert(id);
236236
}
@@ -275,7 +275,7 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
275275
}
276276

277277
if ty.layout(self.ctx).map_or(true, |l| {
278-
l.opaque().can_trivially_derive_hash()
278+
l.opaque().can_trivially_derive_hash(self.ctx)
279279
})
280280
{
281281
trace!(" union layout can trivially derive Hash");

0 commit comments

Comments
 (0)