@@ -54,6 +54,10 @@ trait FloatRepr: Copy + Default + Eq + fmt::Display {
54
54
55
55
const NAME : & ' static str ;
56
56
57
+ // HACK(eddyb) this has to be overwritable because we have more than one
58
+ // format with the same `BIT_WIDTH`, so it's not unambiguous on its own.
59
+ const REPR_TAG : u8 = Self :: BIT_WIDTH as u8 ;
60
+
57
61
// FIXME(eddyb) these should ideally be using `[u8; Self::BYTE_LEN]`.
58
62
fn from_le_bytes ( bytes : & [ u8 ] ) -> Self ;
59
63
fn write_as_le_bytes_into ( self , out_bytes : & mut Vec < u8 > ) ;
@@ -70,17 +74,24 @@ trait FloatRepr: Copy + Default + Eq + fmt::Display {
70
74
macro_rules! float_reprs {
71
75
( $( $name: ident( $repr: ty) {
72
76
type RustcApFloat = $rs_apf_ty: ty;
77
+ $( const REPR_TAG = $repr_tag: expr; ) ?
73
78
extern fn = $cxx_apf_eval_fuzz_op: ident;
74
79
$( type HardFloat = $hard_float_ty: ty; ) ?
75
80
} ) +) => {
76
81
// HACK(eddyb) helper macro used to actually handle all types uniformly.
77
- macro_rules! dispatch_all_reprs {
78
- ( $ty_var: ident => $e: expr) => { {
79
- $( {
80
- type $ty_var = $name;
81
- $e
82
- } ) +
83
- } }
82
+ macro_rules! dispatch_any_float_repr_by_repr_tag {
83
+ ( match $repr_tag_value: ident { for <$ty_var: ident: FloatRepr > => $e: expr } ) => {
84
+ // NOTE(eddyb) this doubles as an overlap check: `REPR_TAG`
85
+ // values across *all* `FloatRepr` `impl` *must* be unique.
86
+ #[ deny( unreachable_patterns) ]
87
+ match $repr_tag_value {
88
+ $( $name:: REPR_TAG => {
89
+ type $ty_var = $name;
90
+ $e;
91
+ } ) +
92
+ _ => { }
93
+ }
94
+ }
84
95
}
85
96
86
97
$(
@@ -96,6 +107,8 @@ macro_rules! float_reprs {
96
107
97
108
const NAME : & ' static str = stringify!( $name) ;
98
109
110
+ $( const REPR_TAG : u8 = $repr_tag; ) ?
111
+
99
112
fn from_le_bytes( bytes: & [ u8 ] ) -> Self {
100
113
// HACK(eddyb) this allows using e.g. `u128` to hold 80 bits.
101
114
let mut repr_bytes = [ 0 ; std:: mem:: size_of:: <$repr>( ) ] ;
@@ -180,6 +193,13 @@ float_reprs! {
180
193
type RustcApFloat = rustc_apfloat:: ieee:: Quad ;
181
194
extern fn = cxx_apf_fuzz_eval_op_ieee128;
182
195
}
196
+
197
+ // Non-standard IEEE-like formats.
198
+ BrainF16 ( u16 ) {
199
+ type RustcApFloat = rustc_apfloat:: ieee:: BFloat ;
200
+ const REPR_TAG = 16 + 1 ;
201
+ extern fn = cxx_apf_fuzz_eval_op_brainf16;
202
+ }
183
203
X87_F80 ( u128 ) {
184
204
type RustcApFloat = rustc_apfloat:: ieee:: X87DoubleExtended ;
185
205
extern fn = cxx_apf_fuzz_eval_op_x87_f80;
@@ -380,15 +400,16 @@ fn main() {
380
400
381
401
data. split_first ( )
382
402
. ok_or ( "empty file" )
383
- . and_then ( |( & bit_width, data) | {
384
- dispatch_all_reprs ! ( F => if bit_width as usize == F :: BIT_WIDTH {
385
- FuzzOp :: <F >:: try_decode( data)
386
- . ok( )
387
- . ok_or( std:: any:: type_name:: <FuzzOp <F >>( ) ) ?
388
- . print_op_and_eval_outputs( & cli_args) ;
389
- return Ok ( ( ) ) ;
403
+ . and_then ( |( & repr_tag, data) | {
404
+ dispatch_any_float_repr_by_repr_tag ! ( match repr_tag {
405
+ for <F : FloatRepr > => return Ok (
406
+ FuzzOp :: <F >:: try_decode( data)
407
+ . ok( )
408
+ . ok_or( std:: any:: type_name:: <FuzzOp <F >>( ) ) ?
409
+ . print_op_and_eval_outputs( & cli_args)
410
+ )
390
411
} ) ;
391
- Err ( "first byte not valid bit width " )
412
+ Err ( "first byte not valid `FloatRepr::REPR_TAG` " )
392
413
} )
393
414
. unwrap_or_else ( |e| println ! ( " invalid data ({e})" ) ) ;
394
415
}
@@ -399,10 +420,11 @@ fn main() {
399
420
400
421
#[ cfg_attr( not( fuzzing) , allow( unused) ) ]
401
422
let fuzz_one_op = |data : & [ u8 ] | {
402
- data. split_first ( ) . and_then ( |( & bit_width, data) | {
403
- dispatch_all_reprs ! ( F => if bit_width as usize == F :: BIT_WIDTH {
404
- FuzzOp :: <F >:: try_decode( data) . ok( ) ?. eval( & cli_args) . assert_all_match( ) ;
405
- return Some ( ( ) ) ;
423
+ data. split_first ( ) . and_then ( |( & repr_tag, data) | {
424
+ dispatch_any_float_repr_by_repr_tag ! ( match repr_tag {
425
+ for <F : FloatRepr > => return Some (
426
+ FuzzOp :: <F >:: try_decode( data) . ok( ) ?. eval( & cli_args) . assert_all_match( )
427
+ )
406
428
} ) ;
407
429
None
408
430
} ) ;
0 commit comments