Skip to content

Commit 84d660c

Browse files
introduced generic types and code refactor
1 parent 1791b35 commit 84d660c

File tree

11 files changed

+810
-692
lines changed

11 files changed

+810
-692
lines changed

Diff for: crates/intrinsic-test/src/arm/constraint.rs

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
use super::json_parser::ArgPrep;
2+
3+
use crate::common::argument::MetadataDefinition;
4+
use serde::Deserialize;
5+
use serde_json::Value;
6+
use std::ops::Range;
7+
8+
9+
#[derive(Debug, PartialEq, Clone, Deserialize)]
10+
pub enum Constraint {
11+
Equal(i64),
12+
Range(Range<i64>),
13+
}
14+
15+
impl Constraint {
16+
pub fn to_range(&self) -> Range<i64> {
17+
match self {
18+
Constraint::Equal(eq) => *eq..*eq + 1,
19+
Constraint::Range(range) => range.clone(),
20+
}
21+
}
22+
}
23+
24+
impl MetadataDefinition for Constraint {
25+
fn from_metadata(metadata: Option<Value>) -> Vec<Box<Self>> {
26+
let arg_prep: Option<ArgPrep> = metadata.and_then(|a| {
27+
if let Value::Object(_) = a {
28+
a.try_into().ok()
29+
} else {
30+
None
31+
}
32+
});
33+
let constraint: Option<Constraint> = arg_prep.and_then(|a| a.try_into().ok());
34+
vec![constraint]
35+
.into_iter()
36+
.filter_map(|a| a)
37+
.map(|a| Box::new(a))
38+
.collect()
39+
}
40+
}
41+
42+
/// ARM-specific
43+
impl TryFrom<ArgPrep> for Constraint {
44+
type Error = ();
45+
46+
fn try_from(prep: ArgPrep) -> Result<Self, Self::Error> {
47+
let parsed_ints = match prep {
48+
ArgPrep::Immediate { min, max } => Ok((min, max)),
49+
_ => Err(()),
50+
};
51+
if let Ok((min, max)) = parsed_ints {
52+
if min == max {
53+
Ok(Constraint::Equal(min))
54+
} else {
55+
Ok(Constraint::Range(min..max + 1))
56+
}
57+
} else {
58+
Err(())
59+
}
60+
}
61+
}

Diff for: crates/intrinsic-test/src/arm/functions.rs

+24-14
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
use super::argument::Argument;
21
use super::config::{AARCH_CONFIGURATIONS, POLY128_OSTREAM_DEF, build_notices};
3-
use super::format::Indentation;
4-
use super::intrinsic::Intrinsic;
2+
use super::intrinsic::ArmIntrinsicType;
3+
use crate::arm::constraint::Constraint;
4+
use crate::common::argument::Argument;
5+
use crate::common::format::Indentation;
56
use crate::common::gen_c::{compile_c, create_c_filenames, generate_c_program};
67
use crate::common::gen_rust::{compile_rust, create_rust_filenames, generate_rust_program};
8+
use crate::common::intrinsic::{Intrinsic, IntrinsicDefinition};
9+
use crate::common::intrinsic_types::IntrinsicTypeDefinition;
710
use crate::common::write_file;
811
use itertools::Itertools;
912
use rayon::prelude::*;
@@ -14,14 +17,14 @@ const PASSES: u32 = 20;
1417

