| //! Intermediate representation for the physical layout of some type. |
| |
| use crate::ir::context::BindgenContext; |
| |
| /// A type that represents the struct layout of a type. |
| #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| pub(crate) struct Layout { |
| /// The size (in bytes) of this layout. |
| pub(crate) size: usize, |
| /// The alignment (in bytes) of this layout. |
| pub(crate) align: usize, |
| /// Whether this layout's members are packed or not. |
| pub(crate) packed: bool, |
| } |
| |
| #[test] |
| fn test_layout_for_size() { |
| use std::mem::size_of; |
| let ptr_size = size_of::<*mut ()>(); |
| assert_eq!( |
| 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) |
| ); |
| } |
| |
| impl Layout { |
| /// Gets the integer type name for a given known size. |
| pub(crate) fn known_type_for_size(size: usize) -> Option<syn::Type> { |
| Some(match size { |
| 16 => syn::parse_quote! { u128 }, |
| 8 => syn::parse_quote! { u64 }, |
| 4 => syn::parse_quote! { u32 }, |
| 2 => syn::parse_quote! { u16 }, |
| 1 => syn::parse_quote! { u8 }, |
| _ => return None, |
| }) |
| } |
| |
| /// Construct a new `Layout` with the given `size` and `align`. It is not |
| /// packed. |
| pub(crate) fn new(size: usize, align: usize) -> Self { |
| Layout { |
| size, |
| align, |
| packed: false, |
| } |
| } |
| |
| fn for_size_internal(ptr_size: usize, size: usize) -> Self { |
| let mut next_align = 2; |
| while size % next_align == 0 && next_align <= ptr_size { |
| next_align *= 2; |
| } |
| Layout { |
| size, |
| align: next_align / 2, |
| packed: false, |
| } |
| } |
| |
| /// Creates a non-packed layout for a given size, trying to use the maximum |
| /// alignment possible. |
| pub(crate) fn for_size(ctx: &BindgenContext, size: usize) -> Self { |
| Self::for_size_internal(ctx.target_pointer_size(), size) |
| } |
| } |