@@ -27,38 +27,30 @@ mod musl_reference_tests {
2727 // These files are all internal functions or otherwise miscellaneous, not
2828 // defining a function we want to test.
2929 const IGNORED_FILES : & [ & str ] = & [
30- "expo2.rs" ,
30+ "expo2.rs" , // kernel, private
3131 "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
4040 "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
5648 ] ;
5749
5850 struct Function {
5951 name : String ,
6052 args : Vec < Ty > ,
61- ret : Ty ,
53+ ret : Vec < Ty > ,
6254 tests : Vec < Test > ,
6355 }
6456
@@ -71,7 +63,7 @@ mod musl_reference_tests {
7163
7264 struct Test {
7365 inputs : Vec < i64 > ,
74- output : i64 ,
66+ outputs : Vec < i64 > ,
7567 }
7668
7769 pub fn generate ( ) {
@@ -103,7 +95,7 @@ mod musl_reference_tests {
10395 // After we have all our inputs, use the x86_64-unknown-linux-musl
10496 // target to generate the expected output.
10597 generate_test_outputs ( & mut math) ;
106-
98+ //panic!("Boo");
10799 // ... and now that we have both inputs and expected outputs, do a bunch
108100 // of codegen to create the unit tests which we'll actually execute.
109101 generate_unit_tests ( & math) ;
@@ -125,7 +117,7 @@ mod musl_reference_tests {
125117 . collect :: < Vec < _ > > ( ) ;
126118 let tail = & s[ end + 1 ..] ;
127119 let tail = eat ( tail, " -> " ) ;
128- let ret = parse_ty ( tail. trim ( ) . split ( ' ' ) . next ( ) . unwrap ( ) ) ;
120+ let ret = parse_retty ( tail. replace ( "{" , "" ) . trim ( ) ) ;
129121
130122 return Function {
131123 name : name. to_string ( ) ,
@@ -144,6 +136,16 @@ mod musl_reference_tests {
144136 }
145137 }
146138
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+
147149 fn eat < ' a > ( s : & ' a str , prefix : & str ) -> & ' a str {
148150 if s. starts_with ( prefix) {
149151 & s[ prefix. len ( ) ..]
@@ -163,7 +165,10 @@ mod musl_reference_tests {
163165 fn generate_test < R : Rng > ( args : & [ Ty ] , rng : & mut R ) -> Test {
164166 let inputs = args. iter ( ) . map ( |ty| ty. gen_i64 ( rng) ) . collect ( ) ;
165167 // zero output for now since we'll generate it later
166- Test { inputs, output : 0 }
168+ Test {
169+ inputs,
170+ outputs : vec ! [ ] ,
171+ }
167172 }
168173 }
169174
@@ -192,6 +197,33 @@ mod musl_reference_tests {
192197 Ty :: Bool => "i32" ,
193198 }
194199 }
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+ }
195227 }
196228
197229 fn generate_test_outputs ( functions : & mut [ Function ] ) {
@@ -212,8 +244,11 @@ mod musl_reference_tests {
212244 for ( i, arg) in function. args . iter ( ) . enumerate ( ) {
213245 src. push_str ( & format ! ( "arg{}: {}," , i, arg. libc_ty( ) ) ) ;
214246 }
247+ for ( i, ret) in function. ret . iter ( ) . skip ( 1 ) . enumerate ( ) {
248+ src. push_str ( & format ! ( "argret{}: {}," , i, ret. libc_pty( ) ) ) ;
249+ }
215250 src. push_str ( ") -> " ) ;
216- src. push_str ( function. ret . libc_ty ( ) ) ;
251+ src. push_str ( function. ret [ 0 ] . libc_ty ( ) ) ;
217252 src. push_str ( "; }" ) ;
218253
219254 src. push_str ( & format ! ( "static TESTS: &[[i64; {}]]" , function. args. len( ) ) ) ;
@@ -229,6 +264,14 @@ mod musl_reference_tests {
229264 src. push_str ( "];" ) ;
230265
231266 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+ }
232275 src. push_str ( "let output = " ) ;
233276 src. push_str ( & function. name ) ;
234277 src. push_str ( "(" ) ;
@@ -241,17 +284,20 @@ mod musl_reference_tests {
241284 } ) ;
242285 src. push_str ( "," ) ;
243286 }
287+ for ( i, _) in function. ret . iter ( ) . skip ( 1 ) . enumerate ( ) {
288+ src. push_str ( & format ! ( "argret_ptr{}," , i) ) ;
289+ }
244290 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( ) ) ) ;
253292 src. push_str ( "result.extend_from_slice(&output.to_le_bytes());" ) ;
254293
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+ }
255301 src. push_str ( "}" ) ;
256302
257303 src. push_str ( "}" ) ;
@@ -288,8 +334,13 @@ mod musl_reference_tests {
288334 i64:: from_le_bytes ( exact)
289335 } ) ;
290336
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+ }
293344 }
294345 assert ! ( results. next( ) . is_none( ) ) ;
295346 }
@@ -306,8 +357,9 @@ mod musl_reference_tests {
306357 src. push_str ( & function. name ) ;
307358 src. push_str ( "_matches_musl() {" ) ;
308359 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( ) ,
311363 ) ) ;
312364 src. push_str ( " = &[" ) ;
313365 for test in function. tests . iter ( ) {
@@ -317,7 +369,12 @@ mod musl_reference_tests {
317369 src. push_str ( "," ) ;
318370 }
319371 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 ( "]," ) ;
321378 src. push_str ( ")," ) ;
322379 }
323380 src. push_str ( "];" ) ;
@@ -336,12 +393,27 @@ mod musl_reference_tests {
336393 src. push_str ( "," ) ;
337394 }
338395 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+ }
345417
346418 src. push_str (
347419 r#"
0 commit comments