1
1
use itertools:: Itertools ;
2
2
use std:: process:: Command ;
3
3
4
- use super :: argument:: Argument ;
4
+ use crate :: common:: constraint:: Constraint ;
5
+
5
6
use super :: indentation:: Indentation ;
6
7
use super :: intrinsic:: { IntrinsicDefinition , format_f16_return_value} ;
7
8
use super :: intrinsic_helpers:: IntrinsicTypeDefinition ;
@@ -153,66 +154,84 @@ pub fn generate_rust_test_loop<T: IntrinsicTypeDefinition>(
153
154
w : & mut impl std:: io:: Write ,
154
155
intrinsic : & dyn IntrinsicDefinition < T > ,
155
156
indentation : Indentation ,
156
- additional : & str ,
157
+ specializations : & [ Vec < u8 > ] ,
157
158
passes : u32 ,
158
159
) -> 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
+ }
165
194
166
195
let return_value = format_f16_return_value ( intrinsic) ;
167
196
let indentation2 = indentation. nested ( ) ;
168
197
let indentation3 = indentation2. nested ( ) ;
169
198
writeln ! (
170
199
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
+ }}",
178
210
loaded_args = intrinsic. arguments( ) . load_values_rust( indentation3) ,
179
- intrinsic_call = intrinsic. name( ) ,
180
- const = constraints,
181
211
args = intrinsic. arguments( ) . as_call_param_rust( ) ,
182
212
)
183
213
}
184
214
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 ( ) ;
213
232
}
214
233
215
- Ok ( ( ) )
234
+ specializations
216
235
}
217
236
218
237
// Top-level function to create complete test program
@@ -230,13 +249,10 @@ pub fn create_rust_test_module<T: IntrinsicTypeDefinition>(
230
249
arguments. gen_arglists_rust ( w, indentation. nested ( ) , PASSES ) ?;
231
250
232
251
// 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 ) ?;
240
256
241
257
writeln ! ( w, "}}" ) ?;
242
258
0 commit comments