Skip to content

Commit

Permalink
codegen: Use target pointer size consistently for layout calculations.
Browse files Browse the repository at this point in the history
Closes #1284
  • Loading branch information
emilio committed Mar 31, 2018
1 parent d7c57dd commit b69ecbf
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 47 deletions.
8 changes: 3 additions & 5 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ use std::collections::{HashSet, VecDeque};
use std::collections::hash_map::{Entry, HashMap};
use std::fmt::Write;
use std::iter;
use std::mem;
use std::ops;

// Name of type defined in constified enum module
Expand Down Expand Up @@ -1777,7 +1776,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 {
Expand Down Expand Up @@ -2720,9 +2719,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(
Expand Down
31 changes: 14 additions & 17 deletions src/codegen/struct_layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}
}
}
Expand All @@ -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;

Expand All @@ -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
Expand Down Expand Up @@ -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)
};
Expand All @@ -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 {
Expand Down
26 changes: 17 additions & 9 deletions src/ir/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -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)
);
}
Expand All @@ -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 {
Expand All @@ -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
Expand Down
18 changes: 2 additions & 16 deletions src/ir/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down Expand Up @@ -232,8 +231,6 @@ impl Type {

/// What is the layout of this type?
pub fn layout(&self, ctx: &BindgenContext) -> Option<Layout> {
use std::mem;

self.layout.or_else(|| {
match self.kind {
TypeKind::Comp(ref ci) => ci.layout(ctx),
Expand All @@ -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) => {
Expand Down Expand Up @@ -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::<f32>(),
FloatKind::Double | FloatKind::LongDouble => mem::size_of::<f64>(),
FloatKind::Float128 => mem::size_of::<f64>() * 2,
}
}
}

/// The different kinds of types that we can parse.
#[derive(Debug)]
pub enum TypeKind {
Expand Down

0 comments on commit b69ecbf

Please sign in to comment.