Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/cranelift/assembler-x64/meta/src/generate.rs
1692 views
1
//! Contains the code-generation logic to emit for the DSL-defined instructions.
2
3
mod features;
4
mod format;
5
mod inst;
6
mod operand;
7
8
use crate::dsl;
9
use cranelift_srcgen::{Formatter, fmtln};
10
11
/// Generate the Rust assembler code; e.g., `enum Inst { ... }`.
12
pub fn rust_assembler(f: &mut Formatter, insts: &[dsl::Inst]) {
13
// Generate "all instructions" enum.
14
generate_inst_enum(f, insts);
15
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
21
// Generate per-instruction structs.
22
f.empty_line();
23
for inst in insts {
24
inst.generate_struct(f);
25
inst.generate_struct_impl(f);
26
inst.generate_display_impl(f);
27
inst.generate_from_impl(f);
28
f.empty_line();
29
}
30
31
// Generate the `Feature` trait.
32
dsl::Feature::generate_macro(f);
33
}
34
35
/// `enum Inst { ... }`
36
fn generate_inst_enum(f: &mut Formatter, insts: &[dsl::Inst]) {
37
fmtln!(f, "#[doc(hidden)]");
38
generate_derive(f);
39
generate_derive_arbitrary_bounds(f);
40
f.add_block("pub enum Inst<R: Registers>", |f| {
41
for inst in insts {
42
let variant_name = inst.name();
43
let struct_name = inst.struct_name_with_generic();
44
fmtln!(f, "{variant_name}({struct_name}),");
45
}
46
});
47
}
48
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
);
65
}
66
67
/// `impl std::fmt::Display for Inst { ... }`
68
fn generate_inst_display_impl(f: &mut Formatter, insts: &[dsl::Inst]) {
69
f.add_block("impl<R: Registers> std::fmt::Display for Inst<R>", |f| {
70
f.add_block(
71
"fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result",
72
|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
});
79
},
80
);
81
});
82
}
83
84
/// `impl Inst { fn encode... }`
85
fn generate_inst_encode_impl(f: &mut Formatter, insts: &[dsl::Inst]) {
86
f.add_block("impl<R: Registers> Inst<R>", |f| {
87
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
});
94
});
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>) {{"
105
);
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
f.add_block(
125
"pub fn is_available(&self, f: &impl AvailableFeatures) -> bool",
126
|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
});
133
},
134
);
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
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
});
148
});
149
});
150
}
151
152