11use itertools:: Itertools ;
22use std:: process:: Command ;
33
4- use super :: argument:: Argument ;
54use super :: indentation:: Indentation ;
65use super :: intrinsic:: { IntrinsicDefinition , format_f16_return_value} ;
76use super :: intrinsic_helpers:: IntrinsicTypeDefinition ;
@@ -156,66 +155,87 @@ pub fn generate_rust_test_loop<T: IntrinsicTypeDefinition>(
156155 w : & mut impl std:: io:: Write ,
157156 intrinsic : & dyn IntrinsicDefinition < T > ,
158157 indentation : Indentation ,
159- additional : & str ,
158+ specializations : & [ Vec < u8 > ] ,
160159 passes : u32 ,
161160) -> std:: io:: Result < ( ) > {
162- let constraints = intrinsic. arguments ( ) . as_constraint_parameters_rust ( ) ;
163- let constraints = if !constraints. is_empty ( ) {
164- format ! ( "::<{constraints}>" )
165- } else {
166- constraints
167- } ;
161+ let intrinsic_name = intrinsic. name ( ) ;
162+
163+ // Each function (and each specialization) has its own type. Erase that type with a cast.
164+ let mut coerce = String :: from ( "unsafe fn(" ) ;
165+ for _ in intrinsic. arguments ( ) . iter ( ) . filter ( |a| !a. has_constraint ( ) ) {
166+ coerce += "_, " ;
167+ }
168+ coerce += ") -> _" ;
169+
170+ match specializations {
171+ [ ] => {
172+ writeln ! ( w, " let specializations = [(\" \" , {intrinsic_name})];" ) ?;
173+ }
174+ [ const_args] if const_args. is_empty ( ) => {
175+ writeln ! ( w, " let specializations = [(\" \" , {intrinsic_name})];" ) ?;
176+ }
177+ _ => {
178+ writeln ! ( w, " let specializations = [" ) ?;
179+
180+ for specialization in specializations {
181+ let mut specialization: Vec < _ > =
182+ specialization. iter ( ) . map ( |d| d. to_string ( ) ) . collect ( ) ;
183+
184+ let const_args = specialization. join ( "," ) ;
185+
186+ // The identifier is reversed.
187+ specialization. reverse ( ) ;
188+ let id = specialization. join ( "-" ) ;
189+
190+ writeln ! (
191+ w,
192+ " (\" -{id}\" , {intrinsic_name}::<{const_args}> as {coerce}),"
193+ ) ?;
194+ }
195+
196+ writeln ! ( w, " ];" ) ?;
197+ }
198+ }
168199
169200 let return_value = format_f16_return_value ( intrinsic) ;
170201 let indentation2 = indentation. nested ( ) ;
171202 let indentation3 = indentation2. nested ( ) ;
172203 writeln ! (
173204 w,
174- "{indentation}for i in 0..{passes} {{\n \
175- {indentation2}unsafe {{\n \
176- {loaded_args}\
177- {indentation3}let __return_value = {intrinsic_call}{const}({args});\n \
178- {indentation3}println!(\" Result {additional}-{{}}: {{:?}}\" , i + 1, {return_value});\n \
179- {indentation2}}}\n \
180- {indentation}}}",
205+ "\
206+ for (id, f) in specializations {{\n \
207+ for i in 0..{passes} {{\n \
208+ unsafe {{\n \
209+ {loaded_args}\
210+ let __return_value = f({args});\n \
211+ println!(\" Result {{id}}-{{}}: {{:?}}\" , i + 1, {return_value});\n \
212+ }}\n \
213+ }}\n \
214+ }}",
181215 loaded_args = intrinsic. arguments( ) . load_values_rust( indentation3) ,
182- intrinsic_call = intrinsic. name( ) ,
183- const = constraints,
184216 args = intrinsic. arguments( ) . as_call_param_rust( ) ,
185217 )
186218}
187219
188- fn generate_rust_constraint_blocks < ' a , T : IntrinsicTypeDefinition + ' a > (
189- w : & mut impl std:: io:: Write ,
190- intrinsic : & dyn IntrinsicDefinition < T > ,
191- indentation : Indentation ,
192- constraints : & mut ( impl Iterator < Item = & ' a Argument < T > > + Clone ) ,
193- name : String ,
194- ) -> std:: io:: Result < ( ) > {
195- let Some ( current) = constraints. next ( ) else {
196- return generate_rust_test_loop ( w, intrinsic, indentation, & name, PASSES ) ;
197- } ;
198-
199- let body_indentation = indentation. nested ( ) ;
200- for i in current. constraint . iter ( ) . flat_map ( |c| c. to_range ( ) ) {
201- let ty = current. ty . rust_type ( ) ;
202-
203- writeln ! ( w, "{indentation}{{" ) ?;
204-
205- writeln ! ( w, "{body_indentation}const {}: {ty} = {i};" , current. name) ?;
206-
207- generate_rust_constraint_blocks (
208- w,
209- intrinsic,
210- body_indentation,
211- & mut constraints. clone ( ) ,
212- format ! ( "{name}-{i}" ) ,
213- ) ?;
214-
215- writeln ! ( w, "{indentation}}}" ) ?;
220+ /// Generate the specializations (unique sequences of const-generic arguments) for this intrinsic.
221+ fn generate_rust_specializations < ' a > (
222+ constraints : & mut impl Iterator < Item = std:: ops:: Range < i64 > > ,
223+ ) -> Vec < Vec < u8 > > {
224+ let mut specializations = vec ! [ vec![ ] ] ;
225+
226+ for constraint in constraints {
227+ specializations = constraint
228+ . flat_map ( |right| {
229+ specializations. iter ( ) . map ( move |left| {
230+ let mut left = left. clone ( ) ;
231+ left. push ( u8:: try_from ( right) . unwrap ( ) ) ;
232+ left
233+ } )
234+ } )
235+ . collect ( ) ;
216236 }
217237
218- Ok ( ( ) )
238+ specializations
219239}
220240
221241// Top-level function to create complete test program
@@ -233,13 +253,13 @@ pub fn create_rust_test_module<T: IntrinsicTypeDefinition>(
233253 arguments. gen_arglists_rust ( w, indentation. nested ( ) , PASSES ) ?;
234254
235255 // Define any const generics as `const` items, then generate the actual test loop.
236- generate_rust_constraint_blocks (
237- w ,
238- intrinsic ,
239- indentation . nested ( ) ,
240- & mut arguments . iter ( ) . rev ( ) . filter ( |i| i . has_constraint ( ) ) ,
241- Default :: default ( ) ,
242- ) ?;
256+ let specializations = generate_rust_specializations (
257+ & mut arguments
258+ . iter ( )
259+ . filter_map ( |i| i . constraint . as_ref ( ) . map ( |v| v . to_range ( ) ) ) ,
260+ ) ;
261+
262+ generate_rust_test_loop ( w , intrinsic , indentation , & specializations , PASSES ) ?;
243263
244264 writeln ! ( w, "}}" ) ?;
245265
0 commit comments