Skip to content

Commit 246fef9

Browse files
fix: code cleanup
1 parent 5e28c83 commit 246fef9

File tree

7 files changed

+231
-17
lines changed

7 files changed

+231
-17
lines changed

crates/intrinsic-test/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ fn main() {
2222
| "aarch64_be-unknown-linux-gnu" => {
2323
Some(ArmArchitectureTest::create(processed_cli_options))
2424
}
25-
25+
2626
"x86_64-unknown-linux-gnu" => Some(X86ArchitectureTest::create(processed_cli_options)),
2727

2828
_ => None,

crates/intrinsic-test/src/x86/config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ pub const X86_CONFIGURATIONS: &str = r#"
2222
#![cfg_attr(target_arch = "x86_64", feature(x86_amx_intrinsics))]
2323
#![cfg_attr(target_arch = "x86_64", feature(stdarch_x86_avx512_f16))]
2424
#![feature(fmt_helpers_for_derive)]
25-
"#;
25+
"#;

crates/intrinsic-test/src/x86/constraint.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ pub fn map_constraints(imm_type: &String) -> Option<Constraint> {
1717
"_CMP_" => Some(Constraint::Range(0..32)),
1818
_ => None,
1919
}
20-
}
20+
}

crates/intrinsic-test/src/x86/intrinsic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@ impl IntrinsicDefinition<X86IntrinsicType> for Intrinsic<X86IntrinsicType> {
4040
fn print_result_c(&self, _indentation: Indentation, _additional: &str) -> String {
4141
todo!("print_result_c in Intrinsic<X86IntrinsicType> needs to be implemented!");
4242
}
43-
}
43+
}

crates/intrinsic-test/src/x86/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@ mod intrinsic;
55
mod types;
66
mod xml_parser;
77

8-
use std::fs::{self, File};
98
use rayon::prelude::*;
9+
use std::fs::{self, File};
1010

1111
use crate::common::cli::ProcessedCli;
12+
use crate::common::gen_c::{write_main_cpp, write_mod_cpp};
1213
use crate::common::intrinsic::{Intrinsic, IntrinsicDefinition};
1314
use crate::common::intrinsic_helpers::TypeKind;
1415
use crate::common::{SupportedArchitectureTest, chunk_info};
15-
use crate::common::gen_c::{write_main_cpp, write_mod_cpp};
16+
use config::build_notices;
1617
use intrinsic::X86IntrinsicType;
1718
use xml_parser::get_xml_intrinsics;
18-
use config::build_notices;
1919

2020
pub struct X86ArchitectureTest {
2121
intrinsics: Vec<Intrinsic<X86IntrinsicType>>,
@@ -120,4 +120,4 @@ impl SupportedArchitectureTest for X86ArchitectureTest {
120120
fn compare_outputs(&self) -> bool {
121121
todo!("compare_outputs in X86ArchitectureTest is not implemented")
122122
}
123-
}
123+
}
Lines changed: 222 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,251 @@
1+
use std::collections::HashMap;
2+
use std::str::FromStr;
3+
4+
use itertools::Itertools;
5+
use regex::Regex;
6+
17
use super::intrinsic::X86IntrinsicType;
28
use crate::common::cli::Language;
3-
use crate::common::intrinsic_helpers::IntrinsicTypeDefinition;
9+
use crate::common::intrinsic_helpers::{IntrinsicType, IntrinsicTypeDefinition, Sign, TypeKind};
410
use crate::x86::xml_parser::Parameter;
511

