cranelift_codegen_meta/cdsl/
types.rs1use std::fmt;
4
5use crate::shared::types as shared_types;
6use cranelift_codegen_shared::constants;
7
8static RUST_NAME_PREFIX: &str = "ir::types::";
10
11#[derive(Clone, Debug, PartialEq, Eq, Hash)]
18pub(crate) enum ValueType {
19 Lane(LaneType),
20 Vector(VectorType),
21 DynamicVector(DynamicVectorType),
22}
23
24impl ValueType {
25 pub fn all_lane_types() -> LaneTypeIterator {
27 LaneTypeIterator::new()
28 }
29
30 pub fn doc(&self) -> String {
32 match *self {
33 ValueType::Lane(l) => l.doc(),
34 ValueType::Vector(ref v) => v.doc(),
35 ValueType::DynamicVector(ref v) => v.doc(),
36 }
37 }
38
39 pub fn lane_bits(&self) -> u64 {
41 match *self {
42 ValueType::Lane(l) => l.lane_bits(),
43 ValueType::Vector(ref v) => v.lane_bits(),
44 ValueType::DynamicVector(ref v) => v.lane_bits(),
45 }
46 }
47
48 pub fn lane_count(&self) -> u64 {
50 match *self {
51 ValueType::Vector(ref v) => v.lane_count(),
52 _ => 1,
53 }
54 }
55
56 pub fn membytes(&self) -> u64 {
58 self.width() / 8
59 }
60
61 pub fn number(&self) -> u16 {
63 match *self {
64 ValueType::Lane(l) => l.number(),
65 ValueType::Vector(ref v) => v.number(),
66 ValueType::DynamicVector(ref v) => v.number(),
67 }
68 }
69
70 pub fn rust_name(&self) -> String {
72 format!("{}{}", RUST_NAME_PREFIX, self.to_string().to_uppercase())
73 }
74
75 pub fn width(&self) -> u64 {
77 self.lane_count() * self.lane_bits()
78 }
79}
80
81impl fmt::Display for ValueType {
82 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
83 match *self {
84 ValueType::Lane(l) => l.fmt(f),
85 ValueType::Vector(ref v) => v.fmt(f),
86 ValueType::DynamicVector(ref v) => v.fmt(f),
87 }
88 }
89}
90
91impl From<LaneType> for ValueType {
93 fn from(lane: LaneType) -> Self {
94 ValueType::Lane(lane)
95 }
96}
97
98impl From<VectorType> for ValueType {
100 fn from(vector: VectorType) -> Self {
101 ValueType::Vector(vector)
102 }
103}
104
105impl From<DynamicVectorType> for ValueType {
107 fn from(vector: DynamicVectorType) -> Self {
108 ValueType::DynamicVector(vector)
109 }
110}
111
112#[derive(Clone, Copy, PartialEq, Eq, Hash)]
114pub(crate) enum LaneType {
115 Float(shared_types::Float),
116 Int(shared_types::Int),
117}
118
119impl LaneType {
120 pub fn doc(self) -> String {
122 match self {
123 LaneType::Float(shared_types::Float::F16) => String::from(
124 "A 16-bit floating point type represented in the IEEE 754-2008
125 *binary16* interchange format. This corresponds to the :c:type:`_Float16`
126 type in most C implementations.
127 WARNING: f16 support is a work-in-progress and is incomplete",
128 ),
129 LaneType::Float(shared_types::Float::F32) => String::from(
130 "A 32-bit floating point type represented in the IEEE 754-2008
131 *binary32* interchange format. This corresponds to the :c:type:`float`
132 type in most C implementations.",
133 ),
134 LaneType::Float(shared_types::Float::F64) => String::from(
135 "A 64-bit floating point type represented in the IEEE 754-2008
136 *binary64* interchange format. This corresponds to the :c:type:`double`
137 type in most C implementations.",
138 ),
139 LaneType::Float(shared_types::Float::F128) => String::from(
140 "A 128-bit floating point type represented in the IEEE 754-2008
141 *binary128* interchange format. This corresponds to the :c:type:`_Float128`
142 type in most C implementations.
143 WARNING: f128 support is a work-in-progress and is incomplete",
144 ),
145 LaneType::Int(_) if self.lane_bits() < 32 => format!(
146 "An integer type with {} bits.
147 WARNING: arithmetic on {}bit integers is incomplete",
148 self.lane_bits(),
149 self.lane_bits()
150 ),
151 LaneType::Int(_) => format!("An integer type with {} bits.", self.lane_bits()),
152 }
153 }
154
155 pub fn lane_bits(self) -> u64 {
157 match self {
158 LaneType::Float(ref f) => *f as u64,
159 LaneType::Int(ref i) => *i as u64,
160 }
161 }
162
163 pub fn number(self) -> u16 {
165 constants::LANE_BASE
166 + match self {
167 LaneType::Int(shared_types::Int::I8) => 4,
168 LaneType::Int(shared_types::Int::I16) => 5,
169 LaneType::Int(shared_types::Int::I32) => 6,
170 LaneType::Int(shared_types::Int::I64) => 7,
171 LaneType::Int(shared_types::Int::I128) => 8,
172 LaneType::Float(shared_types::Float::F16) => 9,
173 LaneType::Float(shared_types::Float::F32) => 10,
174 LaneType::Float(shared_types::Float::F64) => 11,
175 LaneType::Float(shared_types::Float::F128) => 12,
176 }
177 }
178
179 pub fn int_from_bits(num_bits: u16) -> LaneType {
180 LaneType::Int(match num_bits {
181 8 => shared_types::Int::I8,
182 16 => shared_types::Int::I16,
183 32 => shared_types::Int::I32,
184 64 => shared_types::Int::I64,
185 128 => shared_types::Int::I128,
186 _ => unreachable!("unexpected num bits for int"),
187 })
188 }
189
190 pub fn float_from_bits(num_bits: u16) -> LaneType {
191 LaneType::Float(match num_bits {
192 16 => shared_types::Float::F16,
193 32 => shared_types::Float::F32,
194 64 => shared_types::Float::F64,
195 128 => shared_types::Float::F128,
196 _ => unreachable!("unexpected num bits for float"),
197 })
198 }
199
200 pub fn by(self, lanes: u16) -> ValueType {
201 if lanes == 1 {
202 self.into()
203 } else {
204 ValueType::Vector(VectorType::new(self, lanes.into()))
205 }
206 }
207
208 pub fn to_dynamic(self, lanes: u16) -> ValueType {
209 ValueType::DynamicVector(DynamicVectorType::new(self, lanes.into()))
210 }
211}
212
213impl fmt::Display for LaneType {
214 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
215 match *self {
216 LaneType::Float(_) => write!(f, "f{}", self.lane_bits()),
217 LaneType::Int(_) => write!(f, "i{}", self.lane_bits()),
218 }
219 }
220}
221
222impl fmt::Debug for LaneType {
223 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
224 let inner_msg = format!("bits={}", self.lane_bits());
225 write!(
226 f,
227 "{}",
228 match *self {
229 LaneType::Float(_) => format!("FloatType({inner_msg})"),
230 LaneType::Int(_) => format!("IntType({inner_msg})"),
231 }
232 )
233 }
234}
235
236impl From<shared_types::Float> for LaneType {
238 fn from(f: shared_types::Float) -> Self {
239 LaneType::Float(f)
240 }
241}
242
243impl From<shared_types::Int> for LaneType {
245 fn from(i: shared_types::Int) -> Self {
246 LaneType::Int(i)
247 }
248}
249
250pub(crate) struct LaneTypeIterator {
252 int_iter: shared_types::IntIterator,
253 float_iter: shared_types::FloatIterator,
254}
255
256impl LaneTypeIterator {
257 fn new() -> Self {
259 Self {
260 int_iter: shared_types::IntIterator::new(),
261 float_iter: shared_types::FloatIterator::new(),
262 }
263 }
264}
265
266impl Iterator for LaneTypeIterator {
267 type Item = LaneType;
268 fn next(&mut self) -> Option<Self::Item> {
269 if let Some(i) = self.int_iter.next() {
270 Some(LaneType::from(i))
271 } else if let Some(f) = self.float_iter.next() {
272 Some(LaneType::from(f))
273 } else {
274 None
275 }
276 }
277}
278
279#[derive(Clone, PartialEq, Eq, Hash)]
284pub(crate) struct VectorType {
285 base: LaneType,
286 lanes: u64,
287}
288
289impl VectorType {
290 pub fn new(base: LaneType, lanes: u64) -> Self {
292 Self { base, lanes }
293 }
294
295 pub fn doc(&self) -> String {
297 format!(
298 "A SIMD vector with {} lanes containing a `{}` each.",
299 self.lane_count(),
300 self.base
301 )
302 }
303
304 pub fn lane_bits(&self) -> u64 {
306 self.base.lane_bits()
307 }
308
309 pub fn lane_count(&self) -> u64 {
311 self.lanes
312 }
313
314 pub fn lane_type(&self) -> LaneType {
316 self.base
317 }
318
319 pub fn number(&self) -> u16 {
324 let lanes_log_2: u32 = 63 - self.lane_count().leading_zeros();
325 let base_num = u32::from(self.base.number());
326 let num = (lanes_log_2 << 4) + base_num;
327 num as u16
328 }
329}
330
331impl fmt::Display for VectorType {
332 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
333 write!(f, "{}x{}", self.base, self.lane_count())
334 }
335}
336
337impl fmt::Debug for VectorType {
338 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
339 write!(
340 f,
341 "VectorType(base={}, lanes={})",
342 self.base,
343 self.lane_count()
344 )
345 }
346}
347
348#[derive(Clone, PartialEq, Eq, Hash)]
353pub(crate) struct DynamicVectorType {
354 base: LaneType,
355 unscaled_lanes: u64,
356}
357
358impl DynamicVectorType {
359 pub fn new(base: LaneType, unscaled_lanes: u64) -> Self {
361 Self {
362 base,
363 unscaled_lanes,
364 }
365 }
366
367 pub fn doc(&self) -> String {
369 format!(
370 "A dynamically-scaled SIMD vector with a minimum of {} lanes containing `{}` bits each.",
371 self.unscaled_lanes,
372 self.base
373 )
374 }
375
376 pub fn lane_bits(&self) -> u64 {
378 self.base.lane_bits()
379 }
380
381 pub fn minimum_lane_count(&self) -> u64 {
383 self.unscaled_lanes
384 }
385
386 pub fn lane_type(&self) -> LaneType {
388 self.base
389 }
390
391 pub fn number(&self) -> u16 {
398 let base_num = u32::from(self.base.number());
399 let lanes_log_2: u32 = 63 - self.minimum_lane_count().leading_zeros();
400 let num = 0x80 + (lanes_log_2 << 4) + base_num;
401 num as u16
402 }
403}
404
405impl fmt::Display for DynamicVectorType {
406 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
407 write!(f, "{}x{}xN", self.base, self.minimum_lane_count())
408 }
409}
410
411impl fmt::Debug for DynamicVectorType {
412 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
413 write!(
414 f,
415 "DynamicVectorType(base={}, lanes={})",
416 self.base,
417 self.minimum_lane_count(),
418 )
419 }
420}