11use itertools:: Itertools ;
22use std:: process:: Command ;
33
4- use super :: argument:: Argument ;
4+ use crate :: common:: constraint:: Constraint ;
5+
56use super :: indentation:: Indentation ;
67use super :: intrinsic:: { IntrinsicDefinition , format_f16_return_value} ;
78use super :: intrinsic_helpers:: IntrinsicTypeDefinition ;
@@ -153,66 +154,84 @@ pub fn generate_rust_test_loop<T: IntrinsicTypeDefinition>(
153154 w : & mut impl std:: io:: Write ,
154155 intrinsic : & dyn IntrinsicDefinition < T > ,
155156 indentation : Indentation ,
156- additional : & str ,
157+ specializations : & [ Vec < u8 > ] ,
157158 passes : u32 ,
158159) -> std:: io:: Result < ( ) > {
159- let constraints = intrinsic. arguments ( ) . as_constraint_parameters_rust ( ) ;
160- let constraints = if !constraints. is_empty ( ) {
161- format ! ( "::<{constraints}>" )
162- } else {
163- constraints
164- } ;
160+ let intrinsic_name = intrinsic. name ( ) ;
161+
162+ // Each function (and each specialization) has its own type. Erase that type with a cast.
163+ let mut coerce = String :: from ( "unsafe fn(" ) ;
164+ for _ in intrinsic. arguments ( ) . iter ( ) . filter ( |a| !a. has_constraint ( ) ) {
165+ coerce += "_, " ;
166+ }
167+ coerce += ") -> _" ;
168+
169+ match specializations {
170+ [ ] => {
171+ writeln ! ( w, " let specializations = [(\" \" , {intrinsic_name})];" ) ?;
172+ }
173+ [ const_args] if const_args. is_empty ( ) => {
174+ writeln ! ( w, " let specializations = [(\" \" , {intrinsic_name})];" ) ?;
175+ }
176+ _ => {
177+ writeln ! ( w, " let specializations = [" ) ?;
178+
179+ for specialization in specializations {
180+ let specialization: Vec < _ > = specialization. iter ( ) . map ( |d| d. to_string ( ) ) . collect ( ) ;
181+
182+ let const_args = specialization. join ( "," ) ;
183+ let id = specialization. join ( "-" ) ;
184+
185+ writeln ! (
186+ w,
187+ " (\" {id}\" , {intrinsic_name}::<{const_args}> as {coerce}),"
188+ ) ?;
189+ }
190+
191+ writeln ! ( w, " ];" ) ?;
192+ }
193+ }
165194
166195 let return_value = format_f16_return_value ( intrinsic) ;
167196 let indentation2 = indentation. nested ( ) ;
168197 let indentation3 = indentation2. nested ( ) ;
169198 writeln ! (
170199 w,
171- "{indentation}for i in 0..{passes} {{\n \
172- {indentation2}unsafe {{\n \
173- {loaded_args}\
174- {indentation3}let __return_value = {intrinsic_call}{const}({args});\n \
175- {indentation3}println!(\" Result {additional}-{{}}: {{:?}}\" , i + 1, {return_value});\n \
176- {indentation2}}}\n \
177- {indentation}}}",
200+ "\
201+ for (id, f) in specializations {{\n \
202+ for i in 0..{passes} {{\n \
203+ unsafe {{\n \
204+ {loaded_args}\
205+ let __return_value = f({args});\n \
206+ println!(\" Result {{id}}-{{}}: {{:?}}\" , i + 1, {return_value});\n \
207+ }}\n \
208+ }}\n \
209+ }}",
178210 loaded_args = intrinsic. arguments( ) . load_values_rust( indentation3) ,
179- intrinsic_call = intrinsic. name( ) ,
180- const = constraints,
181211 args = intrinsic. arguments( ) . as_call_param_rust( ) ,
182212 )
183213}
184214
185- fn generate_rust_constraint_blocks < ' a , T : IntrinsicTypeDefinition + ' a > (
186- w : & mut impl std:: io:: Write ,
187- intrinsic : & dyn IntrinsicDefinition < T > ,
188- indentation : Indentation ,
189- constraints : & mut ( impl Iterator < Item = & ' a Argument < T > > + Clone ) ,
190- name : String ,
191- ) -> std:: io:: Result < ( ) > {
192- let Some ( current) = constraints. next ( ) else {
193- return generate_rust_test_loop ( w, intrinsic, indentation, & name, PASSES ) ;
194- } ;
195-
196- let body_indentation = indentation. nested ( ) ;
197- for i in current. constraint . iter ( ) . flat_map ( |c| c. to_range ( ) ) {
198- let ty = current. ty . rust_type ( ) ;
199-
200- writeln ! ( w, "{indentation}{{" ) ?;
201-
202- writeln ! ( w, "{body_indentation}const {}: {ty} = {i};" , current. name) ?;
203-
204- generate_rust_constraint_blocks (
205- w,
206- intrinsic,
207- body_indentation,
208- & mut constraints. clone ( ) ,
209- format ! ( "{name}-{i}" ) ,
210- ) ?;
211-
212- writeln ! ( w, "{indentation}}}" ) ?;
215+ /// Generate the specializations (unique sequences of const-generic arguments) for this intrinsic.
216+ fn generate_rust_specializations < ' a > (
217+ constraints : & mut ( impl Iterator < Item = & ' a Constraint > + Clone ) ,
218+ ) -> Vec < Vec < u8 > > {
219+ let mut specializations = vec ! [ vec![ ] ] ;
220+
221+ for constraint in constraints {
222+ specializations = specializations
223+ . into_iter ( )
224+ . flat_map ( |const_args| {
225+ constraint. to_range ( ) . map ( move |i| {
226+ let mut const_args = const_args. clone ( ) ;
227+ const_args. push ( u8:: try_from ( i) . unwrap ( ) ) ;
228+ const_args
229+ } )
230+ } )
231+ . collect ( ) ;
213232 }
214233
215- Ok ( ( ) )
234+ specializations
216235}
217236
218237// Top-level function to create complete test program
@@ -230,13 +249,10 @@ pub fn create_rust_test_module<T: IntrinsicTypeDefinition>(
230249 arguments. gen_arglists_rust ( w, indentation. nested ( ) , PASSES ) ?;
231250
232251 // Define any const generics as `const` items, then generate the actual test loop.
233- generate_rust_constraint_blocks (
234- w,
235- intrinsic,
236- indentation. nested ( ) ,
237- & mut arguments. iter ( ) . rev ( ) . filter ( |i| i. has_constraint ( ) ) ,
238- Default :: default ( ) ,
239- ) ?;
252+ let specializations =
253+ generate_rust_specializations ( & mut arguments. iter ( ) . filter_map ( |i| i. constraint . as_ref ( ) ) ) ;
254+
255+ generate_rust_test_loop ( w, intrinsic, indentation, & specializations, PASSES ) ?;
240256
241257 writeln ! ( w, "}}" ) ?;
242258
0 commit comments