blob: 26c156ae178aa791dd7cf35aa1b82988a0896bbc [file] [log] [blame]
use std::fmt::{self};
/* This file is acting as a bridge between the old neon types and how they
* have a fairly complex way of picking suffixes and the new world. If possible
* it would be good to clean this up. At least it is self contained and the
* logic simple */
use crate::typekinds::{BaseType, BaseTypeKind, TypeKind, VectorType};
use serde::{Deserialize, Serialize};
use std::str::FromStr;
#[allow(clippy::enum_variant_names)]
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
pub enum SuffixKind {
Normal,
Base,
NoQ,
NSuffix,
NoQNSuffix,
DupNox,
Dup,
/* Get the number of lanes or panic if there are not any Lanes */
Lane,
Rot270,
Rot270Lane,
Rot270LaneQ,
Rot180,
Rot180Lane,
Rot180LaneQ,
Rot90,
Rot90Lane,
Rot90LaneQ,
/* Force the type to be unsigned */
Unsigned,
Tuple,
NoX,
BaseByteSize,
LaneNoX,
LaneQNoX,
}
pub fn type_to_size(str_type: &str) -> i32 {
match str_type {
"int8x8_t" | "int8x16_t" | "i8" | "s8" | "uint8x8_t" | "uint8x16_t" | "u8"
| "poly8x8_t" | "poly8x16_t" => 8,
"int16x4_t" | "int16x8_t" | "i16" | "s16" | "uint16x4_t" | "uint16x8_t" | "u16"
| "float16x4_t" | "float16x8_t" | "_f16" | "poly16x4_t" | "poly16x8_t" => 16,
"int32x2_t" | "int32x4_t" | "i32" | "s32" | "uint32x2_t" | "uint32x4_t" | "u32"
| "float32x2_t" | "float32x4_t" | "f32" => 32,
"int64x1_t" | "int64x2_t" | "i64" | "s64" | "uint64x1_t" | "uint64x2_t" | "u64"
| "float64x1_t" | "float64x2_t" | "f64" | "poly64x1_t" | "poly64x2_t" | "p64" => 64,
"p128" => 128,
_ => panic!("unknown type: {str_type}"),
}
}
fn neon_get_base_and_char(ty: &VectorType) -> (u32, char, bool) {
let lanes = ty.lanes();
match ty.base_type() {
BaseType::Sized(BaseTypeKind::Float, size) => (*size, 'f', *size * lanes == 128),
BaseType::Sized(BaseTypeKind::Int, size) => (*size, 's', *size * lanes == 128),
BaseType::Sized(BaseTypeKind::UInt, size) => (*size, 'u', *size * lanes == 128),
BaseType::Sized(BaseTypeKind::Poly, size) => (*size, 'p', *size * lanes == 128),
_ => panic!("Unhandled {ty:?}"),
}
}
/* @TODO
* for the chained enum types we can safely delete them as we can index the
* types array */
pub fn make_neon_suffix(type_kind: TypeKind, suffix_kind: SuffixKind) -> String {
match type_kind {
TypeKind::Vector(ty) => {
let tuple_size = ty.tuple_size().map_or(0, |t| t.to_int());
let (base_size, prefix_char, requires_q) = neon_get_base_and_char(&ty);
let prefix_q = if requires_q { "q" } else { "" };
let lanes = ty.lanes();
match suffix_kind {
SuffixKind::Normal => {
let mut str_suffix: String = format!("{prefix_q}_{prefix_char}{base_size}");
if tuple_size > 0 {
str_suffix.push_str("_x");
str_suffix.push_str(tuple_size.to_string().as_str());
}
str_suffix
}
SuffixKind::NSuffix => {
format!("{prefix_q}_n_{prefix_char}{base_size}")
}
SuffixKind::NoQ => format!("_{prefix_char}{base_size}"),
SuffixKind::NoQNSuffix => format!("_n{prefix_char}{base_size}"),
SuffixKind::Unsigned => {
let t = type_kind.to_string();
if t.starts_with("u") {
return t;
}
format!("u{t}")
}
SuffixKind::Lane => {
if lanes == 0 {
panic!("type {type_kind} has no lanes!")
} else {
format!("{lanes}")
}
}
SuffixKind::Tuple => {
if tuple_size == 0 {
panic!("type {type_kind} has no lanes!")
} else {
format!("{tuple_size}")
}
}
SuffixKind::Base => base_size.to_string(),
SuffixKind::NoX => {
format!("{prefix_q}_{prefix_char}{base_size}")
}
SuffixKind::Dup => {
let mut str_suffix: String = format!("{prefix_q}_dup_{prefix_char}{base_size}");
if tuple_size > 0 {
str_suffix.push_str("_x");
str_suffix.push_str(tuple_size.to_string().as_str());
}
str_suffix
}
SuffixKind::DupNox => {
format!("{prefix_q}_dup_{prefix_char}{base_size}")
}
SuffixKind::LaneNoX => {
format!("{prefix_q}_lane_{prefix_char}{base_size}")
}
SuffixKind::LaneQNoX => {
format!("{prefix_q}_laneq_{prefix_char}{base_size}")
}
SuffixKind::Rot270 => {
format!("{prefix_q}_rot270_{prefix_char}{base_size}")
}
SuffixKind::Rot270Lane => {
format!("{prefix_q}_rot270_lane_{prefix_char}{base_size}")
}
SuffixKind::Rot270LaneQ => {
format!("{prefix_q}_rot270_laneq_{prefix_char}{base_size}")
}
SuffixKind::Rot180 => {
format!("{prefix_q}_rot180_{prefix_char}{base_size}")
}
SuffixKind::Rot180Lane => {
format!("{prefix_q}_rot180_lane_{prefix_char}{base_size}")
}
SuffixKind::Rot180LaneQ => {
format!("{prefix_q}_rot180_laneq_{prefix_char}{base_size}")
}
SuffixKind::Rot90 => {
format!("{prefix_q}_rot90_{prefix_char}{base_size}")
}
SuffixKind::Rot90Lane => {
format!("{prefix_q}_rot90_lane_{prefix_char}{base_size}")
}
SuffixKind::Rot90LaneQ => {
format!("{prefix_q}_rot90_laneq_{prefix_char}{base_size}")
}
SuffixKind::BaseByteSize => format!("{}", base_size / 8),
}
}
_ => panic!("Cannot only make neon vector types suffixed"),
}
}
impl FromStr for SuffixKind {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"no" => Ok(SuffixKind::Normal),
"noq" => Ok(SuffixKind::NoQ),
"N" => Ok(SuffixKind::NSuffix),
"noq_N" => Ok(SuffixKind::NoQNSuffix),
"dup_nox" => Ok(SuffixKind::DupNox),
"dup" => Ok(SuffixKind::Dup),
"lane" => Ok(SuffixKind::Lane),
"base" => Ok(SuffixKind::Base),
"tuple" => Ok(SuffixKind::Tuple),
"rot270" => Ok(SuffixKind::Rot270),
"rot270_lane" => Ok(SuffixKind::Rot270Lane),
"rot270_laneq" => Ok(SuffixKind::Rot270LaneQ),
"rot90" => Ok(SuffixKind::Rot90),
"rot90_lane" => Ok(SuffixKind::Rot90Lane),
"rot90_laneq" => Ok(SuffixKind::Rot90LaneQ),
"rot180" => Ok(SuffixKind::Rot180),
"rot180_lane" => Ok(SuffixKind::Rot180LaneQ),
"rot180_laneq" => Ok(SuffixKind::Rot180LaneQ),
"u" => Ok(SuffixKind::Unsigned),
"nox" => Ok(SuffixKind::NoX),
"base_byte_size" => Ok(SuffixKind::BaseByteSize),
"lane_nox" => Ok(SuffixKind::LaneNoX),
"laneq_nox" => Ok(SuffixKind::LaneQNoX),
_ => Err(format!("unknown suffix type: {s}")),
}
}
}
impl fmt::Display for SuffixKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SuffixKind::Normal => write!(f, "normal"),
SuffixKind::NoQ => write!(f, "NoQ"),
SuffixKind::NSuffix => write!(f, "NSuffix"),
SuffixKind::NoQNSuffix => write!(f, "NoQNSuffix"),
SuffixKind::DupNox => write!(f, "DupNox"),
SuffixKind::Dup => write!(f, "Dup",),
SuffixKind::Lane => write!(f, "Lane"),
SuffixKind::LaneNoX => write!(f, "LaneNoX"),
SuffixKind::LaneQNoX => write!(f, "LaneQNoX"),
SuffixKind::Base => write!(f, "Base"),
SuffixKind::Rot270 => write!(f, "Rot270",),
SuffixKind::Rot270Lane => write!(f, "Rot270Lane"),
SuffixKind::Rot270LaneQ => write!(f, "Rot270LaneQ"),
SuffixKind::Rot90 => write!(f, "Rot90",),
SuffixKind::Rot90Lane => write!(f, "Rot90Lane"),
SuffixKind::Rot90LaneQ => write!(f, "Rot90LaneQ"),
SuffixKind::Rot180 => write!(f, "Rot180",),
SuffixKind::Rot180Lane => write!(f, "Rot180Lane"),
SuffixKind::Rot180LaneQ => write!(f, "Rot180LaneQ"),
SuffixKind::Unsigned => write!(f, "Unsigned"),
SuffixKind::Tuple => write!(f, "Tuple"),
SuffixKind::NoX => write!(f, "NoX"),
SuffixKind::BaseByteSize => write!(f, "BaseByteSize"),
}
}
}