From d5a92e5322b389faedcec38bc18f8238426e52c6 Mon Sep 17 00:00:00 2001 From: Faith Ekstrand Date: Thu, 28 May 2026 17:20:28 -0400 Subject: [PATCH] kraid/isa: Emit TryFrom for all data-type-like enums Part-of: --- src/panfrost/compiler/kraid/data_type.rs | 1 + .../compiler/kraid/proc/isa/encoder.rs | 30 ++++++++++++- src/panfrost/compiler/kraid/proc/isa/enums.rs | 44 +++++++++++++++++-- 3 files changed, 70 insertions(+), 5 deletions(-) diff --git a/src/panfrost/compiler/kraid/data_type.rs b/src/panfrost/compiler/kraid/data_type.rs index 1e34daa24ca..d2390b6fbd9 100644 --- a/src/panfrost/compiler/kraid/data_type.rs +++ b/src/panfrost/compiler/kraid/data_type.rs @@ -42,6 +42,7 @@ pub enum DataType { None, F16, F32, + F64, I8, I16, I24, diff --git a/src/panfrost/compiler/kraid/proc/isa/encoder.rs b/src/panfrost/compiler/kraid/proc/isa/encoder.rs index 325625d30c0..5bae25babfb 100644 --- a/src/panfrost/compiler/kraid/proc/isa/encoder.rs +++ b/src/panfrost/compiler/kraid/proc/isa/encoder.rs @@ -832,12 +832,22 @@ impl ToTokens for InstrEnc { let mut v_idents = Vec::new(); if let Some(ve_ident) = &self.srcs.variants { let mut vars_ts = TokenStream2::new(); + let mut is_data_type = true; + let mut dt_cases_ts = TokenStream2::new(); for v_name in self.variants.keys() { let v_camel_name = to_camel_case(v_name.as_ref().unwrap()); let v_ident = Ident::new(&v_camel_name, Span::call_site()); vars_ts.extend(quote! { #v_ident, }); + + if v_name.as_ref().is_some_and(|s| is_data_type_name(s)) { + dt_cases_ts.extend(quote! { + DataType::#v_ident => Ok(#ve_ident::#v_ident), + }); + } else { + is_data_type = false; + } v_idents.push(v_ident); } @@ -847,6 +857,23 @@ impl ToTokens for InstrEnc { #vars_ts } }); + if is_data_type { + let err = format!("Unsupported {} variant", self.name); + ts.extend(quote! { + impl TryFrom for #ve_ident { + type Error = &'static str; + + fn try_from( + dt: DataType + ) -> Result<#ve_ident, &'static str> { + match dt { + #dt_cases_ts + _ => Err(#err), + } + } + } + }); + } assert_eq!(v_idents.len(), self.variants.len()); } else { assert_eq!(self.variants.len(), 1); @@ -1013,6 +1040,7 @@ pub fn gen_encoder( let mut ts = quote! { use crate::isa::*; use crate::bitview::*; + use crate::data_type::DataType; use compiler::bitset::ConstBitSet; pub type EncodedSrc = super::EncodedSrc; @@ -1059,7 +1087,7 @@ pub fn gen_encoder( ) .expect("Failed to create sample_position meta-enum"); - isa.enums.declare(&mut ts); + isa.enums.declare(&mut ts, true); let mut instrs: BTreeMap<_, InstrEnc> = Default::default(); for i in isa.instrs { diff --git a/src/panfrost/compiler/kraid/proc/isa/enums.rs b/src/panfrost/compiler/kraid/proc/isa/enums.rs index a8287b61050..b1aa647e7bd 100644 --- a/src/panfrost/compiler/kraid/proc/isa/enums.rs +++ b/src/panfrost/compiler/kraid/proc/isa/enums.rs @@ -57,6 +57,7 @@ pub struct Enum { pub arch: ArchSet, pub has_none: bool, pub is_bool: bool, + pub is_data_type: bool, pub values: BTreeMap, meta: OnceCell, } @@ -77,12 +78,19 @@ impl Enum { let camel_name = to_camel_case(&name); let ident = Ident::new(&camel_name, Span::call_site()); + // ls_multi_sr_count_m looks like a data type enum but isn't one. + // Or at least, our data type enum doesn't have enough integer types + // to satisfy it. + let may_be_data_type = + xml.children.len() > 0 && name != "ls_multi_sr_count_m"; + let mut e = Enum { name, ident, arch: xml.get_arch(arch.clone()).into(), has_none: false, is_bool: xml.children.len() == 2, + is_data_type: may_be_data_type, values: Default::default(), meta: Default::default(), }; @@ -100,6 +108,10 @@ impl Enum { e.is_bool = false; } + if !is_data_type_name(v.name.as_str()) { + e.is_data_type = false; + } + if !v.arch.is_empty() { e.values.insert(v.name.clone(), v); } @@ -113,6 +125,7 @@ impl Enum { self.arch |= other.arch; self.has_none |= other.has_none; self.is_bool &= other.is_bool; + self.is_data_type &= other.is_data_type; for (name, value) in other.values.into_iter() { use btree_map::Entry; @@ -127,7 +140,7 @@ impl Enum { } } - pub fn declare(&self, ts: &mut TokenStream2) { + pub fn declare(&self, ts: &mut TokenStream2, data_type_casts: bool) { let mut unique_values = true; let mut all_same_arch = true; let mut max_value = 0_u8; @@ -223,6 +236,30 @@ impl Enum { }); } + let err = format!("Unsupported {e_ident}"); + if self.is_data_type && data_type_casts { + let mut cases_ts = TokenStream2::new(); + for EnumValue { ident, .. } in self.values.values() { + cases_ts.extend(quote! { + DataType::#ident => Ok(#e_ident::#ident), + }); + } + ts.extend(quote! { + impl TryFrom for #e_ident { + type Error = &'static str; + + fn try_from( + dt: DataType + ) -> Result<#e_ident, &'static str> { + match dt { + #cases_ts + _ => Err(#err), + } + } + } + }); + } + if self.name == "ls_multi_sr_count_m" { let mut sr_cases_ts = TokenStream2::new(); for EnumValue { ident, name, .. } in self.values.values() { @@ -329,7 +366,6 @@ impl Enum { // Implement [Try]Encode - let err = format!("Unsupported {e_ident}"); if all_same_arch { let encode_impl = if unique_values { quote! { @@ -685,9 +721,9 @@ impl EnumSet { Ok(()) } - pub fn declare(&self, ts: &mut TokenStream2) { + pub fn declare(&self, ts: &mut TokenStream2, data_type_casts: bool) { for e in self.enums.values() { - e.declare(ts); + e.declare(ts, data_type_casts); } for me in self.meta_enums.values() {