1
1
use itertools:: Itertools ;
2
2
use std:: process:: Command ;
3
3
4
- use super :: argument:: Argument ;
5
4
use super :: indentation:: Indentation ;
6
5
use super :: intrinsic:: { IntrinsicDefinition , format_f16_return_value} ;
7
6
use super :: intrinsic_helpers:: IntrinsicTypeDefinition ;
@@ -156,66 +155,87 @@ pub fn generate_rust_test_loop<T: IntrinsicTypeDefinition>(
156
155
w : & mut impl std:: io:: Write ,
157
156
intrinsic : & dyn IntrinsicDefinition < T > ,
158
157
indentation : Indentation ,
159
- additional : & str ,
158
+ specializations : & [ Vec < u8 > ] ,
160
159
passes : u32 ,
161
160
) -> 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
+ }
168
199
169
200
let return_value = format_f16_return_value ( intrinsic) ;
170
201
let indentation2 = indentation. nested ( ) ;
171
202
let indentation3 = indentation2. nested ( ) ;
172
203
writeln ! (
173
204
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
+ }}",
181
215
loaded_args = intrinsic. arguments( ) . load_values_rust( indentation3) ,
182
- intrinsic_call = intrinsic. name( ) ,
183
- const = constraints,
184
216
args = intrinsic. arguments( ) . as_call_param_rust( ) ,
185
217
)
186
218
}
187
219
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 ( ) ;
216
236
}
217
237
218
- Ok ( ( ) )
238
+ specializations
219
239
}
220
240
221
241
// Top-level function to create complete test program
@@ -233,13 +253,13 @@ pub fn create_rust_test_module<T: IntrinsicTypeDefinition>(
233
253
arguments. gen_arglists_rust ( w, indentation. nested ( ) , PASSES ) ?;
234
254
235
255
// 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 ) ?;
243
263
244
264
writeln ! ( w, "}}" ) ?;
245
265
0 commit comments