@@ -27,38 +27,30 @@ mod musl_reference_tests {
27
27
// These files are all internal functions or otherwise miscellaneous, not
28
28
// defining a function we want to test.
29
29
const IGNORED_FILES : & [ & str ] = & [
30
- "expo2.rs" ,
30
+ "expo2.rs" , // kernel, private
31
31
"fenv.rs" ,
32
- "k_cos.rs" ,
33
- "k_cosf.rs" ,
34
- "k_expo2.rs" ,
35
- "k_expo2f.rs" ,
36
- "k_sin.rs" ,
37
- "k_sinf.rs" ,
38
- "k_tan.rs" ,
39
- "k_tanf.rs" ,
32
+ "k_cos.rs" , // kernel, private
33
+ "k_cosf.rs" , // kernel, private
34
+ "k_expo2.rs" , // kernel, private
35
+ "k_expo2f.rs" , // kernel, private
36
+ "k_sin.rs" , // kernel, private
37
+ "k_sinf.rs" , // kernel, private
38
+ "k_tan.rs" , // kernel, private
39
+ "k_tanf.rs" , // kernel, private
40
40
"mod.rs" ,
41
- "rem_pio2.rs" ,
42
- "rem_pio2_large.rs" ,
43
- "rem_pio2f.rs" ,
44
- "remquo.rs" , // more than 1 result
45
- "remquof.rs" , // more than 1 result
46
- "lgamma_r.rs" , // more than 1 result
47
- "lgammaf_r.rs" , // more than 1 result
48
- "frexp.rs" , // more than 1 result
49
- "frexpf.rs" , // more than 1 result
50
- "sincos.rs" , // more than 1 result
51
- "sincosf.rs" , // more than 1 result
52
- "modf.rs" , // more than 1 result
53
- "modff.rs" , // more than 1 result
54
- "jn.rs" , // passed, but very slow
55
- "jnf.rs" , // passed, but very slow
41
+ "rem_pio2.rs" , // kernel, private
42
+ "rem_pio2_large.rs" , // kernel, private
43
+ "rem_pio2f.rs" , // kernel, private
44
+ "sincos.rs" , // more than 1 result
45
+ "sincosf.rs" , // more than 1 result
46
+ "jn.rs" , // passed, but very slow
47
+ "jnf.rs" , // passed, but very slow
56
48
] ;
57
49
58
50
struct Function {
59
51
name : String ,
60
52
args : Vec < Ty > ,
61
- ret : Ty ,
53
+ ret : Vec < Ty > ,
62
54
tests : Vec < Test > ,
63
55
}
64
56
@@ -71,7 +63,7 @@ mod musl_reference_tests {
71
63
72
64
struct Test {
73
65
inputs : Vec < i64 > ,
74
- output : i64 ,
66
+ outputs : Vec < i64 > ,
75
67
}
76
68
77
69
pub fn generate ( ) {
@@ -103,7 +95,7 @@ mod musl_reference_tests {
103
95
// After we have all our inputs, use the x86_64-unknown-linux-musl
104
96
// target to generate the expected output.
105
97
generate_test_outputs ( & mut math) ;
106
-
98
+ //panic!("Boo");
107
99
// ... and now that we have both inputs and expected outputs, do a bunch
108
100
// of codegen to create the unit tests which we'll actually execute.
109
101
generate_unit_tests ( & math) ;
@@ -125,7 +117,7 @@ mod musl_reference_tests {
125
117
. collect :: < Vec < _ > > ( ) ;
126
118
let tail = & s[ end + 1 ..] ;
127
119
let tail = eat ( tail, " -> " ) ;
128
- let ret = parse_ty ( tail. trim ( ) . split ( ' ' ) . next ( ) . unwrap ( ) ) ;
120
+ let ret = parse_retty ( tail. replace ( "{" , "" ) . trim ( ) ) ;
129
121
130
122
return Function {
131
123
name : name. to_string ( ) ,
@@ -144,6 +136,16 @@ mod musl_reference_tests {
144
136
}
145
137
}
146
138
139
+ fn parse_retty ( s : & str ) -> Vec < Ty > {
140
+ match s {
141
+ "(f32, f32)" => vec ! [ Ty :: F32 , Ty :: F32 ] ,
142
+ "(f32, i32)" => vec ! [ Ty :: F32 , Ty :: I32 ] ,
143
+ "(f64, f64)" => vec ! [ Ty :: F64 , Ty :: F64 ] ,
144
+ "(f64, i32)" => vec ! [ Ty :: F64 , Ty :: I32 ] ,
145
+ other => vec ! [ parse_ty( other) ] ,
146
+ }
147
+ }
148
+
147
149
fn eat < ' a > ( s : & ' a str , prefix : & str ) -> & ' a str {
148
150
if s. starts_with ( prefix) {
149
151
& s[ prefix. len ( ) ..]
@@ -163,7 +165,10 @@ mod musl_reference_tests {
163
165
fn generate_test < R : Rng > ( args : & [ Ty ] , rng : & mut R ) -> Test {
164
166
let inputs = args. iter ( ) . map ( |ty| ty. gen_i64 ( rng) ) . collect ( ) ;
165
167
// zero output for now since we'll generate it later
166
- Test { inputs, output : 0 }
168
+ Test {
169
+ inputs,
170
+ outputs : vec ! [ ] ,
171
+ }
167
172
}
168
173
}
169
174
@@ -192,6 +197,33 @@ mod musl_reference_tests {
192
197
Ty :: Bool => "i32" ,
193
198
}
194
199
}
200
+
201
+ fn libc_pty ( & self ) -> & ' static str {
202
+ match self {
203
+ Ty :: F32 => "*mut f32" ,
204
+ Ty :: F64 => "*mut f64" ,
205
+ Ty :: I32 => "*mut i32" ,
206
+ Ty :: Bool => "*mut i32" ,
207
+ }
208
+ }
209
+
210
+ fn default ( & self ) -> & ' static str {
211
+ match self {
212
+ Ty :: F32 => "0_f32" ,
213
+ Ty :: F64 => "0_f64" ,
214
+ Ty :: I32 => "0_i32" ,
215
+ Ty :: Bool => "false" ,
216
+ }
217
+ }
218
+
219
+ fn to_i64 ( & self ) -> & ' static str {
220
+ match self {
221
+ Ty :: F32 => ".to_bits() as i64" ,
222
+ Ty :: F64 => ".to_bits() as i64" ,
223
+ Ty :: I32 => " as i64" ,
224
+ Ty :: Bool => " as i64" ,
225
+ }
226
+ }
195
227
}
196
228
197
229
fn generate_test_outputs ( functions : & mut [ Function ] ) {
@@ -212,8 +244,11 @@ mod musl_reference_tests {
212
244
for ( i, arg) in function. args . iter ( ) . enumerate ( ) {
213
245
src. push_str ( & format ! ( "arg{}: {}," , i, arg. libc_ty( ) ) ) ;
214
246
}
247
+ for ( i, ret) in function. ret . iter ( ) . skip ( 1 ) . enumerate ( ) {
248
+ src. push_str ( & format ! ( "argret{}: {}," , i, ret. libc_pty( ) ) ) ;
249
+ }
215
250
src. push_str ( ") -> " ) ;
216
- src. push_str ( function. ret . libc_ty ( ) ) ;
251
+ src. push_str ( function. ret [ 0 ] . libc_ty ( ) ) ;
217
252
src. push_str ( "; }" ) ;
218
253
219
254
src. push_str ( & format ! ( "static TESTS: &[[i64; {}]]" , function. args. len( ) ) ) ;
@@ -229,6 +264,14 @@ mod musl_reference_tests {
229
264
src. push_str ( "];" ) ;
230
265
231
266
src. push_str ( "for test in TESTS {" ) ;
267
+ for ( i, arg) in function. ret . iter ( ) . skip ( 1 ) . enumerate ( ) {
268
+ src. push_str ( & format ! ( "let mut argret{} = {};" , i, arg. default ( ) ) ) ;
269
+ src. push_str ( & format ! (
270
+ "let argret_ptr{0} = &mut argret{0} as *mut {1};" ,
271
+ i,
272
+ arg. libc_ty( )
273
+ ) ) ;
274
+ }
232
275
src. push_str ( "let output = " ) ;
233
276
src. push_str ( & function. name ) ;
234
277
src. push_str ( "(" ) ;
@@ -241,17 +284,20 @@ mod musl_reference_tests {
241
284
} ) ;
242
285
src. push_str ( "," ) ;
243
286
}
287
+ for ( i, _) in function. ret . iter ( ) . skip ( 1 ) . enumerate ( ) {
288
+ src. push_str ( & format ! ( "argret_ptr{}," , i) ) ;
289
+ }
244
290
src. push_str ( ");" ) ;
245
- src. push_str ( "let output = " ) ;
246
- src. push_str ( match function. ret {
247
- Ty :: F32 => "output.to_bits() as i64" ,
248
- Ty :: F64 => "output.to_bits() as i64" ,
249
- Ty :: I32 => "output as i64" ,
250
- Ty :: Bool => "output as i64" ,
251
- } ) ;
252
- src. push_str ( ";" ) ;
291
+ src. push_str ( & format ! ( "let output = output{};" , function. ret[ 0 ] . to_i64( ) ) ) ;
253
292
src. push_str ( "result.extend_from_slice(&output.to_le_bytes());" ) ;
254
293
294
+ for ( i, ret) in function. ret . iter ( ) . skip ( 1 ) . enumerate ( ) {
295
+ src. push_str ( & format ! ( "let output{0} = argret{0}{1};" , i, ret. to_i64( ) ) ) ;
296
+ src. push_str ( & format ! (
297
+ "result.extend_from_slice(&output{}.to_le_bytes());" ,
298
+ i
299
+ ) ) ;
300
+ }
255
301
src. push_str ( "}" ) ;
256
302
257
303
src. push_str ( "}" ) ;
@@ -288,8 +334,13 @@ mod musl_reference_tests {
288
334
i64:: from_le_bytes ( exact)
289
335
} ) ;
290
336
291
- for test in functions. iter_mut ( ) . flat_map ( |f| f. tests . iter_mut ( ) ) {
292
- test. output = results. next ( ) . unwrap ( ) ;
337
+ for f in functions. iter_mut ( ) {
338
+ for test in f. tests . iter_mut ( ) {
339
+ test. outputs = vec ! [ results. next( ) . unwrap( ) ] ;
340
+ for _ in f. ret . iter ( ) . skip ( 1 ) {
341
+ test. outputs . push ( results. next ( ) . unwrap ( ) ) ;
342
+ }
343
+ }
293
344
}
294
345
assert ! ( results. next( ) . is_none( ) ) ;
295
346
}
@@ -306,8 +357,9 @@ mod musl_reference_tests {
306
357
src. push_str ( & function. name ) ;
307
358
src. push_str ( "_matches_musl() {" ) ;
308
359
src. push_str ( & format ! (
309
- "static TESTS: &[([i64; {}], i64)]" ,
310
- function. args. len( )
360
+ "static TESTS: &[([i64; {}], [i64; {}])]" ,
361
+ function. args. len( ) ,
362
+ function. ret. len( ) ,
311
363
) ) ;
312
364
src. push_str ( " = &[" ) ;
313
365
for test in function. tests . iter ( ) {
@@ -317,7 +369,12 @@ mod musl_reference_tests {
317
369
src. push_str ( "," ) ;
318
370
}
319
371
src. push_str ( "]," ) ;
320
- src. push_str ( & test. output . to_string ( ) ) ;
372
+ src. push_str ( "[" ) ;
373
+ for val in test. outputs . iter ( ) {
374
+ src. push_str ( & val. to_string ( ) ) ;
375
+ src. push_str ( "," ) ;
376
+ }
377
+ src. push_str ( "]," ) ;
321
378
src. push_str ( ")," ) ;
322
379
}
323
380
src. push_str ( "];" ) ;
@@ -336,12 +393,27 @@ mod musl_reference_tests {
336
393
src. push_str ( "," ) ;
337
394
}
338
395
src. push_str ( ");" ) ;
339
- src. push_str ( match function. ret {
340
- Ty :: F32 => "if _eqf(output, f32::from_bits(*expected as u32)).is_ok() { continue }" ,
341
- Ty :: F64 => "if _eq(output, f64::from_bits(*expected as u64)).is_ok() { continue }" ,
342
- Ty :: I32 => "if output as i64 == *expected { continue }" ,
343
- Ty :: Bool => unreachable ! ( ) ,
344
- } ) ;
396
+ if function. ret . len ( ) > 1 {
397
+ for ( i, ret) in function. ret . iter ( ) . enumerate ( ) {
398
+ src. push_str ( & ( match ret {
399
+ Ty :: F32 => format ! ( "if _eqf(output.{0}, f32::from_bits(expected[{0}] as u32)).is_ok() {{ continue }}" , i) ,
400
+ Ty :: F64 => format ! ( "if _eq(output.{0}, f64::from_bits(expected[{0}] as u64)).is_ok() {{ continue }}" , i) ,
401
+ Ty :: I32 => format ! ( "if output.{0} as i64 == expected[{0}] {{ continue }}" , i) ,
402
+ Ty :: Bool => unreachable ! ( ) ,
403
+ } ) ) ;
404
+ }
405
+ } else {
406
+ src. push_str ( match function. ret [ 0 ] {
407
+ Ty :: F32 => {
408
+ "if _eqf(output, f32::from_bits(expected[0] as u32)).is_ok() { continue }"
409
+ }
410
+ Ty :: F64 => {
411
+ "if _eq(output, f64::from_bits(expected[0] as u64)).is_ok() { continue }"
412
+ }
413
+ Ty :: I32 => "if output as i64 == expected[0] { continue }" ,
414
+ Ty :: Bool => unreachable ! ( ) ,
415
+ } ) ;
416
+ }
345
417
346
418
src. push_str (
347
419
r#"
0 commit comments