From e7d80821f0ad4ae05e28f9380458107216ed93e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 31 Mar 2018 04:25:52 +0200 Subject: [PATCH] codegen: Use target pointer size consistently for layout calculations. Closes #1284 --- src/codegen/mod.rs | 7 +++---- src/codegen/struct_layout.rs | 31 ++++++++++++++----------------- src/ir/layout.rs | 26 +++++++++++++++++--------- src/ir/ty.rs | 18 ++---------------- 4 files changed, 36 insertions(+), 46 deletions(-) diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 5e1043608c..ac90e0cd32 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1777,7 +1777,7 @@ impl CodeGenerator for CompInfo { let align = layout.align; let check_struct_align = - if align > mem::size_of::<*mut ()>() { + if align > ctx.target_pointer_size() { // FIXME when [RFC 1358](https://github.com/rust-lang/rust/issues/33626) ready None } else { @@ -2720,9 +2720,8 @@ trait TryToOpaque { /// leverage the blanket impl for this trait. trait ToOpaque: TryToOpaque { fn get_layout(&self, ctx: &BindgenContext, extra: &Self::Extra) -> Layout { - self.try_get_layout(ctx, extra).unwrap_or_else( - |_| Layout::for_size(1), - ) + self.try_get_layout(ctx, extra) + .unwrap_or_else(|_| Layout::for_size(ctx, 1)) } fn to_opaque( diff --git a/src/codegen/struct_layout.rs b/src/codegen/struct_layout.rs index a538c35fea..d2be5aff76 100644 --- a/src/codegen/struct_layout.rs +++ b/src/codegen/struct_layout.rs @@ -8,7 +8,6 @@ use ir::layout::Layout; use ir::ty::{Type, TypeKind}; use quote; use std::cmp; -use std::mem; /// Trace the layout of struct. #[derive(Debug)] @@ -101,7 +100,7 @@ impl<'a> StructLayoutTracker<'a> { pub fn saw_vtable(&mut self) { debug!("saw vtable for {}", self.name); - let ptr_size = mem::size_of::<*mut ()>(); + let ptr_size = self.ctx.target_pointer_size(); self.latest_offset += ptr_size; self.latest_field_layout = Some(Layout::new(ptr_size, ptr_size)); self.max_field_align = ptr_size; @@ -165,15 +164,13 @@ impl<'a> StructLayoutTracker<'a> { // can support. // // This means that the structs in the array are super-unsafe to - // access, since they won't be properly aligned, but *shrug*. - if let Some(layout) = self.ctx.resolve_type(inner).layout( - self.ctx, - ) - { - if layout.align > mem::size_of::<*mut ()>() { - field_layout.size = align_to(layout.size, layout.align) * - len; - field_layout.align = mem::size_of::<*mut ()>(); + // access, since they won't be properly aligned, but there's not too + // much we can do about it. + if let Some(layout) = self.ctx.resolve_type(inner).layout(self.ctx) { + if layout.align > self.ctx.target_pointer_size() { + field_layout.size = + align_to(layout.size, layout.align) * len; + field_layout.align = self.ctx.target_pointer_size(); } } } @@ -193,7 +190,7 @@ impl<'a> StructLayoutTracker<'a> { // Otherwise the padding is useless. let need_padding = padding_bytes >= field_layout.align || - field_layout.align > mem::size_of::<*mut ()>(); + field_layout.align > self.ctx.target_pointer_size(); self.latest_offset += padding_bytes; @@ -215,7 +212,7 @@ impl<'a> StructLayoutTracker<'a> { if need_padding && padding_bytes != 0 { Some(Layout::new( padding_bytes, - cmp::min(field_layout.align, mem::size_of::<*mut ()>()), + cmp::min(field_layout.align, self.ctx.target_pointer_size()) )) } else { None @@ -267,15 +264,15 @@ impl<'a> StructLayoutTracker<'a> { (self.last_field_was_bitfield && padding_bytes >= self.latest_field_layout.unwrap().align) || - layout.align > mem::size_of::<*mut ()>()) + layout.align > self.ctx.target_pointer_size()) { let layout = if self.is_packed { Layout::new(padding_bytes, 1) } else if self.last_field_was_bitfield || - layout.align > mem::size_of::<*mut ()>() + layout.align > self.ctx.target_pointer_size() { // We've already given up on alignment here. - Layout::for_size(padding_bytes) + Layout::for_size(self.ctx, padding_bytes) } else { Layout::new(padding_bytes, layout.align) }; @@ -290,7 +287,7 @@ impl<'a> StructLayoutTracker<'a> { pub fn requires_explicit_align(&self, layout: Layout) -> bool { self.max_field_align < layout.align && - layout.align <= mem::size_of::<*mut ()>() + layout.align <= self.ctx.target_pointer_size() } fn padding_bytes(&self, layout: Layout) -> usize { diff --git a/src/ir/layout.rs b/src/ir/layout.rs index 0c99c7e77c..bc3f8a5a0a 100644 --- a/src/ir/layout.rs +++ b/src/ir/layout.rs @@ -4,8 +4,9 @@ use super::derive::{CanTriviallyDeriveCopy, CanTriviallyDeriveDebug, CanTriviallyDeriveDefault, CanTriviallyDeriveHash, CanTriviallyDerivePartialEqOrPartialOrd, CanDerive}; use super::ty::{RUST_DERIVE_IN_ARRAY_LIMIT, Type, TypeKind}; +use ir::context::BindgenContext; use clang; -use std::{cmp, mem}; +use std::cmp; /// A type that represents the struct layout of a type. #[derive(Debug, Clone, Copy, PartialEq)] @@ -20,10 +21,15 @@ pub struct Layout { #[test] fn test_layout_for_size() { + use std::mem; + let ptr_size = mem::size_of::<*mut ()>(); - assert_eq!(Layout::for_size(ptr_size), Layout::new(ptr_size, ptr_size)); assert_eq!( - Layout::for_size(3 * ptr_size), + Layout::for_size_internal(ptr_size, ptr_size), + Layout::new(ptr_size, ptr_size) + ); + assert_eq!( + Layout::for_size_internal(ptr_size, 3 * ptr_size), Layout::new(3 * ptr_size, ptr_size) ); } @@ -39,13 +45,9 @@ impl Layout { } } - /// Creates a non-packed layout for a given size, trying to use the maximum - /// alignment possible. - pub fn for_size(size: usize) -> Self { + fn for_size_internal(ptr_size: usize, size: usize) -> Self { let mut next_align = 2; - while size % next_align == 0 && - next_align <= mem::size_of::<*mut ()>() - { + while size % next_align == 0 && next_align <= ptr_size { next_align *= 2; } Layout { @@ -55,6 +57,12 @@ impl Layout { } } + /// Creates a non-packed layout for a given size, trying to use the maximum + /// alignment possible. + pub fn for_size(ctx: &BindgenContext, size: usize) -> Self { + Self::for_size_internal(ctx.target_pointer_size(), size) + } + /// Is this a zero-sized layout? pub fn is_zero(&self) -> bool { self.size == 0 && self.align == 0 diff --git a/src/ir/ty.rs b/src/ir/ty.rs index 2fab41be6d..b42f44240c 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -16,7 +16,6 @@ use clang::{self, Cursor}; use parse::{ClangItemParser, ParseError, ParseResult}; use std::borrow::Cow; use std::io; -use std::mem; /// The base representation of a type in bindgen. /// @@ -232,8 +231,6 @@ impl Type { /// What is the layout of this type? pub fn layout(&self, ctx: &BindgenContext) -> Option { - use std::mem; - self.layout.or_else(|| { match self.kind { TypeKind::Comp(ref ci) => ci.layout(ctx), @@ -242,8 +239,8 @@ impl Type { TypeKind::Pointer(..) | TypeKind::BlockPointer => { Some(Layout::new( - mem::size_of::<*mut ()>(), - mem::align_of::<*mut ()>(), + ctx.target_pointer_size(), + ctx.target_pointer_size(), )) } TypeKind::ResolvedTypeRef(inner) => { @@ -596,17 +593,6 @@ pub enum FloatKind { Float128, } -impl FloatKind { - /// If this type has a known size, return it (in bytes). - pub fn known_size(&self) -> usize { - match *self { - FloatKind::Float => mem::size_of::(), - FloatKind::Double | FloatKind::LongDouble => mem::size_of::(), - FloatKind::Float128 => mem::size_of::() * 2, - } - } -} - /// The different kinds of types that we can parse. #[derive(Debug)] pub enum TypeKind {