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 Reference(ReferenceType),
21 Vector(VectorType),
22 DynamicVector(DynamicVectorType),
23}
24
25impl ValueType {
26 pub fn all_lane_types() -> LaneTypeIterator {
28 LaneTypeIterator::new()
29 }
30
31 pub fn all_reference_types() -> ReferenceTypeIterator {
32 ReferenceTypeIterator::new()
33 }
34
35 pub fn doc(&self) -> String {
37 match *self {
38 ValueType::Lane(l) => l.doc(),
39 ValueType::Reference(r) => r.doc(),
40 ValueType::Vector(ref v) => v.doc(),
41 ValueType::DynamicVector(ref v) => v.doc(),
42 }
43 }
44
45 pub fn lane_bits(&self) -> u64 {
47 match *self {
48 ValueType::Lane(l) => l.lane_bits(),
49 ValueType::Reference(r) => r.lane_bits(),
50 ValueType::Vector(ref v) => v.lane_bits(),
51 ValueType::DynamicVector(ref v) => v.lane_bits(),
52 }
53 }
54
55 pub fn lane_count(&self) -> u64 {
57 match *self {
58 ValueType::Vector(ref v) => v.lane_count(),
59 _ => 1,
60 }
61 }
62
63 pub fn membytes(&self) -> u64 {
65 self.width() / 8
66 }
67
68 pub fn number(&self) -> u16 {
70 match *self {
71 ValueType::Lane(l) => l.number(),
72 ValueType::Reference(r) => r.number(),
73 ValueType::Vector(ref v) => v.number(),
74 ValueType::DynamicVector(ref v) => v.number(),
75 }
76 }
77
78 pub fn rust_name(&self) -> String {
80 format!("{}{}", RUST_NAME_PREFIX, self.to_string().to_uppercase())
81 }
82
83 pub fn width(&self) -> u64 {
85 self.lane_count() * self.lane_bits()
86 }
87}
88
89impl fmt::Display for ValueType {
90 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
91 match *self {
92 ValueType::Lane(l) => l.fmt(f),
93 ValueType::Reference(r) => r.fmt(f),
94 ValueType::Vector(ref v) => v.fmt(f),
95 ValueType::DynamicVector(ref v) => v.fmt(f),
96 }
97 }
98}
99
100impl From<LaneType> for ValueType {
102 fn from(lane: LaneType) -> Self {
103 ValueType::Lane(lane)
104 }
105}
106
107impl From<ReferenceType> for ValueType {
109 fn from(reference: ReferenceType) -> Self {
110 ValueType::Reference(reference)
111 }
112}
113
114impl From<VectorType> for ValueType {
116 fn from(vector: VectorType) -> Self {
117 ValueType::Vector(vector)
118 }
119}
120
121impl From<DynamicVectorType> for ValueType {
123 fn from(vector: DynamicVectorType) -> Self {
124 ValueType::DynamicVector(vector)
125 }
126}
127
128#[derive(Clone, Copy, PartialEq, Eq, Hash)]
130pub(crate) enum LaneType {
131 Float(shared_types::Float),
132 Int(shared_types::Int),
133}
134
135impl LaneType {
136 pub fn doc(self) -> String {
138 match self {
139 LaneType::Float(shared_types::Float::F16) => String::from(
140 "A 16-bit floating point type represented in the IEEE 754-2008
141 *binary16* interchange format. This corresponds to the :c:type:`_Float16`
142 type in most C implementations.
143 WARNING: f16 support is a work-in-progress and is incomplete",
144 ),
145 LaneType::Float(shared_types::Float::F32) => String::from(
146 "A 32-bit floating point type represented in the IEEE 754-2008
147 *binary32* interchange format. This corresponds to the :c:type:`float`
148 type in most C implementations.",
149 ),
150 LaneType::Float(shared_types::Float::F64) => String::from(
151 "A 64-bit floating point type represented in the IEEE 754-2008
152 *binary64* interchange format. This corresponds to the :c:type:`double`
153 type in most C implementations.",
154 ),
155 LaneType::Float(shared_types::Float::F128) => String::from(
156 "A 128-bit floating point type represented in the IEEE 754-2008
157 *binary128* interchange format. This corresponds to the :c:type:`_Float128`
158 type in most C implementations.
159 WARNING: f128 support is a work-in-progress and is incomplete",
160 ),
161 LaneType::Int(_) if self.lane_bits() < 32 => format!(
162 "An integer type with {} bits.
163 WARNING: arithmetic on {}bit integers is incomplete",
164 self.lane_bits(),
165 self.lane_bits()
166 ),
167 LaneType::Int(_) => format!("An integer type with {} bits.", self.lane_bits()),
168 }
169 }
170
171 pub fn lane_bits(self) -> u64 {
173 match self {
174 LaneType::Float(ref f) => *f as u64,
175 LaneType::Int(ref i) => *i as u64,
176 }
177 }
178
179 pub fn number(self) -> u16 {
181 constants::LANE_BASE
182 + match self {
183 LaneType::Int(shared_types::Int::I8) => 4,
184 LaneType::Int(shared_types::Int::I16) => 5,
185 LaneType::Int(shared_types::Int::I32) => 6,
186 LaneType::Int(shared_types::Int::I64) => 7,
187 LaneType::Int(shared_types::Int::I128) => 8,
188 LaneType::Float(shared_types::Float::F16) => 9,
189 LaneType::Float(shared_types::Float::F32) => 10,
190 LaneType::Float(shared_types::Float::F64) => 11,
191 LaneType::Float(shared_types::Float::F128) => 12,
192 }
193 }
194
195 pub fn int_from_bits(num_bits: u16) -> LaneType {
196 LaneType::Int(match num_bits {
197 8 => shared_types::Int::I8,
198 16 => shared_types::Int::I16,
199 32 => shared_types::Int::I32,
200 64 => shared_types::Int::I64,
201 128 => shared_types::Int::I128,
202 _ => unreachable!("unexpected num bits for int"),
203 })
204 }
205
206 pub fn float_from_bits(num_bits: u16) -> LaneType {
207 LaneType::Float(match num_bits {
208 16 => shared_types::Float::F16,
209 32 => shared_types::Float::F32,
210 64 => shared_types::Float::F64,
211 128 => shared_types::Float::F128,
212 _ => unreachable!("unexpected num bits for float"),
213 })
214 }
215
216 pub fn by(self, lanes: u16) -> ValueType {
217 if lanes == 1 {
218 self.into()
219 } else {
220 ValueType::Vector(VectorType::new(self, lanes.into()))
221 }
222 }
223
224 pub fn to_dynamic(self, lanes: u16) -> ValueType {
225 ValueType::DynamicVector(DynamicVectorType::new(self, lanes.into()))
226 }
227}
228
229impl fmt::Display for LaneType {
230 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
231 match *self {
232 LaneType::Float(_) => write!(f, "f{}", self.lane_bits()),
233 LaneType::Int(_) => write!(f, "i{}", self.lane_bits()),
234 }
235 }
236}
237
238impl fmt::Debug for LaneType {
239 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
240 let inner_msg = format!("bits={}", self.lane_bits());
241 write!(
242 f,
243 "{}",
244 match *self {
245 LaneType::Float(_) => format!("FloatType({})", inner_msg),
246 LaneType::Int(_) => format!("IntType({})", inner_msg),
247 }
248 )
249 }
250}
251
252impl From<shared_types::Float> for LaneType {
254 fn from(f: shared_types::Float) -> Self {
255 LaneType::Float(f)
256 }
257}
258
259impl From<shared_types::Int> for LaneType {
261 fn from(i: shared_types::Int) -> Self {
262 LaneType::Int(i)
263 }
264}
265
266pub(crate) struct LaneTypeIterator {
268 int_iter: shared_types::IntIterator,
269 float_iter: shared_types::FloatIterator,
270}
271
272impl LaneTypeIterator {
273 fn new() -> Self {
275 Self {
276 int_iter: shared_types::IntIterator::new(),
277 float_iter: shared_types::FloatIterator::new(),
278 }
279 }
280}
281
282impl Iterator for LaneTypeIterator {
283 type Item = LaneType;
284 fn next(&mut self) -> Option<Self::Item> {
285 if let Some(i) = self.int_iter.next() {
286 Some(LaneType::from(i))
287 } else if let Some(f) = self.float_iter.next() {
288 Some(LaneType::from(f))
289 } else {
290 None
291 }
292 }
293}
294
295#[derive(Clone, PartialEq, Eq, Hash)]
300pub(crate) struct VectorType {
301 base: LaneType,
302 lanes: u64,
303}
304
305impl VectorType {
306 pub fn new(base: LaneType, lanes: u64) -> Self {
308 Self { base, lanes }
309 }
310
311 pub fn doc(&self) -> String {
313 format!(
314 "A SIMD vector with {} lanes containing a `{}` each.",
315 self.lane_count(),
316 self.base
317 )
318 }
319
320 pub fn lane_bits(&self) -> u64 {
322 self.base.lane_bits()
323 }
324
325 pub fn lane_count(&self) -> u64 {
327 self.lanes
328 }
329
330 pub fn lane_type(&self) -> LaneType {
332 self.base
333 }
334
335 pub fn number(&self) -> u16 {
340 let lanes_log_2: u32 = 63 - self.lane_count().leading_zeros();
341 let base_num = u32::from(self.base.number());
342 let num = (lanes_log_2 << 4) + base_num;
343 num as u16
344 }
345}
346
347impl fmt::Display for VectorType {
348 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
349 write!(f, "{}x{}", self.base, self.lane_count())
350 }
351}
352
353impl fmt::Debug for VectorType {
354 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
355 write!(
356 f,
357 "VectorType(base={}, lanes={})",
358 self.base,
359 self.lane_count()
360 )
361 }
362}
363
364#[derive(Clone, PartialEq, Eq, Hash)]
369pub(crate) struct DynamicVectorType {
370 base: LaneType,
371 unscaled_lanes: u64,
372}
373
374impl DynamicVectorType {
375 pub fn new(base: LaneType, unscaled_lanes: u64) -> Self {
377 Self {
378 base,
379 unscaled_lanes,
380 }
381 }
382
383 pub fn doc(&self) -> String {
385 format!(
386 "A dynamically-scaled SIMD vector with a minimum of {} lanes containing `{}` bits each.",
387 self.unscaled_lanes,
388 self.base
389 )
390 }
391
392 pub fn lane_bits(&self) -> u64 {
394 self.base.lane_bits()
395 }
396
397 pub fn minimum_lane_count(&self) -> u64 {
399 self.unscaled_lanes
400 }
401
402 pub fn lane_type(&self) -> LaneType {
404 self.base
405 }
406
407 pub fn number(&self) -> u16 {
414 let base_num = u32::from(self.base.number());
415 let lanes_log_2: u32 = 63 - self.minimum_lane_count().leading_zeros();
416 let num = 0x80 + (lanes_log_2 << 4) + base_num;
417 num as u16
418 }
419}
420
421impl fmt::Display for DynamicVectorType {
422 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
423 write!(f, "{}x{}xN", self.base, self.minimum_lane_count())
424 }
425}
426
427impl fmt::Debug for DynamicVectorType {
428 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
429 write!(
430 f,
431 "DynamicVectorType(base={}, lanes={})",
432 self.base,
433 self.minimum_lane_count(),
434 )
435 }
436}
437
438#[derive(Clone, Copy, PartialEq, Eq, Hash)]
440pub(crate) struct ReferenceType(pub shared_types::Reference);
441
442impl ReferenceType {
443 pub fn doc(self) -> String {
445 format!("An opaque reference type with {} bits.", self.lane_bits())
446 }
447
448 pub fn lane_bits(self) -> u64 {
450 match self.0 {
451 shared_types::Reference::R32 => 32,
452 shared_types::Reference::R64 => 64,
453 }
454 }
455
456 pub fn number(self) -> u16 {
458 constants::REFERENCE_BASE
459 + match self {
460 ReferenceType(shared_types::Reference::R32) => 0,
461 ReferenceType(shared_types::Reference::R64) => 1,
462 }
463 }
464
465 pub fn ref_from_bits(num_bits: u16) -> ReferenceType {
466 ReferenceType(match num_bits {
467 32 => shared_types::Reference::R32,
468 64 => shared_types::Reference::R64,
469 _ => unreachable!("unexpected number of bits for a reference type"),
470 })
471 }
472}
473
474impl fmt::Display for ReferenceType {
475 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
476 write!(f, "r{}", self.lane_bits())
477 }
478}
479
480impl fmt::Debug for ReferenceType {
481 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
482 write!(f, "ReferenceType(bits={})", self.lane_bits())
483 }
484}
485
486impl From<shared_types::Reference> for ReferenceType {
488 fn from(r: shared_types::Reference) -> Self {
489 ReferenceType(r)
490 }
491}
492
493pub(crate) struct ReferenceTypeIterator {
495 reference_iter: shared_types::ReferenceIterator,
496}
497
498impl ReferenceTypeIterator {
499 fn new() -> Self {
501 Self {
502 reference_iter: shared_types::ReferenceIterator::new(),
503 }
504 }
505}
506
507impl Iterator for ReferenceTypeIterator {
508 type Item = ReferenceType;
509 fn next(&mut self) -> Option<Self::Item> {
510 self.reference_iter.next().map(ReferenceType::from)
511 }
512}