Bindgen historically represented 8-byte aligned types with u64. That's borked in x86 where u64 is 4-byte aligned. I fixed this in upstream bindgen (https://github.com/rust-lang/rust-bindgen/pull/3280), so update it. There are a few changes needed: * https://github.com/mozilla/neqo/pull/2913 to deal with the now properly aligned type. * Similar change (less fun because transmute, but still sound) in the macos crash reporter. I could try to generate a bit easier to use bindings for 8-byte 8-byte-aligned blobs, but this would do. * Some opaque additions in layout/style/ServoBindings.toml and the profiler bindings. This is unrelated to the opaque change, but fallout from other bindgen improvements. In particular, layout tests now run at compile time, so this uncovered some layout mismatches on platforms where we don't run rusttests on CI. Differential Revision: https://phabricator.services.mozilla.com/D262840
115 lines
3.5 KiB
Rust
115 lines
3.5 KiB
Rust
use crate::ir::comp::{CompInfo, CompKind, Field, FieldMethods};
|
|
use crate::ir::context::BindgenContext;
|
|
use crate::ir::item::{IsOpaque, Item};
|
|
use crate::ir::ty::TypeKind;
|
|
|
|
/// Generate a manual implementation of `PartialEq` trait for the
|
|
/// specified compound type.
|
|
pub(crate) fn gen_partialeq_impl(
|
|
ctx: &BindgenContext,
|
|
comp_info: &CompInfo,
|
|
item: &Item,
|
|
ty_for_impl: &proc_macro2::TokenStream,
|
|
) -> Option<proc_macro2::TokenStream> {
|
|
let mut tokens = vec![];
|
|
|
|
if item.is_opaque(ctx, &()) {
|
|
tokens.push(quote! {
|
|
&self._bindgen_opaque_blob[..] == &other._bindgen_opaque_blob[..]
|
|
});
|
|
} else if comp_info.kind() == CompKind::Union {
|
|
assert!(!ctx.options().untagged_union);
|
|
tokens.push(quote! {
|
|
&self.bindgen_union_field[..] == &other.bindgen_union_field[..]
|
|
});
|
|
} else {
|
|
for base in comp_info.base_members() {
|
|
if !base.requires_storage(ctx) {
|
|
continue;
|
|
}
|
|
|
|
let ty_item = ctx.resolve_item(base.ty);
|
|
let field_name = &base.field_name;
|
|
tokens.push(gen_field(ctx, ty_item, field_name));
|
|
}
|
|
|
|
for field in comp_info.fields() {
|
|
match *field {
|
|
Field::DataMember(ref fd) => {
|
|
let ty_item = ctx.resolve_item(fd.ty());
|
|
let name = fd.name().unwrap();
|
|
tokens.push(gen_field(ctx, ty_item, name));
|
|
}
|
|
Field::Bitfields(ref bu) => {
|
|
for bitfield in bu.bitfields() {
|
|
if bitfield.name().is_some() {
|
|
let getter_name = bitfield.getter_name();
|
|
let name_ident = ctx.rust_ident_raw(getter_name);
|
|
tokens.push(quote! {
|
|
self.#name_ident () == other.#name_ident ()
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Some(quote! {
|
|
fn eq(&self, other: & #ty_for_impl) -> bool {
|
|
#( #tokens )&&*
|
|
}
|
|
})
|
|
}
|
|
|
|
fn gen_field(
|
|
ctx: &BindgenContext,
|
|
ty_item: &Item,
|
|
name: &str,
|
|
) -> proc_macro2::TokenStream {
|
|
fn quote_equals(
|
|
name_ident: &proc_macro2::Ident,
|
|
) -> proc_macro2::TokenStream {
|
|
quote! { self.#name_ident == other.#name_ident }
|
|
}
|
|
|
|
let name_ident = ctx.rust_ident(name);
|
|
let ty = ty_item.expect_type();
|
|
|
|
match *ty.kind() {
|
|
TypeKind::Void |
|
|
TypeKind::NullPtr |
|
|
TypeKind::Int(..) |
|
|
TypeKind::Complex(..) |
|
|
TypeKind::Float(..) |
|
|
TypeKind::Enum(..) |
|
|
TypeKind::TypeParam |
|
|
TypeKind::UnresolvedTypeRef(..) |
|
|
TypeKind::Reference(..) |
|
|
TypeKind::ObjCInterface(..) |
|
|
TypeKind::ObjCId |
|
|
TypeKind::ObjCSel |
|
|
TypeKind::Comp(..) |
|
|
TypeKind::Pointer(_) |
|
|
TypeKind::Function(..) |
|
|
TypeKind::Array(..) |
|
|
TypeKind::TemplateInstantiation(..) |
|
|
TypeKind::Opaque => quote_equals(&name_ident),
|
|
TypeKind::Vector(_, len) => {
|
|
let self_ids = 0..len;
|
|
let other_ids = 0..len;
|
|
quote! {
|
|
#(self.#self_ids == other.#other_ids &&)* true
|
|
}
|
|
}
|
|
|
|
TypeKind::ResolvedTypeRef(t) |
|
|
TypeKind::TemplateAlias(t, _) |
|
|
TypeKind::Alias(t) |
|
|
TypeKind::BlockPointer(t) => {
|
|
let inner_item = ctx.resolve_item(t);
|
|
gen_field(ctx, inner_item, name)
|
|
}
|
|
}
|
|
}
|