1use rucc_tuple::Arch;
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum Lane {
21 I8,
23 U8,
25 I16,
27 U16,
29 I32,
31 U32,
33 I64,
35 U64,
37 F16,
39 F32,
41 F64,
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47pub enum TypeName {
48 Vector(Lane, u8),
50 Sizeless,
54 Float128,
56}
57
58const AARCH64: &[(&str, TypeName)] = &[
62 ("__Int8x8_t", TypeName::Vector(Lane::I8, 8)),
63 ("__Int16x4_t", TypeName::Vector(Lane::I16, 4)),
64 ("__Int32x2_t", TypeName::Vector(Lane::I32, 2)),
65 ("__Int64x1_t", TypeName::Vector(Lane::I64, 1)),
66 ("__Uint8x8_t", TypeName::Vector(Lane::U8, 8)),
67 ("__Uint16x4_t", TypeName::Vector(Lane::U16, 4)),
68 ("__Uint32x2_t", TypeName::Vector(Lane::U32, 2)),
69 ("__Uint64x1_t", TypeName::Vector(Lane::U64, 1)),
70 ("__Poly8x8_t", TypeName::Vector(Lane::U8, 8)),
71 ("__Poly16x4_t", TypeName::Vector(Lane::U16, 4)),
72 ("__Poly64x1_t", TypeName::Vector(Lane::U64, 1)),
73 ("__Float16x4_t", TypeName::Vector(Lane::F16, 4)),
74 ("__Float32x2_t", TypeName::Vector(Lane::F32, 2)),
75 ("__Float64x1_t", TypeName::Vector(Lane::F64, 1)),
76 ("__Int8x16_t", TypeName::Vector(Lane::I8, 16)),
77 ("__Int16x8_t", TypeName::Vector(Lane::I16, 8)),
78 ("__Int32x4_t", TypeName::Vector(Lane::I32, 4)),
79 ("__Int64x2_t", TypeName::Vector(Lane::I64, 2)),
80 ("__Uint8x16_t", TypeName::Vector(Lane::U8, 16)),
81 ("__Uint16x8_t", TypeName::Vector(Lane::U16, 8)),
82 ("__Uint32x4_t", TypeName::Vector(Lane::U32, 4)),
83 ("__Uint64x2_t", TypeName::Vector(Lane::U64, 2)),
84 ("__Poly8x16_t", TypeName::Vector(Lane::U8, 16)),
85 ("__Poly16x8_t", TypeName::Vector(Lane::U16, 8)),
86 ("__Poly64x2_t", TypeName::Vector(Lane::U64, 2)),
87 ("__Float16x8_t", TypeName::Vector(Lane::F16, 8)),
88 ("__Float32x4_t", TypeName::Vector(Lane::F32, 4)),
89 ("__Float64x2_t", TypeName::Vector(Lane::F64, 2)),
90 ("__SVInt8_t", TypeName::Sizeless),
91 ("__SVInt16_t", TypeName::Sizeless),
92 ("__SVInt32_t", TypeName::Sizeless),
93 ("__SVInt64_t", TypeName::Sizeless),
94 ("__SVUint8_t", TypeName::Sizeless),
95 ("__SVUint16_t", TypeName::Sizeless),
96 ("__SVUint32_t", TypeName::Sizeless),
97 ("__SVUint64_t", TypeName::Sizeless),
98 ("__SVFloat16_t", TypeName::Sizeless),
99 ("__SVFloat32_t", TypeName::Sizeless),
100 ("__SVFloat64_t", TypeName::Sizeless),
101 ("__SVBool_t", TypeName::Sizeless),
102];
103
104const FLOAT128: &[(&str, TypeName)] = &[("__float128", TypeName::Float128)];
106
107#[must_use]
109pub(crate) fn type_names(arch: Arch) -> &'static [(&'static str, TypeName)] {
110 match arch {
111 Arch::Aarch64 => AARCH64,
112 Arch::X86_64 | Arch::X86 | Arch::PowerPc64 => FLOAT128,
113 _ => &[],
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120
121 #[test]
122 fn every_vector_is_one_of_the_two_widths_the_registers_have() {
123 let width = |lane: Lane| match lane {
124 Lane::I8 | Lane::U8 => 1,
125 Lane::I16 | Lane::U16 | Lane::F16 => 2,
126 Lane::I32 | Lane::U32 | Lane::F32 => 4,
127 Lane::I64 | Lane::U64 | Lane::F64 => 8,
128 };
129 for &(name, ty) in AARCH64 {
130 if let TypeName::Vector(lane, lanes) = ty {
131 let bytes = width(lane) * u32::from(lanes);
132 assert!(bytes == 8 || bytes == 16, "{name} is {bytes} bytes");
133 let q = name.ends_with(&format!("x{lanes}_t"));
134 assert!(q, "{name} does not say it has {lanes} lanes");
135 }
136 }
137 }
138
139 #[test]
140 fn quad_precision_has_its_old_name_where_gcc_has_it() {
141 let has = |arch| type_names(arch).iter().any(|&(name, _)| name == "__float128");
142 assert!(has(Arch::X86_64));
143 assert!(has(Arch::X86));
144 assert!(has(Arch::PowerPc64));
145 assert!(!has(Arch::Aarch64));
146 assert!(!has(Arch::Riscv64));
147 assert!(type_names(Arch::Arm).is_empty());
148 }
149}