diff options
Diffstat (limited to 'library/stdarch/crates/stdarch-gen-arm/src/matching.rs')
| -rw-r--r-- | library/stdarch/crates/stdarch-gen-arm/src/matching.rs | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/library/stdarch/crates/stdarch-gen-arm/src/matching.rs b/library/stdarch/crates/stdarch-gen-arm/src/matching.rs new file mode 100644 index 00000000000..0c480620428 --- /dev/null +++ b/library/stdarch/crates/stdarch-gen-arm/src/matching.rs @@ -0,0 +1,170 @@ +use proc_macro2::TokenStream; +use quote::ToTokens; +use serde::{Deserialize, Serialize}; +use std::fmt; + +use crate::context::{self, LocalContext}; +use crate::typekinds::{BaseType, BaseTypeKind, TypeKind}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct MatchSizeValues<T> { + pub default: T, + pub byte: Option<T>, + pub halfword: Option<T>, + pub doubleword: Option<T>, +} + +impl<T> MatchSizeValues<T> { + pub fn get(&mut self, ty: &TypeKind, ctx: &LocalContext) -> context::Result<&T> { + let base_ty = if let Some(w) = ty.wildcard() { + ctx.provide_type_wildcard(w)? + } else { + ty.clone() + }; + + if let BaseType::Sized(_, bitsize) = base_ty.base_type().unwrap() { + match (bitsize, &self.byte, &self.halfword, &self.doubleword) { + (64, _, _, Some(v)) | (16, _, Some(v), _) | (8, Some(v), _, _) => Ok(v), + _ => Ok(&self.default), + } + } else { + Err(format!("cannot match bitsize to unsized type {ty:?}!")) + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct MatchKindValues<T> { + pub default: T, + pub float: Option<T>, + pub unsigned: Option<T>, +} + +impl<T> MatchKindValues<T> { + pub fn get(&mut self, ty: &TypeKind, ctx: &LocalContext) -> context::Result<&T> { + let base_ty = if let Some(w) = ty.wildcard() { + ctx.provide_type_wildcard(w)? + } else { + ty.clone() + }; + + match ( + base_ty.base_type().unwrap().kind(), + &self.float, + &self.unsigned, + ) { + (BaseTypeKind::Float, Some(v), _) | (BaseTypeKind::UInt, _, Some(v)) => Ok(v), + _ => Ok(&self.default), + } + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged, deny_unknown_fields)] +pub enum SizeMatchable<T> { + Matched(T), + Unmatched { + match_size: Option<TypeKind>, + #[serde(flatten)] + values: MatchSizeValues<Box<T>>, + }, +} + +impl<T: Clone> SizeMatchable<T> { + pub fn perform_match(&mut self, ctx: &LocalContext) -> context::Result { + match self { + Self::Unmatched { + match_size: None, + values: MatchSizeValues { default, .. }, + } => *self = Self::Matched(*default.to_owned()), + Self::Unmatched { + match_size: Some(ty), + values, + } => *self = Self::Matched(*values.get(ty, ctx)?.to_owned()), + _ => {} + } + Ok(()) + } +} + +impl<T: fmt::Debug> AsRef<T> for SizeMatchable<T> { + fn as_ref(&self) -> &T { + if let SizeMatchable::Matched(v) = self { + v + } else { + panic!("no match for {self:?} was performed"); + } + } +} + +impl<T: fmt::Debug> AsMut<T> for SizeMatchable<T> { + fn as_mut(&mut self) -> &mut T { + if let SizeMatchable::Matched(v) = self { + v + } else { + panic!("no match for {self:?} was performed"); + } + } +} + +impl<T: fmt::Debug + ToTokens> ToTokens for SizeMatchable<T> { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.as_ref().to_tokens(tokens) + } +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged, deny_unknown_fields)] +pub enum KindMatchable<T> { + Matched(T), + Unmatched { + match_kind: Option<TypeKind>, + #[serde(flatten)] + values: MatchKindValues<Box<T>>, + }, +} + +impl<T: Clone> KindMatchable<T> { + pub fn perform_match(&mut self, ctx: &LocalContext) -> context::Result { + match self { + Self::Unmatched { + match_kind: None, + values: MatchKindValues { default, .. }, + } => *self = Self::Matched(*default.to_owned()), + Self::Unmatched { + match_kind: Some(ty), + values, + } => *self = Self::Matched(*values.get(ty, ctx)?.to_owned()), + _ => {} + } + Ok(()) + } +} + +impl<T: fmt::Debug> AsRef<T> for KindMatchable<T> { + fn as_ref(&self) -> &T { + if let KindMatchable::Matched(v) = self { + v + } else { + panic!("no match for {self:?} was performed"); + } + } +} + +impl<T: fmt::Debug> AsMut<T> for KindMatchable<T> { + fn as_mut(&mut self) -> &mut T { + if let KindMatchable::Matched(v) = self { + v + } else { + panic!("no match for {self:?} was performed"); + } + } +} + +impl<T: fmt::Debug + ToTokens> ToTokens for KindMatchable<T> { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.as_ref().to_tokens(tokens) + } +} |
