@@ -12,11 +12,8 @@ use cranelift_srcgen::{Formatter, fmtln};
12
12
pub fn rust_assembler ( f : & mut Formatter , insts : & [ dsl:: Inst ] ) {
13
13
// Generate "all instructions" enum.
14
14
generate_inst_enum ( f, insts) ;
15
+ generate_inst_impls ( f, insts) ;
15
16
generate_inst_display_impl ( f, insts) ;
16
- generate_inst_encode_impl ( f, insts) ;
17
- generate_inst_visit_impl ( f, insts) ;
18
- generate_inst_is_available_impl ( f, insts) ;
19
- generate_inst_features_impl ( f, insts) ;
20
17
21
18
// Generate per-instruction structs.
22
19
f. empty_line ( ) ;
@@ -46,22 +43,14 @@ fn generate_inst_enum(f: &mut Formatter, insts: &[dsl::Inst]) {
46
43
} ) ;
47
44
}
48
45
49
- /// `#[derive(...)]`
50
- fn generate_derive ( f : & mut Formatter ) {
51
- fmtln ! ( f, "#[derive(Copy, Clone, Debug)]" ) ;
52
- fmtln ! (
53
- f,
54
- "#[cfg_attr(any(test, feature = \" fuzz\" ), derive(arbitrary::Arbitrary))]"
55
- ) ;
56
- }
57
-
58
- /// Adds a custom bound to the `Arbitrary` implementation which ensures that
59
- /// the associated registers are all `Arbitrary` as well.
60
- fn generate_derive_arbitrary_bounds ( f : & mut Formatter ) {
61
- fmtln ! (
62
- f,
63
- "#[cfg_attr(any(test, feature = \" fuzz\" ), arbitrary(bound = \" R: crate::fuzz::RegistersArbitrary\" ))]"
64
- ) ;
46
+ /// Helper for emitting `match self { ... }` blocks over all instructions. For each instruction in
47
+ /// `insts`, this generate a separate match arm containing `invoke`.
48
+ fn match_variants ( f : & mut Formatter , insts : & [ dsl:: Inst ] , invoke : & str ) {
49
+ f. add_block ( "match self" , |f| {
50
+ for inst in insts. iter ( ) . map ( |i| i. name ( ) ) {
51
+ fmtln ! ( f, "Self::{inst}(i) => i.{invoke}," ) ;
52
+ }
53
+ } ) ;
65
54
}
66
55
67
56
/// `impl std::fmt::Display for Inst { ... }`
@@ -70,81 +59,52 @@ fn generate_inst_display_impl(f: &mut Formatter, insts: &[dsl::Inst]) {
70
59
f. add_block (
71
60
"fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result" ,
72
61
|f| {
73
- f. add_block ( "match self" , |f| {
74
- for inst in insts {
75
- let variant_name = inst. name ( ) ;
76
- fmtln ! ( f, "Self::{variant_name}(i) => i.fmt(f)," ) ;
77
- }
78
- } ) ;
62
+ match_variants ( f, insts, "fmt(f)" ) ;
79
63
} ,
80
64
) ;
81
65
} ) ;
82
66
}
83
67
84
- /// `impl Inst { fn encode... }`
85
- fn generate_inst_encode_impl ( f : & mut Formatter , insts : & [ dsl:: Inst ] ) {
68
+ fn generate_inst_impls ( f : & mut Formatter , insts : & [ dsl:: Inst ] ) {
86
69
f. add_block ( "impl<R: Registers> Inst<R>" , |f| {
87
70
f. add_block ( "pub fn encode(&self, b: &mut impl CodeSink)" , |f| {
88
- f. add_block ( "match self" , |f| {
89
- for inst in insts {
90
- let variant_name = inst. name ( ) ;
91
- fmtln ! ( f, "Self::{variant_name}(i) => i.encode(b)," ) ;
92
- }
93
- } ) ;
71
+ match_variants ( f, insts, "encode(b)" ) ;
94
72
} ) ;
95
- } ) ;
96
- }
97
-
98
- /// `impl Inst { fn visit... }`
99
- fn generate_inst_visit_impl ( f : & mut Formatter , insts : & [ dsl:: Inst ] ) {
100
- fmtln ! ( f, "impl<R: Registers> Inst<R> {{" ) ;
101
- f. indent ( |f| {
102
- fmtln ! (
103
- f,
104
- "pub fn visit(&mut self, v: &mut impl RegisterVisitor<R>) {{"
73
+ f. add_block (
74
+ "pub fn visit(&mut self, v: &mut impl RegisterVisitor<R>)" ,
75
+ |f| {
76
+ match_variants ( f, insts, "visit(v)" ) ;
77
+ } ,
105
78
) ;
106
- f. indent ( |f| {
107
- fmtln ! ( f, "match self {{" ) ;
108
- f. indent_push ( ) ;
109
- for inst in insts {
110
- let variant_name = inst. name ( ) ;
111
- fmtln ! ( f, "Self::{variant_name}(i) => i.visit(v)," ) ;
112
- }
113
- f. indent_pop ( ) ;
114
- fmtln ! ( f, "}}" ) ;
115
- } ) ;
116
- fmtln ! ( f, "}}" ) ;
117
- } ) ;
118
- fmtln ! ( f, "}}" ) ;
119
- }
120
-
121
- /// `impl Inst { fn is_available... }`
122
- fn generate_inst_is_available_impl ( f : & mut Formatter , insts : & [ dsl:: Inst ] ) {
123
- f. add_block ( "impl<R: Registers> Inst<R>" , |f| {
124
79
f. add_block (
125
80
"pub fn is_available(&self, f: &impl AvailableFeatures) -> bool" ,
126
81
|f| {
127
- f. add_block ( "match self" , |f| {
128
- for inst in insts {
129
- let variant_name = inst. name ( ) ;
130
- fmtln ! ( f, "Self::{variant_name}(i) => i.is_available(f)," ) ;
131
- }
132
- } ) ;
82
+ match_variants ( f, insts, "is_available(f)" ) ;
133
83
} ,
134
84
) ;
135
- } ) ;
136
- }
137
-
138
- /// `impl Inst { fn features... }`
139
- fn generate_inst_features_impl ( f : & mut Formatter , insts : & [ dsl:: Inst ] ) {
140
- f. add_block ( "impl<R: Registers> Inst<R>" , |f| {
141
85
f. add_block ( "pub fn features(&self) -> &'static Features" , |f| {
142
- f. add_block ( "match self" , |f| {
143
- for inst in insts {
144
- let variant_name = inst. name ( ) ;
145
- fmtln ! ( f, "Self::{variant_name}(i) => i.features()," ) ;
146
- }
147
- } ) ;
86
+ match_variants ( f, insts, "features()" ) ;
87
+ } ) ;
88
+ f. add_block ( "pub fn num_registers_available(&self) -> usize" , |f| {
89
+ match_variants ( f, insts, "num_registers_available()" ) ;
148
90
} ) ;
149
91
} ) ;
150
92
}
93
+
94
+ /// `#[derive(...)]`
95
+ fn generate_derive ( f : & mut Formatter ) {
96
+ fmtln ! ( f, "#[derive(Copy, Clone, Debug)]" ) ;
97
+ fmtln ! (
98
+ f,
99
+ "#[cfg_attr(any(test, feature = \" fuzz\" ), derive(arbitrary::Arbitrary))]"
100
+ ) ;
101
+ }
102
+
103
+ /// Adds a custom bound to the `Arbitrary` implementation which ensures that
104
+ /// the associated registers are all `Arbitrary` as well.
105
+ fn generate_derive_arbitrary_bounds ( f : & mut Formatter ) {
106
+ fmtln ! (
107
+ f,
108
+ "#[cfg_attr(any(test, feature = \" fuzz\" ), arbitrary(bound = \" R: crate::fuzz::RegistersArbitrary\" ))]"
109
+ ) ;
110
+ }
0 commit comments