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
use crate::common::IntPredicate;
use crate::meth;
use crate::traits::*;
use rustc_middle::ty::{self, Ty};
pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
bx: &mut Bx,
t: Ty<'tcx>,
info: Option<Bx::Value>,
) -> (Bx::Value, Bx::Value) {
let layout = bx.layout_of(t);
debug!("size_and_align_of_dst(ty={}, info={:?}): layout: {:?}", t, info, layout);
if !layout.is_unsized() {
let size = bx.const_usize(layout.size.bytes());
let align = bx.const_usize(layout.align.abi.bytes());
return (size, align);
}
match t.kind() {
ty::Dynamic(..) => {
let vtable = info.unwrap();
(meth::SIZE.get_usize(bx, vtable), meth::ALIGN.get_usize(bx, vtable))
}
ty::Slice(_) | ty::Str => {
let unit = layout.field(bx, 0);
(
bx.mul(info.unwrap(), bx.const_usize(unit.size.bytes())),
bx.const_usize(unit.align.abi.bytes()),
)
}
_ => {
assert!(!t.is_simd());
debug!("DST {} layout: {:?}", t, layout);
let i = layout.fields.count() - 1;
let sized_size = layout.fields.offset(i).bytes();
let sized_align = layout.align.abi.bytes();
debug!("DST {} statically sized prefix size: {} align: {}", t, sized_size, sized_align);
let sized_size = bx.const_usize(sized_size);
let sized_align = bx.const_usize(sized_align);
let field_ty = layout.field(bx, i).ty;
let (unsized_size, mut unsized_align) = size_and_align_of_dst(bx, field_ty, info);
let size = bx.add(sized_size, unsized_size);
if let ty::Adt(def, _) = t.kind() {
if def.repr.packed() {
unsized_align = sized_align;
}
}
let align = match (
bx.const_to_opt_u128(sized_align, false),
bx.const_to_opt_u128(unsized_align, false),
) {
(Some(sized_align), Some(unsized_align)) => {
bx.const_usize(std::cmp::max(sized_align, unsized_align) as u64)
}
_ => {
let cmp = bx.icmp(IntPredicate::IntUGT, sized_align, unsized_align);
bx.select(cmp, sized_align, unsized_align)
}
};
let one = bx.const_usize(1);
let addend = bx.sub(align, one);
let add = bx.add(size, addend);
let neg = bx.neg(align);
let size = bx.and(add, neg);
(size, align)
}
}
}