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