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