612
impl IntrinsicTypeDefinition for X86IntrinsicType {
713
/// Gets a string containing the type in C format.
814
/// This function assumes that this value is present in the metadata hashmap.
915
fn c_type(&self) -> String {
10-
todo!("c_type from IntrinsicTypeDefinition is not defined!")
16+
self.metadata
17+
.get("type")
18+
.expect("Failed to extract the C typename in X86!")
19+
.to_string()
1120
}
1221

1322
fn c_single_vector_type(&self) -> String {
1423
// matches __m128, __m256 and similar types
15-
todo!("c_type from IntrinsicTypeDefinition is not defined!")
24+
let re = Regex::new(r"\__m\d+\").unwrap();
25+
match self.metadata.get("type") {
26+
Some(type_data) if re.is_match(type_data) => type_data.to_string(),
27+
_ => unreachable!("Shouldn't be called on this type"),
28+
}
1629
}
1730

31+
// fn rust_type(&self) -> String {
32+
// // handling edge cases first
33+
// // the general handling is implemented below
34+
// if let Some(val) = self.metadata.get("type") {
35+
// match val.as_str() {
36+
// "__m128 const *" => {
37+
// return "&__m128".to_string();
38+
// }
39+
// "__m128d const *" => {
40+
// return "&__m128d".to_string();
41+
// }
42+
// "const void*" => {
43+
// return "&__m128d".to_string();
44+
// }
45+
// _ => {}
46+
// }
47+
// }
48+
49+
// if self.kind() == TypeKind::Void && self.ptr {
50+
// // this has been handled by default settings in
51+
// // the from_param function of X86IntrinsicType
52+
// unreachable!()
53+
// }
54+
55+
// // general handling cases
56+
// let core_part = if self.kind() == TypeKind::Mask {
57+
// // all types of __mmask<int> are handled here
58+
// format!("__mask{}", self.bit_len.unwrap())
59+
// } else if self.simd_len.is_some() {
60+
// // all types of __m<int> vector types are handled here
61+
// let re = Regex::new(r"\__m\d+[a-z]*").unwrap();
62+
// let rust_type = self
63+
// .metadata
64+
// .get("type")
65+
// .map(|val| re.find(val).unwrap().as_str());
66+
// rust_type.unwrap().to_string()
67+
// } else {
68+
// format!(
69+
// "{}{}",
70+
// self.kind.rust_prefix().to_string(),
71+
// self.bit_len.unwrap()
72+
// )
73+
// };
74+
75+
// // extracting "memsize" so that even vector types can be involved
76+
// let memwidth = self
77+
// .metadata
78+
// .get("memwidth")
79+
// .map(|n| str::parse::<u32>(n).unwrap());
80+
// let prefix_part = if self.ptr && self.constant && self.bit_len.eq(&memwidth) {
81+
// "&"
82+
// } else if self.ptr && self.bit_len.eq(&memwidth) {
83+
// "&mut "
84+
// } else if self.ptr && self.constant {
85+
// "*const "
86+
// } else if self.ptr {
87+
// "*mut "
88+
// } else {
89+
// ""
90+
// };
91+
92+
// return prefix_part.to_string() + core_part.as_str();
93+
// }
94+
1895
/// Determines the load function for this type.
1996
fn get_load_function(&self, _language: Language) -> String {
20-
todo!("get_load_function from IntrinsicTypeDefinition is not defined!")
97+
if let Some(type_value) = self.metadata.get("type") {
98+
if type_value.starts_with("__mmask") {
99+
// no need of loads, since they work directly
100+
// with hex constants
101+
String::from("*")
102+
} else if type_value.starts_with("__m") {
103+
// the structure is like the follows:
104+
// if "type" starts with __m<num>{h/i/<null>},
105+
// then use either _mm_set1_epi64,
106+
// _mm256_set1_epi64 or _mm512_set1_epi64
107+
let type_val_filtered = type_value
108+
.chars()
109+
.filter(|c| c.is_numeric())
110+
.join("")
111+
.replace("128", "");
112+
format!("_mm{type_val_filtered}_set1_epi64")
113+
} else {
114+
// if it is a pointer, then rely on type conversion
115+
// If it is not any of the above type (__int<num>, __bfloat16, unsigned short, etc)
116+
// then typecast it.
117+
format!("({type_value})")
118+
}
119+
// Look for edge cases (constexpr, literal, etc)
120+
} else {
121+
unimplemented!("the value for key 'type' is not present!");
122+
}
21123
}
22124

23125
/// Determines the get lane function for this type.
24126
fn get_lane_function(&self) -> String {
25127
todo!("get_lane_function for X86IntrinsicType needs to be implemented!");
26128
}
27129

28-
fn from_c(s: &str, target: &str) -> Result<Self, String> {
29-
todo!("from_c from IntrinsicTypeDefinition is not defined!")
130+
fn from_c(s: &str) -> Result<Self, String> {
131+
let mut s_copy = s.to_string();
132+
let mut metadata: HashMap<String, String> = HashMap::new();
133+
metadata.insert("type".to_string(), s.to_string());
134+
s_copy = s_copy
135+
.replace("*", "")
136+
.replace("_", "")
137+
.replace("constexpr", "")
138+
.replace("const", "")
139+
.replace("literal", "");
140+
141+
let s_split = s_copy
142+
.split(" ")
143+
.filter_map(|s| if s.len() == 0 { None } else { Some(s) })
144+
.last();
145+
146+
let s_split = s_split.map(|s| s.chars().filter(|c| !c.is_numeric()).join(""));
147+
148+
// TODO: make the unwrapping safe
149+
let kind = TypeKind::from_str(s_split.unwrap().trim()).unwrap_or(TypeKind::Void);
150+
151+
let kind = if s.find("unsigned").is_some() {
152+
match kind {
153+
TypeKind::Int(_) => TypeKind::Int(Sign::Unsigned),
154+
TypeKind::Char(_) => TypeKind::Char(Sign::Unsigned),
155+
a => a,
156+
}
157+
} else {
158+
kind
159+
};
160+
161+
let ptr_constant = false;
162+
let constant = s.matches("const").next().is_some();
163+
let ptr = s.matches("*").next().is_some();
164+
165+
Ok(X86IntrinsicType(IntrinsicType {
166+
ptr,
167+
ptr_constant,
168+
constant,
169+
kind,
170+
bit_len: None,
171+
simd_len: None,
172+
vec_len: None,
173+
metadata,
174+
}))
30175
}
31176
}
32177

33178
impl X86IntrinsicType {
34179
pub fn from_param(param: &Parameter) -> Result<Self, String> {
35-
todo!("from_param from X86IntrinsicType is not defined!")
180+
match Self::from_c(param.type_data.as_str()) {
181+
Err(message) => Err(message),
182+
Ok(mut ret) => {
183+
// First correct the type of the parameter using param.etype.
184+
// The assumption is that the parameter of type void may have param.type
185+
// as "__m128i", "__mmask8" and the like.
186+
ret.set_metadata("etype".to_string(), param.etype.clone());
187+
ret.set_metadata("memwidth".to_string(), param.memwidth.to_string());
188+
if !param.etype.is_empty() {
189+
match TypeKind::from_str(param.etype.as_str()) {
190+
Ok(value) => {
191+
ret.kind = value;
192+
}
193+
Err(_) => {}
194+
};
195+
}
196+
197+
// check for param.etype.
198+
// extract the numeric part and set as bit-len
199+
// If param.etype is not present, guess the default bit-len
200+
201+
let mut etype_processed = param.etype.clone();
202+
etype_processed.retain(|c| c.is_numeric());
203+
204+
match str::parse::<u32>(etype_processed.as_str()) {
205+
Ok(value) => ret.bit_len = Some(value),
206+
Err(_) => {
207+
ret.bit_len = match ret.kind() {
208+
TypeKind::Char(_) => Some(8),
209+
TypeKind::BFloat => Some(16),
210+
TypeKind::Int(_) => Some(32),
211+
TypeKind::Float => Some(32),
212+
_ => None,
213+
};
214+
}
215+
}
216+
217+
// then check the param.type and extract numeric part if there are double
218+
// underscores. divide this number with bit-len and set this as simd-len.
219+
// Only __m<int> types can have a simd-len.
220+
if param.type_data.matches("__m").next().is_some()
221+
&& param.type_data.matches("__mmask").next().is_none()
222+
{
223+
let mut type_processed = param.type_data.clone();
224+
type_processed.retain(|c| c.is_numeric());
225+
ret.vec_len = match str::parse::<u32>(type_processed.as_str()) {
226+
// If bit_len is None, vec_len will be None.
227+
// Else vec_len will be (num_bits / bit_len).
228+
Ok(num_bits) => ret.bit_len.and(Some(num_bits / ret.bit_len.unwrap())),
229+
Err(_) => None,
230+
};
231+
}
232+
233+
// default settings for "void *" parameters
234+
// often used by intrinsics to denote memory address or so.
235+
if ret.kind == TypeKind::Void && ret.ptr {
236+
ret.kind = TypeKind::Int(Sign::Unsigned);
237+
ret.bit_len = Some(8);
238+
}
239+
240+
// if param.etype == IMM, then it is a constant.
241+
// else it stays unchanged.
242+
ret.constant |= param.etype == "IMM";
243+
244+
Ok(ret)
245+
}
246+
}
247+
// Tile types won't currently reach here, since the intrinsic that involve them
248+
// often return "null" type. Such intrinsics are not tested in `intrinsic-test`
249+
// currently and are filtered out at `mod.rs`.
36250
}
37-
}
251+
}

crates/intrinsic-test/src/x86/xml_parser.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,4 @@ fn xml_to_intrinsic(
112112
results: result.unwrap(),
113113
arch_tags: intr.cpuid,
114114
})
115-
}
115+
}

0 commit comments

Comments
 (0)