1 use proc_macro2::{Ident, Span, TokenStream};
2 use quote::{quote, ToTokens};
5 collections::{BTreeSet, HashMap},
9 macro_rules! make_enum {
11 $vis:vis enum $ty:ident {
13 $field:ident $(= $value:expr)?,
17 #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
27 $vis const VALUES: &'static [Self] = &[
62 const fn bits(self) -> u32 {
76 const fn make_possible(lossless: bool) -> Self {
83 const fn make_non_lossy(possible: bool) -> Self {
90 const fn possible(self) -> bool {
92 Convertibility::Impossible => false,
93 Convertibility::Lossy | Convertibility::Lossless => true,
99 fn is_valid(self, bits: TypeBits, vector_scalar: VectorScalar) -> bool {
101 TypeKind::Float => bits >= TypeBits::Bits16,
102 TypeKind::Bool => bits == TypeBits::Bits8 || vector_scalar == VectorScalar::Vector,
103 TypeKind::UInt | TypeKind::SInt => true,
106 fn prim_ty(self, bits: TypeBits) -> Ident {
109 TypeKind::Bool => "bool".into(),
110 TypeKind::UInt => format!("u{}", bits.bits()),
111 TypeKind::SInt => format!("i{}", bits.bits()),
112 TypeKind::Float if bits == TypeBits::Bits16 => "F16".into(),
113 TypeKind::Float => format!("f{}", bits.bits()),
118 fn ty(self, bits: TypeBits, vector_scalar: VectorScalar) -> Ident {
119 let vec_prefix = match vector_scalar {
120 VectorScalar::Scalar => "",
121 VectorScalar::Vector => "Vec",
125 TypeKind::Bool => match vector_scalar {
126 VectorScalar::Scalar => "Bool".into(),
127 VectorScalar::Vector => format!("VecBool{}", bits.bits()),
129 TypeKind::UInt => format!("{}U{}", vec_prefix, bits.bits()),
130 TypeKind::SInt => format!("{}I{}", vec_prefix, bits.bits()),
131 TypeKind::Float => format!("{}F{}", vec_prefix, bits.bits()),
136 fn convertibility_to(
139 dest_type_kind: TypeKind,
141 ) -> Convertibility {
142 Convertibility::make_possible(match (self, dest_type_kind) {
143 (TypeKind::Bool, _) | (_, TypeKind::Bool) => {
144 return Convertibility::make_non_lossy(self == dest_type_kind);
146 (TypeKind::UInt, TypeKind::UInt) => dest_bits >= src_bits,
147 (TypeKind::UInt, TypeKind::SInt) => dest_bits > src_bits,
148 (TypeKind::UInt, TypeKind::Float) => dest_bits > src_bits,
149 (TypeKind::SInt, TypeKind::UInt) => false,
150 (TypeKind::SInt, TypeKind::SInt) => dest_bits >= src_bits,
151 (TypeKind::SInt, TypeKind::Float) => dest_bits > src_bits,
152 (TypeKind::Float, TypeKind::UInt) => false,
153 (TypeKind::Float, TypeKind::SInt) => false,
154 (TypeKind::Float, TypeKind::Float) => dest_bits >= src_bits,
159 #[derive(Default, Debug)]
160 struct TokenStreamSetElement {
161 token_stream: TokenStream,
165 impl Ord for TokenStreamSetElement {
166 fn cmp(&self, other: &Self) -> Ordering {
167 self.text.cmp(&other.text)
171 impl PartialOrd for TokenStreamSetElement {
172 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
173 Some(self.cmp(other))
177 impl PartialEq for TokenStreamSetElement {
178 fn eq(&self, other: &Self) -> bool {
179 self.text == other.text
183 impl Eq for TokenStreamSetElement {}
185 impl From<TokenStream> for TokenStreamSetElement {
186 fn from(token_stream: TokenStream) -> Self {
187 let text = token_stream.to_string();
188 Self { token_stream, text }
192 impl ToTokens for TokenStreamSetElement {
193 fn to_tokens(&self, tokens: &mut TokenStream) {
194 self.token_stream.to_tokens(tokens)
197 fn to_token_stream(&self) -> TokenStream {
198 self.token_stream.to_token_stream()
201 fn into_token_stream(self) -> TokenStream {
206 type TokenStreamSet = BTreeSet<TokenStreamSetElement>;
208 #[derive(Debug, Default)]
210 trait_sets_map: HashMap<(TypeKind, TypeBits, VectorScalar), TokenStreamSet>,
218 vector_scalar: VectorScalar,
219 ) -> &mut TokenStreamSet {
220 if type_kind == TypeKind::Bool && vector_scalar == VectorScalar::Scalar {
221 bits = TypeBits::Bits8;
224 .entry((type_kind, bits, vector_scalar))
231 vector_scalar: VectorScalar,
232 v: impl Into<TokenStreamSetElement>,
234 self.get(type_kind, bits, vector_scalar).insert(v.into());
237 for &bits in TypeBits::VALUES {
238 for &type_kind in TypeKind::VALUES {
239 for &vector_scalar in VectorScalar::VALUES {
240 if !type_kind.is_valid(bits, vector_scalar) {
243 let prim_ty = type_kind.prim_ty(bits);
244 let ty = type_kind.ty(bits, vector_scalar);
245 if vector_scalar == VectorScalar::Vector {
246 let scalar_ty = type_kind.ty(bits, VectorScalar::Scalar);
251 quote! { From<Self::#scalar_ty> },
254 let bool_ty = TypeKind::Bool.ty(bits, vector_scalar);
255 let uint_ty = TypeKind::UInt.ty(bits, vector_scalar);
256 let sint_ty = TypeKind::SInt.ty(bits, vector_scalar);
257 let type_trait = match type_kind {
258 TypeKind::Bool => quote! { Bool },
260 quote! { UInt<PrimUInt = #prim_ty, SignedType = Self::#sint_ty> }
263 quote! { SInt<PrimSInt = #prim_ty, UnsignedType = Self::#uint_ty> }
265 TypeKind::Float => quote! { Float<
266 BitsType = Self::#uint_ty,
267 SignedBitsType = Self::#sint_ty,
268 PrimFloat = #prim_ty,
271 self.add_trait(type_kind, bits, vector_scalar, type_trait);
276 quote! { Compare<Bool = Self::#bool_ty> },
282 quote! { Select<Self::#ty> },
287 VectorScalar::Scalar,
288 quote! { Select<Self::#ty> },
290 for &other_bits in TypeBits::VALUES {
291 for &other_type_kind in TypeKind::VALUES {
292 if !other_type_kind.is_valid(other_bits, vector_scalar) {
295 if other_bits == bits && other_type_kind == type_kind {
298 let other_ty = other_type_kind.ty(other_bits, vector_scalar);
300 other_type_kind.convertibility_to(other_bits, type_kind, bits);
301 if convertibility == Convertibility::Lossless {
306 quote! { From<Self::#other_ty> },
309 if convertibility.possible() {
314 quote! { ConvertFrom<Self::#other_ty> },
323 quote! { Make<Context = Self, Prim = #prim_ty> },
331 pub fn make_context_types() -> TokenStream {
332 let mut types = Vec::new();
333 let mut trait_sets = TraitSets::default();
335 for &bits in TypeBits::VALUES {
336 for &type_kind in TypeKind::VALUES {
337 for &vector_scalar in VectorScalar::VALUES {
338 if !type_kind.is_valid(bits, vector_scalar) {
341 let ty = type_kind.ty(bits, vector_scalar);
342 let traits = trait_sets.get(type_kind, bits, vector_scalar);
344 type #ty: #(#traits)+*;
350 /// reference used to build IR for Kazan; an empty type for `core::simd`
351 pub trait Context: Copy {
353 fn make<T: Make<Context = Self>>(self, v: T::Prim) -> T {