1- use itertools:: Itertools ;
21use rayon:: prelude:: * ;
32use std:: process:: Command ;
43
@@ -10,57 +9,6 @@ use super::intrinsic_helpers::IntrinsicTypeDefinition;
109// The number of times each intrinsic will be called.
1110const PASSES : u32 = 20 ;
1211
13- // Formats the main C program template with placeholders
14- pub fn format_c_main_template (
15- notices : & str ,
16- header_files : & [ & str ] ,
17- arch_identifier : & str ,
18- arch_specific_definitions : & [ & str ] ,
19- arglists : & str ,
20- passes : & str ,
21- ) -> String {
22- format ! (
23- r#"{notices}{header_files}
24- #include <iostream>
25- #include <cstring>
26- #include <iomanip>
27- #include <sstream>
28-
29- template<typename T1, typename T2> T1 cast(T2 x) {{
30- static_assert(sizeof(T1) == sizeof(T2), "sizeof T1 and T2 must be the same");
31- T1 ret{{}};
32- memcpy(&ret, &x, sizeof(T1));
33- return ret;
34- }}
35-
36- std::ostream& operator<<(std::ostream& os, float16_t value) {{
37- uint16_t temp = 0;
38- memcpy(&temp, &value, sizeof(float16_t));
39- std::stringstream ss;
40- ss << "0x" << std::setfill('0') << std::setw(4) << std::hex << temp;
41- os << ss.str();
42- return os;
43- }}
44-
45- #ifdef __{arch_identifier}__
46- {arch_specific_definitions}
47- #endif
48-
49- {arglists}
50-
51- int main(int argc, char **argv) {{
52- {passes}
53- return 0;
54- }}"# ,
55- header_files = header_files
56- . iter( )
57- . map( |header| format!( "#include <{header}>" ) )
58- . collect:: <Vec <_>>( )
59- . join( "\n " ) ,
60- arch_specific_definitions = arch_specific_definitions. join( "\n " ) ,
61- )
62- }
63-
6412pub fn compile_c_programs ( compiler_commands : & [ String ] ) -> bool {
6513 compiler_commands
6614 . par_iter ( )
@@ -87,14 +35,15 @@ pub fn compile_c_programs(compiler_commands: &[String]) -> bool {
8735}
8836
8937pub fn generate_c_test_loop < T : IntrinsicTypeDefinition + Sized > (
38+ w : & mut impl std:: io:: Write ,
9039 intrinsic : & dyn IntrinsicDefinition < T > ,
9140 indentation : Indentation ,
9241 additional : & str ,
9342 passes : u32 ,
94- _target : & str ,
95- ) -> String {
43+ ) -> std:: io:: Result < ( ) > {
9644 let body_indentation = indentation. nested ( ) ;
97- format ! (
45+ write ! (
46+ w,
9847 "{indentation}for (int i=0; i<{passes}; i++) {{\n \
9948 {loaded_args}\
10049 {body_indentation}auto __return_value = {intrinsic_call}({args});\n \
@@ -107,78 +56,105 @@ pub fn generate_c_test_loop<T: IntrinsicTypeDefinition + Sized>(
10756 )
10857}
10958
110- pub fn generate_c_constraint_blocks < T : IntrinsicTypeDefinition > (
59+ pub fn generate_c_constraint_blocks < ' a , T : IntrinsicTypeDefinition + ' a > (
60+ w : & mut impl std:: io:: Write ,
11161 intrinsic : & dyn IntrinsicDefinition < T > ,
11262 indentation : Indentation ,
113- constraints : & [ & Argument < T > ] ,
63+ constraints : & mut ( impl Iterator < Item = & ' a Argument < T > > + Clone ) ,
11464 name : String ,
115- target : & str ,
116- ) -> String {
117- if let Some ( ( current, constraints) ) = constraints. split_last ( ) {
118- let range = current
119- . constraint
120- . iter ( )
121- . map ( |c| c. to_range ( ) )
122- . flat_map ( |r| r. into_iter ( ) ) ;
123-
124- let body_indentation = indentation. nested ( ) ;
125- range
126- . map ( |i| {
127- format ! (
128- "{indentation}{{\n \
129- {body_indentation}{ty} {name} = {val};\n \
130- {pass}\n \
131- {indentation}}}",
132- name = current. name,
133- ty = current. ty. c_type( ) ,
134- val = i,
135- pass = generate_c_constraint_blocks(
136- intrinsic,
137- body_indentation,
138- constraints,
139- format!( "{name}-{i}" ) ,
140- target,
141- )
142- )
143- } )
144- . join ( "\n " )
145- } else {
146- generate_c_test_loop ( intrinsic, indentation, & name, PASSES , target)
65+ ) -> std:: io:: Result < ( ) > {
66+ let Some ( current) = constraints. next ( ) else {
67+ return generate_c_test_loop ( w, intrinsic, indentation, & name, PASSES ) ;
68+ } ;
69+
70+ let body_indentation = indentation. nested ( ) ;
71+ for i in current. constraint . iter ( ) . flat_map ( |c| c. to_range ( ) ) {
72+ let ty = current. ty . c_type ( ) ;
73+
74+ writeln ! ( w, "{indentation}{{" ) ?;
75+ writeln ! ( w, "{body_indentation}{ty} {} = {i};" , current. name) ?;
76+
77+ generate_c_constraint_blocks (
78+ w,
79+ intrinsic,
80+ body_indentation,
81+ & mut constraints. clone ( ) ,
82+ format ! ( "{name}-{i}" ) ,
83+ ) ?;
84+
85+ writeln ! ( w, "{indentation}}}" ) ?;
14786 }
87+
88+ Ok ( ( ) )
14889}
14990
15091// Compiles C test programs using specified compiler
15192pub fn create_c_test_program < T : IntrinsicTypeDefinition > (
93+ w : & mut impl std:: io:: Write ,
15294 intrinsic : & dyn IntrinsicDefinition < T > ,
15395 header_files : & [ & str ] ,
154- target : & str ,
96+ _target : & str ,
15597 c_target : & str ,
15698 notices : & str ,
15799 arch_specific_definitions : & [ & str ] ,
158- ) -> String {
100+ ) -> std:: io:: Result < ( ) > {
101+ let indentation = Indentation :: default ( ) ;
102+
103+ write ! ( w, "{notices}" ) ?;
104+
105+ for header in header_files {
106+ writeln ! ( w, "#include <{header}>" ) ?;
107+ }
108+
109+ writeln ! (
110+ w,
111+ r#"
112+ #include <iostream>
113+ #include <cstring>
114+ #include <iomanip>
115+ #include <sstream>
116+
117+ template<typename T1, typename T2> T1 cast(T2 x) {{
118+ static_assert(sizeof(T1) == sizeof(T2), "sizeof T1 and T2 must be the same");
119+ T1 ret{{}};
120+ memcpy(&ret, &x, sizeof(T1));
121+ return ret;
122+ }}
123+
124+ std::ostream& operator<<(std::ostream& os, float16_t value) {{
125+ uint16_t temp = 0;
126+ memcpy(&temp, &value, sizeof(float16_t));
127+ std::stringstream ss;
128+ ss << "0x" << std::setfill('0') << std::setw(4) << std::hex << temp;
129+ os << ss.str();
130+ return os;
131+ }}
132+ "#
133+ ) ?;
134+
135+ let arch_identifier = c_target;
136+ writeln ! ( w, "#ifdef __{arch_identifier}__" ) ?;
137+ for def in arch_specific_definitions {
138+ writeln ! ( w, "{def}" ) ?;
139+ }
140+ writeln ! ( w, "#endif" ) ?;
141+
142+ // Define the arrays of arguments.
159143 let arguments = intrinsic. arguments ( ) ;
160- let constraints = arguments
161- . iter ( )
162- . filter ( |& i| i. has_constraint ( ) )
163- . collect_vec ( ) ;
144+ arguments. gen_arglists_c ( w, indentation, PASSES ) ?;
164145
165- let indentation = Indentation :: default ( ) ;
166- format_c_main_template (
167- notices,
168- header_files,
169- c_target,
170- arch_specific_definitions,
171- intrinsic
172- . arguments ( )
173- . gen_arglists_c ( indentation, PASSES )
174- . as_str ( ) ,
175- generate_c_constraint_blocks (
176- intrinsic,
177- indentation. nested ( ) ,
178- constraints. as_slice ( ) ,
179- Default :: default ( ) ,
180- target,
181- )
182- . as_str ( ) ,
183- )
146+ writeln ! ( w, "int main(int argc, char **argv) {{" ) ?;
147+
148+ generate_c_constraint_blocks (
149+ w,
150+ intrinsic,
151+ indentation. nested ( ) ,
152+ & mut arguments. iter ( ) . rev ( ) . filter ( |& i| i. has_constraint ( ) ) ,
153+ Default :: default ( ) ,
154+ ) ?;
155+
156+ writeln ! ( w, " return 0;" ) ?;
157+ writeln ! ( w, "}}" ) ?;
158+
159+ Ok ( ( ) )
184160}
0 commit comments