1use super::intrinsic::ArmIntrinsicType;2use crate::common::cli::Language;3use crate::common::indentation::Indentation;4use crate::common::intrinsic_helpers::{IntrinsicType, IntrinsicTypeDefinition, Sign, TypeKind};56impl IntrinsicTypeDefinition for ArmIntrinsicType {7 /// Gets a string containing the typename for this type in C format.8 fn c_type(&self) -> String {9 let prefix = self.kind.c_prefix();10 let const_prefix = if self.constant { "const " } else { "" };1112 if let (Some(bit_len), simd_len, vec_len) = (self.bit_len, self.simd_len, self.vec_len) {13 match (simd_len, vec_len) {14 (None, None) => format!("{const_prefix}{prefix}{bit_len}_t"),15 (Some(simd), None) => format!("{prefix}{bit_len}x{simd}_t"),16 (Some(simd), Some(vec)) => format!("{prefix}{bit_len}x{simd}x{vec}_t"),17 (None, Some(_)) => todo!("{self:#?}"), // Likely an invalid case18 }19 } else {20 todo!("{self:#?}")21 }22 }2324 fn c_single_vector_type(&self) -> String {25 if let (Some(bit_len), Some(simd_len)) = (self.bit_len, self.simd_len) {26 format!(27 "{prefix}{bit_len}x{simd_len}_t",28 prefix = self.kind.c_prefix()29 )30 } else {31 unreachable!("Shouldn't be called on this type")32 }33 }3435 /// Determines the load function for this type.36 fn get_load_function(&self, language: Language) -> String {37 if let IntrinsicType {38 kind: k,39 bit_len: Some(bl),40 simd_len,41 vec_len,42 ..43 } = &self.data44 {45 let quad = if simd_len.unwrap_or(1) * bl > 64 {46 "q"47 } else {48 ""49 };5051 let choose_workaround = language == Language::C && self.target.contains("v7");52 format!(53 "vld{len}{quad}_{type}{size}",54 type = match k {55 TypeKind::Int(Sign::Unsigned) => "u",56 TypeKind::Int(Sign::Signed) => "s",57 TypeKind::Float => "f",58 // The ACLE doesn't support 64-bit polynomial loads on Armv759 // if armv7 and bl == 64, use "s", else "p"60 TypeKind::Poly => if choose_workaround && *bl == 64 {"s"} else {"p"},61 x => todo!("get_load_function TypeKind: {x:#?}"),62 },63 size = bl,64 quad = quad,65 len = vec_len.unwrap_or(1),66 )67 } else {68 todo!("get_load_function IntrinsicType: {self:#?}")69 }70 }7172 /// Determines the get lane function for this type.73 fn get_lane_function(&self) -> String {74 if let IntrinsicType {75 kind: k,76 bit_len: Some(bl),77 simd_len,78 ..79 } = &self.data80 {81 let quad = if (simd_len.unwrap_or(1) * bl) > 64 {82 "q"83 } else {84 ""85 };86 format!(87 "vget{quad}_lane_{type}{size}",88 type = match k {89 TypeKind::Int(Sign::Unsigned) => "u",90 TypeKind::Int(Sign::Signed) => "s",91 TypeKind::Float => "f",92 TypeKind::Poly => "p",93 x => todo!("get_load_function TypeKind: {x:#?}"),94 },95 size = bl,96 quad = quad,97 )98 } else {99 todo!("get_lane_function IntrinsicType: {self:#?}")100 }101 }102103 /// Generates a std::cout for the intrinsics results that will match the104 /// rust debug output format for the return type. The generated line assumes105 /// there is an int i in scope which is the current pass number.106 fn print_result_c(&self, indentation: Indentation, additional: &str) -> String {107 let lanes = if self.num_vectors() > 1 {108 (0..self.num_vectors())109 .map(|vector| {110 format!(111 r#""{ty}(" << {lanes} << ")""#,112 ty = self.c_single_vector_type(),113 lanes = (0..self.num_lanes())114 .map(move |idx| -> std::string::String {115 let lane_fn = self.get_lane_function();116 let final_cast = self.generate_final_type_cast();117 format!(118 "{final_cast}{lane_fn}(__return_value.val[{vector}], {idx})"119 )120 })121 .collect::<Vec<_>>()122 .join(r#" << ", " << "#)123 )124 })125 .collect::<Vec<_>>()126 .join(r#" << ", " << "#)127 } else if self.num_lanes() > 1 {128 (0..self.num_lanes())129 .map(|idx| -> std::string::String {130 let lane_fn = self.get_lane_function();131 let final_cast = self.generate_final_type_cast();132 format!("{final_cast}{lane_fn}(__return_value, {idx})")133 })134 .collect::<Vec<_>>()135 .join(r#" << ", " << "#)136 } else {137 format!(138 "{promote}cast<{cast}>(__return_value)",139 cast = match self.kind() {140 TypeKind::Float if self.inner_size() == 16 => "float16_t".to_string(),141 TypeKind::Float if self.inner_size() == 32 => "float".to_string(),142 TypeKind::Float if self.inner_size() == 64 => "double".to_string(),143 TypeKind::Int(Sign::Signed) => format!("int{}_t", self.inner_size()),144 TypeKind::Int(Sign::Unsigned) => format!("uint{}_t", self.inner_size()),145 TypeKind::Poly => format!("poly{}_t", self.inner_size()),146 ty => todo!("print_result_c - Unknown type: {ty:#?}"),147 },148 promote = self.generate_final_type_cast(),149 )150 };151152 format!(153 r#"{indentation}std::cout << "Result {additional}-" << i+1 << ": {ty}" << std::fixed << std::setprecision(150) << {lanes} << "{close}" << std::endl;"#,154 ty = if self.is_simd() {155 format!("{}(", self.c_type())156 } else {157 String::from("")158 },159 close = if self.is_simd() { ")" } else { "" },160 )161 }162}163164impl ArmIntrinsicType {165 pub fn from_c(s: &str, target: &str) -> Result<Self, String> {166 const CONST_STR: &str = "const";167 if let Some(s) = s.strip_suffix('*') {168 let (s, constant) = match s.trim().strip_suffix(CONST_STR) {169 Some(stripped) => (stripped, true),170 None => (s, false),171 };172 let s = s.trim_end();173 let temp_return = ArmIntrinsicType::from_c(s, target);174 temp_return.map(|mut op| {175 op.ptr = true;176 op.ptr_constant = constant;177 op178 })179 } else {180 // [const ]TYPE[{bitlen}[x{simdlen}[x{vec_len}]]][_t]181 let (mut s, constant) = match s.strip_prefix(CONST_STR) {182 Some(stripped) => (stripped.trim(), true),183 None => (s, false),184 };185 s = s.strip_suffix("_t").unwrap_or(s);186 let mut parts = s.split('x'); // [[{bitlen}], [{simdlen}], [{vec_len}] ]187 let start = parts.next().ok_or("Impossible to parse type")?;188 if let Some(digit_start) = start.find(|c: char| c.is_ascii_digit()) {189 let (arg_kind, bit_len) = start.split_at(digit_start);190 let arg_kind = arg_kind.parse::<TypeKind>()?;191 let bit_len = bit_len.parse::<u32>().map_err(|err| err.to_string())?;192 let simd_len = match parts.next() {193 Some(part) => Some(194 part.parse::<u32>()195 .map_err(|_| "Couldn't parse simd_len: {part}")?,196 ),197 None => None,198 };199 let vec_len = match parts.next() {200 Some(part) => Some(201 part.parse::<u32>()202 .map_err(|_| "Couldn't parse vec_len: {part}")?,203 ),204 None => None,205 };206 Ok(ArmIntrinsicType {207 data: IntrinsicType {208 ptr: false,209 ptr_constant: false,210 constant,211 kind: arg_kind,212 bit_len: Some(bit_len),213 simd_len,214 vec_len,215 },216 target: target.to_string(),217 })218 } else {219 let kind = start.parse::<TypeKind>()?;220 let bit_len = match kind {221 TypeKind::Int(_) => Some(32),222 _ => None,223 };224 Ok(ArmIntrinsicType {225 data: IntrinsicType {226 ptr: false,227 ptr_constant: false,228 constant,229 kind: start.parse::<TypeKind>()?,230 bit_len,231 simd_len: None,232 vec_len: None,233 },234 target: target.to_string(),235 })236 }237 }238 }239}
Code quality findings 12
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning
correctness
unchecked-indexing
"{final_cast}{lane_fn}(__return_value.val[{vector}], {idx})"
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning
correctness
unchecked-indexing
// [const ]TYPE[{bitlen}[x{simdlen}[x{vec_len}]]][_t]
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
(None, Some(_)) => todo!("{self:#?}"), // Likely an invalid case
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
todo!("{self:#?}")
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
x => todo!("get_load_function TypeKind: {x:#?}"),
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
todo!("get_load_function IntrinsicType: {self:#?}")
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
x => todo!("get_load_function TypeKind: {x:#?}"),
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
todo!("get_lane_function IntrinsicType: {self:#?}")
Maintainability Info: `todo!()` or `unimplemented!()` macros indicate incomplete code paths that will panic at runtime if reached. Ensure these are replaced with actual logic before production use.
info
correctness
todo-unimplemented
ty => todo!("print_result_c - Unknown type: {ty:#?}"),
Info: This standard library function returns a Result. Ensure the Result is handled properly (e.g., using '?', match, if let) rather than potentially panicking with .unwrap() or .expect().
info
correctness
unhandled-result
part.parse::<u32>()
Info: This standard library function returns a Result. Ensure the Result is handled properly (e.g., using '?', match, if let) rather than potentially panicking with .unwrap() or .expect().
info
correctness
unhandled-result
part.parse::<u32>()
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info
correctness
match-wildcard
let bit_len = match kind {