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
use std;
use builder::Builder;
use common::*;
use llvm;
use meth;
use rustc::ty::layout::LayoutOf;
use rustc::ty::{self, Ty};
use value::Value;
pub fn size_and_align_of_dst(bx: &Builder<'_, 'll, 'tcx>, t: Ty<'tcx>, info: Option<&'ll Value>)
-> (&'ll Value, &'ll Value) {
debug!("calculate size of DST: {}; with lost info: {:?}",
t, info);
if bx.cx.type_is_sized(t) {
let (size, align) = bx.cx.size_and_align_of(t);
debug!("size_and_align_of_dst t={} info={:?} size: {:?} align: {:?}",
t, info, size, align);
let size = C_usize(bx.cx, size.bytes());
let align = C_usize(bx.cx, align.abi());
return (size, align);
}
match t.sty {
ty::Dynamic(..) => {
let vtable = info.unwrap();
(meth::SIZE.get_usize(bx, vtable), meth::ALIGN.get_usize(bx, vtable))
}
ty::Slice(_) | ty::Str => {
let unit = t.sequence_element_type(bx.tcx());
let (size, align) = bx.cx.size_and_align_of(unit);
(bx.mul(info.unwrap(), C_usize(bx.cx, size.bytes())),
C_usize(bx.cx, align.abi()))
}
_ => {
let cx = bx.cx;
assert!(!t.is_simd());
let layout = cx.layout_of(t);
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();
debug!("DST {} statically sized prefix size: {} align: {}",
t, sized_size, sized_align);
let sized_size = C_usize(cx, sized_size);
let sized_align = C_usize(cx, sized_align);
let field_ty = layout.field(cx, 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.sty {
if def.repr.packed() {
unsized_align = sized_align;
}
}
let align = match (const_to_opt_u128(sized_align, false),
const_to_opt_u128(unsized_align, false)) {
(Some(sized_align), Some(unsized_align)) => {
C_usize(cx, std::cmp::max(sized_align, unsized_align) as u64)
}
_ => bx.select(bx.icmp(llvm::IntUGT, sized_align, unsized_align),
sized_align,
unsized_align)
};
let addend = bx.sub(align, C_usize(bx.cx, 1));
let size = bx.and(bx.add(size, addend), bx.neg(align));
(size, align)
}
}
}