Skip to content

Commit cc06054

Browse files
madhav-madhusoodananAmanieu
authored andcommitted
introduced generic types and code refactor
1 parent a06409d commit cc06054

File tree

11 files changed

+808
-640
lines changed

11 files changed

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

crates/intrinsic-test/src/arm/functions.rs

Lines changed: 24 additions & 14 deletions
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>,

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

Lines changed: 79 additions & 36 deletions
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,22 +104,22 @@ 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
},

crates/intrinsic-test/src/arm/json_parser.rs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
use super::argument::{Argument, ArgumentList};
2-
use super::intrinsic::Intrinsic;
3-
use super::types::IntrinsicType;
1+
use super::constraint::Constraint;
2+
use super::intrinsic::ArmIntrinsicType;
3+
use crate::common::argument::{Argument, ArgumentList};
4+
use crate::common::intrinsic::Intrinsic;
5+
use crate::common::intrinsic_types::{IntrinsicType, IntrinsicTypeDefinition};
46
use serde::Deserialize;
57
use serde_json::Value;
68
use std::collections::HashMap;
@@ -53,7 +55,7 @@ struct JsonIntrinsic {
5355
pub fn get_neon_intrinsics(
5456
filename: &Path,
5557
target: &String,
56-
) -> Result<Vec<Intrinsic>, Box<dyn std::error::Error>> {
58+
) -> Result<Vec<Intrinsic<ArmIntrinsicType, Constraint>>, Box<dyn std::error::Error>> {
5759
let file = std::fs::File::open(filename)?;
5860
let reader = std::io::BufReader::new(file);
5961
let json: Vec<JsonIntrinsic> = serde_json::from_reader(reader).expect("Couldn't parse JSON");
@@ -74,37 +76,39 @@ pub fn get_neon_intrinsics(
7476
fn json_to_intrinsic(
7577
mut intr: JsonIntrinsic,
7678
target: &String,
77-
) -> Result<Intrinsic, Box<dyn std::error::Error>> {
79+
) -> Result<Intrinsic<ArmIntrinsicType, Constraint>, Box<dyn std::error::Error>> {
7880
let name = intr.name.replace(['[', ']'], "");
7981

80-
let results = IntrinsicType::from_c(&intr.return_type.value, target)?;
82+
let results = ArmIntrinsicType::from_c(&intr.return_type.value, target)?;
8183

8284
let args = intr
8385
.arguments
8486
.into_iter()
8587
.enumerate()
8688
.map(|(i, arg)| {
87-
// let arg_name = Argument::type_and_name_from_c(&arg).1;
88-
let mut arg = Argument::from_c(i, &arg, target, intr.args_prep.as_mut());
89+
let arg_name = Argument::<ArmIntrinsicType, Constraint>::type_and_name_from_c(&arg).1;
90+
let metadata = intr.args_prep.as_mut();
91+
let metadata = metadata.and_then(|a| a.remove(arg_name));
92+
let mut arg =
93+
Argument::<ArmIntrinsicType, Constraint>::from_c(i, &arg, target, metadata);
94+
8995
// The JSON doesn't list immediates as const
90-
if let IntrinsicType::Type {
96+
let IntrinsicType {
9197
ref mut constant, ..
92-
} = arg.ty
93-
{
94-
if arg.name.starts_with("imm") {
95-
*constant = true
96-
}
98+
} = arg.ty.0;
99+
if arg.name.starts_with("imm") {
100+
*constant = true
97101
}
98102
arg
99103
})
100104
.collect();
101105

102-
let arguments = ArgumentList { args };
106+
let arguments = ArgumentList::<ArmIntrinsicType, Constraint> { args };
103107

104108
Ok(Intrinsic {
105109
name,
106110
arguments,
107-
results,
111+
results: *results,
108112
a64_only: intr.architectures == vec!["A64".to_string()],
109113
})
110114
}

0 commit comments

Comments
 (0)