1use std::num::NonZero;
2
3use rustc_hashes::Hash64;
4use rustc_index::{Idx, IndexVec};
5
6use crate::{
7 AbiAlign, BackendRepr, FieldsShape, HasDataLayout, LayoutData, Niche, Primitive, Scalar, Size,
8 Variants,
9};
10
11impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
13 pub fn unit<C: HasDataLayout>(cx: &C, sized: bool) -> Self {
14 let dl = cx.data_layout();
15 LayoutData {
16 variants: Variants::Single { index: VariantIdx::new(0) },
17 fields: FieldsShape::Arbitrary {
18 offsets: IndexVec::new(),
19 memory_index: IndexVec::new(),
20 },
21 backend_repr: BackendRepr::Memory { sized },
22 largest_niche: None,
23 uninhabited: false,
24 align: AbiAlign::new(dl.i8_align),
25 size: Size::ZERO,
26 max_repr_align: None,
27 unadjusted_abi_align: dl.i8_align,
28 randomization_seed: Hash64::new(0),
29 }
30 }
31
32 pub fn never_type<C: HasDataLayout>(cx: &C) -> Self {
33 let dl = cx.data_layout();
34 LayoutData {
36 variants: Variants::Empty,
37 fields: FieldsShape::Primitive,
38 backend_repr: BackendRepr::Memory { sized: true },
39 largest_niche: None,
40 uninhabited: true,
41 align: AbiAlign::new(dl.i8_align),
42 size: Size::ZERO,
43 max_repr_align: None,
44 unadjusted_abi_align: dl.i8_align,
45 randomization_seed: Hash64::ZERO,
46 }
47 }
48
49 pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
50 let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar);
51 let size = scalar.size(cx);
52 let align = scalar.align(cx);
53
54 let range = scalar.valid_range(cx);
55
56 let randomization_seed = size
63 .bytes()
64 .wrapping_add(
65 match scalar.primitive() {
66 Primitive::Int(_, true) => 1,
67 Primitive::Int(_, false) => 2,
68 Primitive::Float(_) => 3,
69 Primitive::Pointer(_) => 4,
70 } << 32,
71 )
72 .wrapping_add((range.start as u64).rotate_right(16))
74 .wrapping_add((range.end as u64).rotate_right(16));
76
77 LayoutData {
78 variants: Variants::Single { index: VariantIdx::new(0) },
79 fields: FieldsShape::Primitive,
80 backend_repr: BackendRepr::Scalar(scalar),
81 largest_niche,
82 uninhabited: false,
83 size,
84 align,
85 max_repr_align: None,
86 unadjusted_abi_align: align.abi,
87 randomization_seed: Hash64::new(randomization_seed),
88 }
89 }
90
91 pub fn scalar_pair<C: HasDataLayout>(cx: &C, a: Scalar, b: Scalar) -> Self {
92 let dl = cx.data_layout();
93 let b_align = b.align(dl).abi;
94 let align = a.align(dl).abi.max(b_align).max(dl.aggregate_align);
95 let b_offset = a.size(dl).align_to(b_align);
96 let size = (b_offset + b.size(dl)).align_to(align);
97
98 let largest_niche = Niche::from_scalar(dl, b_offset, b)
101 .into_iter()
102 .chain(Niche::from_scalar(dl, Size::ZERO, a))
103 .max_by_key(|niche| niche.available(dl));
104
105 let combined_seed = a.size(dl).bytes().wrapping_add(b.size(dl).bytes());
106
107 LayoutData {
108 variants: Variants::Single { index: VariantIdx::new(0) },
109 fields: FieldsShape::Arbitrary {
110 offsets: [Size::ZERO, b_offset].into(),
111 memory_index: [0, 1].into(),
112 },
113 backend_repr: BackendRepr::ScalarPair(a, b),
114 largest_niche,
115 uninhabited: false,
116 align: AbiAlign::new(align),
117 size,
118 max_repr_align: None,
119 unadjusted_abi_align: align,
120 randomization_seed: Hash64::new(combined_seed),
121 }
122 }
123
124 pub fn uninhabited_variant<C: HasDataLayout>(cx: &C, index: VariantIdx, fields: usize) -> Self {
129 let dl = cx.data_layout();
130 LayoutData {
131 variants: Variants::Single { index },
132 fields: match NonZero::new(fields) {
133 Some(fields) => FieldsShape::Union(fields),
134 None => FieldsShape::Arbitrary {
135 offsets: IndexVec::new(),
136 memory_index: IndexVec::new(),
137 },
138 },
139 backend_repr: BackendRepr::Memory { sized: true },
140 largest_niche: None,
141 uninhabited: true,
142 align: AbiAlign::new(dl.i8_align),
143 size: Size::ZERO,
144 max_repr_align: None,
145 unadjusted_abi_align: dl.i8_align,
146 randomization_seed: Hash64::ZERO,
147 }
148 }
149}