Skip to content

Commit b336645

Browse files
feat: adding a parser for LoongArch spec sheets
1 parent ac7200d commit b336645

File tree

2 files changed

+178
-0
lines changed

2 files changed

+178
-0
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
mod intrinsic;
2+
mod parser;
23
mod types;
34

45
use std::fs::{self, File};
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
use std::fs::{self, File};
2+
use std::io::{BufRead, BufReader};
3+
use std::path::Path;
4+
5+
use crate::common::intrinsic::Intrinsic;
6+
use crate::common::intrinsic_helpers::IntrinsicType;
7+
use crate::loongarch::intrinsic::LoongArchIntrinsicType;
8+
9+
pub fn get_loongson_intrinsics(
10+
path: &Path,
11+
target: &str
12+
) -> Result<Vec<Intrinsic<LoongArchIntrinsicType>>, Box<dyn std::error::Error>> {
13+
let f = File::open(path).unwrap_or_else(|_| panic!("Failed to open {}", path.display()));
14+
let f = BufReader::new(f);
15+
16+
let mut para_num;
17+
let mut current_name: Option<String> = None;
18+
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();
22+
23+
let mut intrinsics: Vec<Intrinsic<LoongArchIntrinsicType>> = Vec::new();
24+
for line in f.lines() {
25+
let line = line.unwrap();
26+
if line.is_empty() {
27+
continue;
28+
}
29+
if let Some(name) = line.strip_prefix("name = ") {
30+
current_name = Some(String::from(name));
31+
} else if line.starts_with("asm-fmts = ") {
32+
asm_fmts = line[10..]
33+
.split(',')
34+
.map(|v| v.trim().to_string())
35+
.collect();
36+
} else if line.starts_with("data-types = ") {
37+
let current_name = current_name.clone().unwrap();
38+
let data_types: Vec<&str> = line
39+
.get(12..)
40+
.unwrap()
41+
.split(',')
42+
.map(|e| e.trim())
43+
.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 {
63+
panic!("DEBUG: line: {0} len: {1}", line, data_types.len());
64+
}
65+
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);
69+
if intrinsic.is_ok() {
70+
intrinsics.push(intrinsic.unwrap());
71+
}
72+
}
73+
};
74+
return Ok(intrinsics)
75+
}
76+
77+
fn gen_intrinsic(
78+
current_name: &str,
79+
asm_fmts: &[String],
80+
in_t: &[&str; 4],
81+
out_t: &str,
82+
para_num: i32,
83+
target: &str,
84+
) -> 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()
121+
} else {
122+
v
123+
};
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+
171+
Ok(Intrinsic {
172+
name: current_name.to_string(),
173+
arguments,
174+
results: results,
175+
arch_tags: vec![target.to_string()],
176+
})
177+
}

0 commit comments

Comments
 (0)