1518
fn gen_code_c(
1619
indentation: Indentation,
17-
intrinsic: &Intrinsic,
18-
constraints: &[&Argument],
20+
intrinsic: &Intrinsic<ArmIntrinsicType, Constraint>,
21+
constraints: &[&Argument<ArmIntrinsicType, Constraint>],
1922
name: String,
2023
target: &str,
2124
) -> String {
2225
if let Some((current, constraints)) = constraints.split_last() {
2326
let range = current
24-
.constraints
27+
.metadata
2528
.iter()
2629
.map(|c| c.to_range())
2730
.flat_map(|r| r.into_iter());
@@ -52,11 +55,15 @@ fn gen_code_c(
5255
}
5356
}
5457

55-
fn generate_c_program_arm(header_files: &[&str], intrinsic: &Intrinsic, target: &str) -> String {
58+
fn generate_c_program_arm(
59+
header_files: &[&str],
60+
intrinsic: &Intrinsic<ArmIntrinsicType, Constraint>,
61+
target: &str,
62+
) -> String {
5663
let constraints = intrinsic
5764
.arguments
5865
.iter()
59-
.filter(|i| i.has_constraint())
66+
.filter(|&i| i.has_constraint())
6067
.collect_vec();
6168

6269
let indentation = Indentation::default();
@@ -82,13 +89,13 @@ fn generate_c_program_arm(header_files: &[&str], intrinsic: &Intrinsic, target:
8289

8390
fn gen_code_rust(
8491
indentation: Indentation,
85-
intrinsic: &Intrinsic,
86-
constraints: &[&Argument],
92+
intrinsic: &Intrinsic<ArmIntrinsicType, Constraint>,
93+
constraints: &[&Argument<ArmIntrinsicType, Constraint>],
8794
name: String,
8895
) -> String {
8996
if let Some((current, constraints)) = constraints.split_last() {
9097
let range = current
91-
.constraints
98+
.metadata
9299
.iter()
93100
.map(|c| c.to_range())
94101
.flat_map(|r| r.into_iter());
@@ -118,7 +125,10 @@ fn gen_code_rust(
118125
}
119126
}
120127

121-
fn generate_rust_program_arm(intrinsic: &Intrinsic, target: &str) -> String {
128+
fn generate_rust_program_arm(
129+
intrinsic: &Intrinsic<ArmIntrinsicType, Constraint>,
130+
target: &str,
131+
) -> String {
122132
let constraints = intrinsic
123133
.arguments
124134
.iter()
@@ -220,7 +230,7 @@ fn compile_c_arm(
220230
}
221231

222232
pub fn build_c(
223-
intrinsics: &Vec<Intrinsic>,
233+
intrinsics: &Vec<Intrinsic<ArmIntrinsicType, Constraint>>,
224234
compiler: Option<&str>,
225235
target: &str,
226236
cxx_toolchain_dir: Option<&str>,
@@ -252,7 +262,7 @@ pub fn build_c(
252262
}
253263

254264
pub fn build_rust(
255-
intrinsics: &[Intrinsic],
265+
intrinsics: &[Intrinsic<ArmIntrinsicType, Constraint>],
256266
toolchain: Option<&str>,
257267
target: &str,
258268
linker: Option<&str>,

Diff for: crates/intrinsic-test/src/arm/intrinsic.rs

+80-88
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,83 @@
1-
use super::argument::ArgumentList;
2-
use super::format::Indentation;
3-
use super::types::{IntrinsicType, TypeKind};
1+
use super::constraint::Constraint;
2+
use crate::common::argument::ArgumentList;
3+
use crate::common::format::Indentation;
4+
use crate::common::intrinsic::{Intrinsic, IntrinsicDefinition};
5+
use crate::common::intrinsic_types::{
6+
BaseIntrinsicTypeDefinition, IntrinsicType, IntrinsicTypeDefinition, TypeKind
7+
};
8+
use crate::common::types::Language;
49

5-
/// An intrinsic
6-
#[derive(Debug, PartialEq, Clone)]
7-
pub struct Intrinsic {
8-
/// The function name of this intrinsic.
9-
pub name: String,
10+
#[derive(Debug, Clone, PartialEq)]
11+
pub struct ArmIntrinsicType(pub IntrinsicType);
1012

11-
/// Any arguments for this intrinsic.
12-
pub arguments: ArgumentList,
13+
impl BaseIntrinsicTypeDefinition for ArmIntrinsicType {
14+
fn kind(&self) -> TypeKind {
15+
self.0.kind()
16+
}
17+
fn inner_size(&self) -> u32 {
18+
self.0.inner_size()
19+
}
20+
fn num_lanes(&self) -> u32 {
21+
self.0.num_lanes()
22+
}
23+
fn num_vectors(&self) -> u32 {
24+
self.0.num_vectors()
25+
}
26+
fn is_simd(&self) -> bool {
27+
self.0.is_simd()
28+
}
29+
fn is_ptr(&self) -> bool {
30+
self.0.is_ptr()
31+
}
32+
fn c_scalar_type(&self) -> String {
33+
self.0.c_scalar_type()
34+
}
35+
fn rust_scalar_type(&self) -> String {
36+
self.0.rust_scalar_type()
37+
}
38+
fn c_promotion(&self) -> &str {
39+
self.0.c_promotion()
40+
}
41+
fn populate_random(&self, indentation: Indentation, loads: u32, language: &Language) -> String {
42+
self.0.populate_random(indentation, loads, language)
43+
}
44+
fn is_rust_vals_array_const(&self) -> bool {
45+
self.0.is_rust_vals_array_const()
46+
}
47+
fn as_call_param_c(&self, name: &String) -> String {
48+
self.0.as_call_param_c(name)
49+
}
50+
}
1351

14-
/// The return type of this intrinsic.
15-
pub results: IntrinsicType,
52+
impl IntrinsicDefinition<ArmIntrinsicType, Constraint> for Intrinsic<ArmIntrinsicType, Constraint> {
53+
fn arguments(&self) -> ArgumentList<ArmIntrinsicType, Constraint> {
54+
self.arguments.clone()
55+
}
1656

17-
/// Whether this intrinsic is only available on A64.
18-
pub a64_only: bool,
19-
}
57+
fn results(&self) -> ArmIntrinsicType {
58+
self.results.clone()
59+
}
60+
61+
fn name(&self) -> String {
62+
self.name.clone()
63+
}
2064

21-
impl Intrinsic {
2265
/// Generates a std::cout for the intrinsics results that will match the
2366
/// rust debug output format for the return type. The generated line assumes
2467
/// there is an int i in scope which is the current pass number.
25-
pub fn print_result_c(&self, indentation: Indentation, additional: &str) -> String {
26-
let lanes = if self.results.num_vectors() > 1 {
27-
(0..self.results.num_vectors())
68+
fn print_result_c(&self, indentation: Indentation, additional: &str) -> String {
69+
let lanes = if self.results().num_vectors() > 1 {
70+
(0..self.results().num_vectors())
2871
.map(|vector| {
2972
format!(
3073
r#""{ty}(" << {lanes} << ")""#,
31-
ty = self.results.c_single_vector_type(),
32-
lanes = (0..self.results.num_lanes())
74+
ty = self.results().c_single_vector_type(),
75+
lanes = (0..self.results().num_lanes())
3376
.map(move |idx| -> std::string::String {
3477
format!(
3578
"{cast}{lane_fn}(__return_value.val[{vector}], {lane})",
36-
cast = self.results.c_promotion(),
37-
lane_fn = self.results.get_lane_function(),
79+
cast = self.results().c_promotion(),
80+
lane_fn = self.results().get_lane_function(),
3881
lane = idx,
3982
vector = vector,
4083
)
@@ -45,13 +88,13 @@ impl Intrinsic {
4588
})
4689
.collect::<Vec<_>>()
4790
.join(r#" << ", " << "#)
48-
} else if self.results.num_lanes() > 1 {
49-
(0..self.results.num_lanes())
91+
} else if self.results().num_lanes() > 1 {
92+
(0..self.results().num_lanes())
5093
.map(|idx| -> std::string::String {
5194
format!(
5295
"{cast}{lane_fn}(__return_value, {lane})",
53-
cast = self.results.c_promotion(),
54-
lane_fn = self.results.get_lane_function(),
96+
cast = self.results().c_promotion(),
97+
lane_fn = self.results().get_lane_function(),
5598
lane = idx
5699
)
57100
})
@@ -61,77 +104,26 @@ impl Intrinsic {
61104
format!(
62105
"{promote}cast<{cast}>(__return_value)",
63106
cast = match self.results.kind() {
64-
TypeKind::Float if self.results.inner_size() == 16 => "float16_t".to_string(),
65-
TypeKind::Float if self.results.inner_size() == 32 => "float".to_string(),
66-
TypeKind::Float if self.results.inner_size() == 64 => "double".to_string(),
67-
TypeKind::Int => format!("int{}_t", self.results.inner_size()),
68-
TypeKind::UInt => format!("uint{}_t", self.results.inner_size()),
69-
TypeKind::Poly => format!("poly{}_t", self.results.inner_size()),
107+
TypeKind::Float if self.results().inner_size() == 16 => "float16_t".to_string(),
108+
TypeKind::Float if self.results().inner_size() == 32 => "float".to_string(),
109+
TypeKind::Float if self.results().inner_size() == 64 => "double".to_string(),
110+
TypeKind::Int => format!("int{}_t", self.results().inner_size()),
111+
TypeKind::UInt => format!("uint{}_t", self.results().inner_size()),
112+
TypeKind::Poly => format!("poly{}_t", self.results().inner_size()),
70113
ty => todo!("print_result_c - Unknown type: {:#?}", ty),
71114
},
72-
promote = self.results.c_promotion(),
115+
promote = self.results().c_promotion(),
73116
)
74117
};
75118

76119
format!(
77120
r#"{indentation}std::cout << "Result {additional}-" << i+1 << ": {ty}" << std::fixed << std::setprecision(150) << {lanes} << "{close}" << std::endl;"#,
78-
ty = if self.results.is_simd() {
79-
format!("{}(", self.results.c_type())
121+
ty = if self.results().is_simd() {
122+
format!("{}(", self.results().c_type())
80123
} else {
81124
String::from("")
82125
},
83-
close = if self.results.is_simd() { ")" } else { "" },
84-
)
85-
}
86-
87-
pub fn generate_loop_c(
88-
&self,
89-
indentation: Indentation,
90-
additional: &str,
91-
passes: u32,
92-
_target: &str,
93-
) -> String {
94-
let body_indentation = indentation.nested();
95-
format!(
96-
"{indentation}for (int i=0; i<{passes}; i++) {{\n\
97-
{loaded_args}\
98-
{body_indentation}auto __return_value = {intrinsic_call}({args});\n\
99-
{print_result}\n\
100-
{indentation}}}",
101-
loaded_args = self.arguments.load_values_c(body_indentation),
102-
intrinsic_call = self.name,
103-
args = self.arguments.as_call_param_c(),
104-
print_result = self.print_result_c(body_indentation, additional)
105-
)
106-
}
107-
108-
pub fn generate_loop_rust(
109-
&self,
110-
indentation: Indentation,
111-
additional: &str,
112-
passes: u32,
113-
) -> String {
114-
let constraints = self.arguments.as_constraint_parameters_rust();
115-
let constraints = if !constraints.is_empty() {
116-
format!("::<{constraints}>")
117-
} else {
118-
constraints
119-
};
120-
121-
let indentation2 = indentation.nested();
122-
let indentation3 = indentation2.nested();
123-
format!(
124-
"{indentation}for i in 0..{passes} {{\n\
125-
{indentation2}unsafe {{\n\
126-
{loaded_args}\
127-
{indentation3}let __return_value = {intrinsic_call}{const}({args});\n\
128-
{indentation3}println!(\"Result {additional}-{{}}: {{:.150?}}\", i + 1, __return_value);\n\
129-
{indentation2}}}\n\
130-
{indentation}}}",
131-
loaded_args = self.arguments.load_values_rust(indentation3),
132-
intrinsic_call = self.name,
133-
const = constraints,
134-
args = self.arguments.as_call_param_rust(),
126+
close = if self.results().is_simd() { ")" } else { "" },
135127
)
136128
}
137129
}

0 commit comments

Comments
 (0)