-
Notifications
You must be signed in to change notification settings - Fork 707
/
layout.rs
147 lines (130 loc) · 4.14 KB
/
layout.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//! Intermediate representation for the physical layout of some type.
use super::derive::{CanTriviallyDeriveCopy, CanTriviallyDeriveDebug,
CanTriviallyDeriveDefault, CanTriviallyDeriveHash,
CanTriviallyDerivePartialEqOrPartialOrd};
use super::ty::{RUST_DERIVE_IN_ARRAY_LIMIT, Type, TypeKind};
use clang;
use std::{cmp, mem};
/// A type that represents the struct layout of a type.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Layout {
/// The size (in bytes) of this layout.
pub size: usize,
/// The alignment (in bytes) of this layout.
pub align: usize,
/// Whether this layout's members are packed or not.
pub packed: bool,
}
#[test]
fn test_layout_for_size() {
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::new(3 * ptr_size, ptr_size)
);
}
impl Layout {
/// Construct a new `Layout` with the given `size` and `align`. It is not
/// packed.
pub fn new(size: usize, align: usize) -> Self {
Layout {
size: size,
align: align,
packed: false,
}
}
/// Creates a non-packed layout for a given size, trying to use the maximum
/// alignment possible.
pub fn for_size(size: usize) -> Self {
let mut next_align = 2;
while size % next_align == 0 &&
next_align <= mem::size_of::<*mut ()>()
{
next_align *= 2;
}
Layout {
size: size,
align: next_align / 2,
packed: false,
}
}
/// Is this a zero-sized layout?
pub fn is_zero(&self) -> bool {
self.size == 0 && self.align == 0
}
/// Construct a zero-sized layout.
pub fn zero() -> Self {
Self::new(0, 0)
}
/// Get this layout as an opaque type.
pub fn opaque(&self) -> Opaque {
Opaque(*self)
}
}
/// When we are treating a type as opaque, it is just a blob with a `Layout`.
#[derive(Clone, Debug, PartialEq)]
pub struct Opaque(pub Layout);
impl Opaque {
/// Construct a new opaque type from the given clang type.
pub fn from_clang_ty(ty: &clang::Type) -> Type {
let layout = Layout::new(ty.size(), ty.align());
let ty_kind = TypeKind::Opaque;
Type::new(None, Some(layout), ty_kind, false)
}
/// Return the known rust type we should use to create a correctly-aligned
/// field with this layout.
pub fn known_rust_type_for_array(&self) -> Option<&'static str> {
Some(match self.0.align {
8 => "u64",
4 => "u32",
2 => "u16",
1 => "u8",
_ => return None,
})
}
/// Return the array size that an opaque type for this layout should have if
/// we know the correct type for it, or `None` otherwise.
pub fn array_size(&self) -> Option<usize> {
if self.known_rust_type_for_array().is_some() {
Some(self.0.size / cmp::max(self.0.align, 1))
} else {
None
}
}
}
impl CanTriviallyDeriveDebug for Opaque {
fn can_trivially_derive_debug(&self) -> bool {
self.array_size().map_or(false, |size| {
size <= RUST_DERIVE_IN_ARRAY_LIMIT
})
}
}
impl CanTriviallyDeriveDefault for Opaque {
fn can_trivially_derive_default(&self) -> bool {
self.array_size().map_or(false, |size| {
size <= RUST_DERIVE_IN_ARRAY_LIMIT
})
}
}
impl CanTriviallyDeriveCopy for Opaque {
fn can_trivially_derive_copy(&self) -> bool {
self.array_size().map_or(false, |size| {
size <= RUST_DERIVE_IN_ARRAY_LIMIT
})
}
}
impl CanTriviallyDeriveHash for Opaque {
fn can_trivially_derive_hash(&self) -> bool {
self.array_size().map_or(false, |size| {
size <= RUST_DERIVE_IN_ARRAY_LIMIT
})
}
}
impl CanTriviallyDerivePartialEqOrPartialOrd for Opaque {
fn can_trivially_derive_partialeq_or_partialord(&self) -> bool {
self.array_size().map_or(false, |size| {
size <= RUST_DERIVE_IN_ARRAY_LIMIT
})
}
}