Skip to content

Commit c0e8a27

Browse files
feat: create parser for LoongArch intrinsics
1 parent b336645 commit c0e8a27

File tree

3 files changed

+149
-121
lines changed

3 files changed

+149
-121
lines changed

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

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ use std::fs::{self, File};
66

77
use rayon::prelude::*;
88

9+
use crate::common::intrinsic_helpers::TypeKind;
910
use crate::common::SupportedArchitectureTest;
1011
use crate::common::cli::ProcessedCli;
1112
use crate::common::compare::compare_outputs;
1213

1314
use crate::common::intrinsic::Intrinsic;
15+
use crate::loongarch::parser::get_loongson_intrinsics;
1416
use intrinsic::LoongArchIntrinsicType;
1517

1618
pub struct LoongArchArchitectureTest {
@@ -20,7 +22,23 @@ pub struct LoongArchArchitectureTest {
2022

2123
impl SupportedArchitectureTest for LoongArchArchitectureTest {
2224
fn create(cli_options: ProcessedCli) -> Box<Self> {
23-
unimplemented!("create of LoongArchIntrinsicType is not defined!")
25+
let mut intrinsics = get_loongson_intrinsics(&cli_options.filename, &cli_options.target)
26+
.expect("Error parsing input file");
27+
28+
intrinsics.sort_by(|a, b| a.name.cmp(&b.name));
29+
30+
let mut intrinsics = intrinsics
31+
.into_iter()
32+
.filter(|i| i.results.kind() != TypeKind::Void)
33+
.filter(|i| !i.arguments.iter().any(|a| a.is_ptr()))
34+
.filter(|i| !cli_options.skip.contains(&i.name))
35+
.collect::<Vec<_>>();
36+
intrinsics.dedup();
37+
38+
Box::new(Self {
39+
intrinsics,
40+
cli_options,
41+
})
2442
}
2543

2644
fn build_c_file(&self) -> bool {

crates/intrinsic-test/src/loongarch/parser.rs

Lines changed: 76 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
use std::fs::{self, File};
1+
use std::fs::File;
22
use std::io::{BufRead, BufReader};
33
use std::path::Path;
44

5+
use crate::common::argument::{Argument, ArgumentList};
56
use crate::common::intrinsic::Intrinsic;
6-
use crate::common::intrinsic_helpers::IntrinsicType;
77
use crate::loongarch::intrinsic::LoongArchIntrinsicType;
88

99
pub fn get_loongson_intrinsics(
@@ -13,12 +13,8 @@ pub fn get_loongson_intrinsics(
1313
let f = File::open(path).unwrap_or_else(|_| panic!("Failed to open {}", path.display()));
1414
let f = BufReader::new(f);
1515

16-
let mut para_num;
1716
let mut current_name: Option<String> = None;
1817
let mut asm_fmts: Vec<String> = Vec::new();
19-
let mut impl_function_str = String::new();
20-
let mut call_function_str = String::new();
21-
let mut out = String::new();
2218

2319
let mut intrinsics: Vec<Intrinsic<LoongArchIntrinsicType>> = Vec::new();
2420
for line in f.lines() {
@@ -35,37 +31,25 @@ pub fn get_loongson_intrinsics(
3531
.collect();
3632
} else if line.starts_with("data-types = ") {
3733
let current_name = current_name.clone().unwrap();
38-
let data_types: Vec<&str> = line
34+
let mut data_types: Vec<String> = line
3935
.get(12..)
4036
.unwrap()
4137
.split(',')
42-
.map(|e| e.trim())
38+
.map(|e| e.trim().to_string())
4339
.collect();
44-
let in_t;
45-
let out_t;
46-
if data_types.len() == 2 {
47-
in_t = [data_types[1], "NULL", "NULL", "NULL"];
48-
out_t = data_types[0];
49-
para_num = 1;
50-
} else if data_types.len() == 3 {
51-
in_t = [data_types[1], data_types[2], "NULL", "NULL"];
52-
out_t = data_types[0];
53-
para_num = 2;
54-
} else if data_types.len() == 4 {
55-
in_t = [data_types[1], data_types[2], data_types[3], "NULL"];
56-
out_t = data_types[0];
57-
para_num = 3;
58-
} else if data_types.len() == 5 {
59-
in_t = [data_types[1], data_types[2], data_types[3], data_types[4]];
60-
out_t = data_types[0];
61-
para_num = 4;
62-
} else {
40+
let arguments;
41+
let return_type;
42+
let data_types_len = data_types.len();
43+
if data_types_len > 0 && data_types_len < 6 {
44+
arguments = data_types.split_off(1);
45+
46+
// Being explicit here with the variable name
47+
return_type = data_types.get(0).unwrap();
48+
} else {
6349
panic!("DEBUG: line: {0} len: {1}", line, data_types.len());
6450
}
6551

66-
// TODO: implement the below functions
67-
// create list of intrinsics
68-
let intrinsic = gen_intrinsic(current_name.as_str(), asm_fmts.as_slice(), &in_t, out_t, para_num, target);
52+
let intrinsic = gen_intrinsic(current_name.as_str(), asm_fmts.clone(), arguments, return_type, target);
6953
if intrinsic.is_ok() {
7054
intrinsics.push(intrinsic.unwrap());
7155
}
@@ -76,98 +60,72 @@ pub fn get_loongson_intrinsics(
7660

7761
fn gen_intrinsic(
7862
current_name: &str,
79-
asm_fmts: &[String],
80-
in_t: &[&str; 4],
81-
out_t: &str,
82-
para_num: i32,
63+
asm_fmts: Vec<String>,
64+
args: Vec<String>,
65+
return_type: &String,
8366
target: &str,
8467
) -> Result<Intrinsic<LoongArchIntrinsicType>, Box<dyn std::error::Error>> {
85-
let type_to_ct = |t: &str| -> &str {
86-
match t {
87-
"V16QI" => "union v16qi",
88-
"V32QI" => "union v32qi",
89-
"V8HI" => "union v8hi",
90-
"V16HI" => "union v16hi",
91-
"V4SI" => "union v4si",
92-
"V8SI" => "union v8si",
93-
"V2DI" => "union v2di",
94-
"V4DI" => "union v4di",
95-
"UV16QI" => "union uv16qi",
96-
"UV32QI" => "union uv32qi",
97-
"UV8HI" => "union uv8hi",
98-
"UV16HI" => "union uv16hi",
99-
"UV4SI" => "union uv4si",
100-
"UV8SI" => "union uv8si",
101-
"UV2DI" => "union uv2di",
102-
"UV4DI" => "union uv4di",
103-
"SI" => "int32_t",
104-
"DI" => "int64_t",
105-
"USI" => "uint32_t",
106-
"UDI" => "uint64_t",
107-
"V4SF" => "union v4sf",
108-
"V8SF" => "union v8sf",
109-
"V2DF" => "union v2df",
110-
"V4DF" => "union v4df",
111-
"UQI" => "uint32_t",
112-
"QI" => "int32_t",
113-
"CVPOINTER" => "void*",
114-
"HI" => "int32_t",
115-
_ => panic!("unknown type: {t}"),
116-
}
117-
};
118-
let type_to_size = |v: &str, t: &str| -> u32 {
119-
let n = if v.starts_with('_') {
120-
v.get(1..).unwrap()
68+
let para_num = args.len();
69+
let mut arguments = asm_fmts
70+
.iter()
71+
.zip(args.iter())
72+
.enumerate()
73+
.map(|(i, (asm_fmt, arg_type))| {
74+
let ty = LoongArchIntrinsicType::from_values(asm_fmt, arg_type).unwrap();
75+
let arg = Argument::<LoongArchIntrinsicType>::new(i, format!("_{i}_{}", arg_type), ty, None);
76+
return arg;
77+
})
78+
.collect::<Vec<Argument<LoongArchIntrinsicType>>>();
79+
80+
if para_num == 1 && args[0] == "HI" {
81+
match asm_fmts[1].as_str() {
82+
"si13" | "i13" => arguments[0].ty.constant = true,
83+
"si10" => arguments[0].ty.constant = true,
84+
_ => panic!("unsupported assembly format: {:?}", asm_fmts),
85+
};
86+
} else if para_num == 2 && (args[1] == "UQI" || args[1] == "USI") {
87+
if asm_fmts[2].starts_with("ui") {
88+
arguments[1].ty.constant = true;
12189
} else {
122-
v
90+
panic!("unsupported assembly format: {:?}", asm_fmts);
12391
};
124-
match t {
125-
"A16QI" => 8,
126-
"AM16QI" => 8,
127-
"V16QI" => 8,
128-
"V32QI" => 8,
129-
"A32QI" => 8,
130-
"AM32QI" => 8,
131-
"V8HI" => 16,
132-
"V16HI" => 16,
133-
"V4SI" => 32,
134-
"V8SI" => 32,
135-
"V2DI" => 64,
136-
"V4DI" => 64,
137-
"UV16QI" => 8,
138-
"UV32QI" => 8,
139-
"UV8HI" => 16,
140-
"UV16HI" => 16,
141-
"UV4SI" => 32,
142-
"UV8SI" => 32,
143-
"UV2DI" => 64,
144-
"UV4DI" => 64,
145-
"V4SF" => 32,
146-
"V8SF" => 32,
147-
"V2DF" => 64,
148-
"V4DF" => 64,
149-
"SI" | "DI" | "USI" | "UDI" | "UQI" | "QI" | "CVPOINTER" | "HI" => 0,
150-
_ => panic!("unknown type: {t}"),
151-
}
152-
};
153-
let type_to_rp = |t: &str| -> Option<u32> {
154-
match t {
155-
"SI" | "DI" | "USI" | "UDI" | "UQI" | "QI" | "HI" | => None,
156-
"V32QI" | "V16HI" | "V8SI" | "V4DI" | "UV32QI" | "UV16HI" | "UV8SI" | "UV4DI"
157-
| "V8SF" | "V4DF" => Some(4)
158-
_ => Some(2),
159-
}
160-
};
161-
let type_to_imm = |t| -> i8 {
162-
match t {
163-
'b' => 4,
164-
'h' => 3,
165-
'w' => 2,
166-
'd' => 1,
167-
_ => panic!("unsupported type"),
168-
}
169-
};
170-
92+
} else if para_num == 2 && args[1] == "QI" {
93+
if asm_fmts[2].starts_with("si") {
94+
arguments[1].ty.constant = true;
95+
} else {
96+
panic!("unsupported assembly format: {:?}", asm_fmts);
97+
};
98+
} else if para_num == 2 && args[0] == "CVPOINTER" && args[1] == "SI" {
99+
if asm_fmts[2].starts_with("si") {
100+
arguments[1].ty.constant = true;
101+
} else {
102+
panic!("unsupported assembly format: {:?}", asm_fmts);
103+
};
104+
} else if para_num == 3 && (args[2] == "USI" || args[2] == "UQI") {
105+
if asm_fmts[2].starts_with("ui") {
106+
arguments[2].ty.constant = true;
107+
} else {
108+
panic!("unsupported assembly format: {:?}", asm_fmts);
109+
};
110+
} else if para_num == 3 && args[1] == "CVPOINTER" && args[2] == "SI" {
111+
match asm_fmts[2].as_str() {
112+
"si12" => arguments[2].ty.constant = true,
113+
_ => panic!("unsupported assembly format: {:?}", asm_fmts),
114+
};
115+
} else if para_num == 4 {
116+
match (asm_fmts[3].as_str(), current_name.chars().last().unwrap()) {
117+
("si8", t) => {
118+
arguments[2].ty.constant = true;
119+
arguments[3].ty.constant = true;
120+
},
121+
(_, _) => panic!(
122+
"unsupported assembly format: {:?} for {}",
123+
asm_fmts, current_name
124+
),
125+
};
126+
}
127+
let results = LoongArchIntrinsicType::from_values(return_type, &asm_fmts[0])?;
128+
let arguments = ArgumentList::<LoongArchIntrinsicType> { args: arguments };
171129
Ok(Intrinsic {
172130
name: current_name.to_string(),
173131
arguments,

crates/intrinsic-test/src/loongarch/types.rs

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::intrinsic::LoongArchIntrinsicType;
22
use crate::common::cli::Language;
3-
use crate::common::intrinsic_helpers::IntrinsicTypeDefinition;
3+
use crate::common::intrinsic_helpers::{IntrinsicType, IntrinsicTypeDefinition, TypeKind};
44

55
impl IntrinsicTypeDefinition for LoongArchIntrinsicType {
66
/// Gets a string containing the type in C format.
@@ -24,4 +24,56 @@ impl IntrinsicTypeDefinition for LoongArchIntrinsicType {
2424
}
2525
}
2626

27-
impl LoongArchIntrinsicType
27+
impl LoongArchIntrinsicType {
28+
/// Accepts X, Y and Z.
29+
/// Returns a `LoongArchType`
30+
pub fn from_values(asm_fmt: &String, data_type: &String) -> Result<Self, String> {
31+
let bit_len = match data_type.as_str() {
32+
"A16QI" => Some(8),
33+
"AM16QI" => Some(8),
34+
"V16QI" => Some(8),
35+
"V32QI" => Some(8),
36+
"A32QI" => Some(8),
37+
"AM32QI" => Some(8),
38+
"V8HI" => Some(16),
39+
"V16HI" => Some(16),
40+
"V4SI" => Some(32),
41+
"V8SI" => Some(32),
42+
"V2DI" => Some(64),
43+
"V4DI" => Some(64),
44+
"UV16QI" => Some(8),
45+
"UV32QI" => Some(8),
46+
"UV8HI" => Some(16),
47+
"UV16HI" => Some(16),
48+
"UV4SI" => Some(32),
49+
"UV8SI" => Some(32),
50+
"UV2DI" => Some(64),
51+
"UV4DI" => Some(64),
52+
"V4SF" => Some(32),
53+
"V8SF" => Some(32),
54+
"V2DF" => Some(64),
55+
"V4DF" => Some(64),
56+
"SI" | "DI" | "USI" | "UDI" | "UQI" | "QI" | "CVPOINTER" | "HI" => None,
57+
_ => panic!("unknown type {data_type} with ASM {asm_fmt}"),
58+
};
59+
60+
let vec_len = match data_type.as_str() {
61+
"SI" | "DI" | "USI" | "UDI" | "UQI" | "QI" | "HI" | => None,
62+
"V32QI" | "V16HI" | "V8SI" | "V4DI" | "UV32QI" | "UV16HI" | "UV8SI" | "UV4DI"
63+
| "V8SF" | "V4DF" => Some(4),
64+
_ => Some(2),
65+
};
66+
67+
Ok(LoongArchIntrinsicType {
68+
data: IntrinsicType {
69+
constant: false,
70+
ptr_constant: false,
71+
ptr: false,
72+
kind: TypeKind::Mask,
73+
bit_len,
74+
vec_len,
75+
simd_len: None
76+
}
77+
})
78+
}
79+
}

0 commit comments

Comments
 (0)