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 ;
@@ -188,66 +187,87 @@ pub fn generate_rust_test_loop<T: IntrinsicTypeDefinition>(
188187 w : & mut impl std:: io:: Write ,
189188 intrinsic : & dyn IntrinsicDefinition < T > ,
190189 indentation : Indentation ,
191- additional : & str ,
190+ specializations : & [ Vec < u8 > ] ,
192191 passes : u32 ,
193192) -> std:: io:: Result < ( ) > {
194- let constraints = intrinsic. arguments ( ) . as_constraint_parameters_rust ( ) ;
195- let constraints = if !constraints. is_empty ( ) {
196- format ! ( "::<{constraints}>" )
197- } else {
198- constraints
199- } ;
193+ let intrinsic_name = intrinsic. name ( ) ;
194+
195+ // Each function (and each specialization) has its own type. Erase that type with a cast.
196+ let mut coerce = String :: from ( "unsafe fn(" ) ;
197+ for _ in intrinsic. arguments ( ) . iter ( ) . filter ( |a| !a. has_constraint ( ) ) {
198+ coerce += "_, " ;
199+ }
200+ coerce += ") -> _" ;
201+
202+ match specializations {
203+ [ ] => {
204+ writeln ! ( w, " let specializations = [(\" \" , {intrinsic_name})];" ) ?;
205+ }
206+ [ const_args] if const_args. is_empty ( ) => {
207+ writeln ! ( w, " let specializations = [(\" \" , {intrinsic_name})];" ) ?;
208+ }
209+ _ => {
210+ writeln ! ( w, " let specializations = [" ) ?;
211+
212+ for specialization in specializations {
213+ let mut specialization: Vec < _ > =
214+ specialization. iter ( ) . map ( |d| d. to_string ( ) ) . collect ( ) ;
215+
216+ let const_args = specialization. join ( "," ) ;
217+
218+ // The identifier is reversed.
219+ specialization. reverse ( ) ;
220+ let id = specialization. join ( "-" ) ;
221+
222+ writeln ! (
223+ w,
224+ " (\" -{id}\" , {intrinsic_name}::<{const_args}> as {coerce}),"
225+ ) ?;
226+ }
227+
228+ writeln ! ( w, " ];" ) ?;
229+ }
230+ }
200231
201232 let return_value = format_f16_return_value ( intrinsic) ;
202233 let indentation2 = indentation. nested ( ) ;
203234 let indentation3 = indentation2. nested ( ) ;
204235 writeln ! (
205236 w,
206- "{indentation}for i in 0..{passes} {{\n \
207- {indentation2}unsafe {{\n \
208- {loaded_args}\
209- {indentation3}let __return_value = {intrinsic_call}{const}({args});\n \
210- {indentation3}println!(\" Result {additional}-{{}}: {{:?}}\" , i + 1, {return_value});\n \
211- {indentation2}}}\n \
212- {indentation}}}",
237+ "\
238+ for (id, f) in specializations {{\n \
239+ for i in 0..{passes} {{\n \
240+ unsafe {{\n \
241+ {loaded_args}\
242+ let __return_value = f({args});\n \
243+ println!(\" Result {{id}}-{{}}: {{:?}}\" , i + 1, {return_value});\n \
244+ }}\n \
245+ }}\n \
246+ }}",
213247 loaded_args = intrinsic. arguments( ) . load_values_rust( indentation3) ,
214- intrinsic_call = intrinsic. name( ) ,
215- const = constraints,
216248 args = intrinsic. arguments( ) . as_call_param_rust( ) ,
217249 )
218250}
219251
220- fn generate_rust_constraint_blocks < ' a , T : IntrinsicTypeDefinition + ' a > (
221- w : & mut impl std:: io:: Write ,
222- intrinsic : & dyn IntrinsicDefinition < T > ,
223- indentation : Indentation ,
224- constraints : & mut ( impl Iterator < Item = & ' a Argument < T > > + Clone ) ,
225- name : String ,
226- ) -> std:: io:: Result < ( ) > {
227- let Some ( current) = constraints. next ( ) else {
228- return generate_rust_test_loop ( w, intrinsic, indentation, & name, PASSES ) ;
229- } ;
230-
231- let body_indentation = indentation. nested ( ) ;
232- for i in current. constraint . iter ( ) . flat_map ( |c| c. to_range ( ) ) {
233- let ty = current. ty . rust_type ( ) ;
234-
235- writeln ! ( w, "{indentation}{{" ) ?;
236-
237- writeln ! ( w, "{body_indentation}const {}: {ty} = {i};" , current. name) ?;
238-
239- generate_rust_constraint_blocks (
240- w,
241- intrinsic,
242- body_indentation,
243- & mut constraints. clone ( ) ,
244- format ! ( "{name}-{i}" ) ,
245- ) ?;
246-
247- writeln ! ( w, "{indentation}}}" ) ?;
252+ /// Generate the specializations (unique sequences of const-generic arguments) for this intrinsic.
253+ fn generate_rust_specializations < ' a > (
254+ constraints : & mut impl Iterator < Item = std:: ops:: Range < i64 > > ,
255+ ) -> Vec < Vec < u8 > > {
256+ let mut specializations = vec ! [ vec![ ] ] ;
257+
258+ for constraint in constraints {
259+ specializations = constraint
260+ . flat_map ( |right| {
261+ specializations. iter ( ) . map ( move |left| {
262+ let mut left = left. clone ( ) ;
263+ left. push ( u8:: try_from ( right) . unwrap ( ) ) ;
264+ left
265+ } )
266+ } )
267+ . collect ( ) ;
248268 }
249269
250- Ok ( ( ) )
270+ specializations
251271}
252272
253273// Top-level function to create complete test program
@@ -265,13 +285,13 @@ pub fn create_rust_test_module<T: IntrinsicTypeDefinition>(
265285 arguments. gen_arglists_rust ( w, indentation. nested ( ) , PASSES ) ?;
266286
267287 // Define any const generics as `const` items, then generate the actual test loop.
268- generate_rust_constraint_blocks (
269- w ,
270- intrinsic ,
271- indentation . nested ( ) ,
272- & mut arguments . iter ( ) . rev ( ) . filter ( |i| i . has_constraint ( ) ) ,
273- Default :: default ( ) ,
274- ) ?;
288+ let specializations = generate_rust_specializations (
289+ & mut arguments
290+ . iter ( )
291+ . filter_map ( |i| i . constraint . as_ref ( ) . map ( |v| v . to_range ( ) ) ) ,
292+ ) ;
293+
294+ generate_rust_test_loop ( w , intrinsic , indentation , & specializations , PASSES ) ?;
275295
276296 writeln ! ( w, "}}" ) ?;
277297
0 commit comments