1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
//! The IR model against the names the IR actually gives its instructions.
//!
//! `rules/ir.model` says what the terms of the IR mean, and `term::heads` says what the IR calls
//! its instructions. Those are two lists of the same names written by hand in two places, and a
//! name spelled one way here and another way there is a rule that never fires, which is the
//! quietest kind of mistake a rule set has. So they are checked against each other.
//!
//! The solver never notices any of this. A model entry for a head no instruction has is an entry
//! nothing asks about, and a head with no entry only shows up on the day somebody writes a rule
//! about it, which may be a year after the typo.
use BTreeSet;
use heads;
/// The model, read at compile time out of the crate it belongs to.
const MODEL: &str = include_str!;
/// Every head the model gives a meaning to.
///
/// Scanned rather than parsed, because the parser is in a build tool this crate cannot see and
/// what is wanted is the name in head position of each entry. An entry always starts a line and
/// always opens with its head, which the model's own layout guarantees and which the model is
/// checked against below.
/// Every name the IR gives an instruction.
/// The layout the scan above relies on: an entry starts a line and nothing else in the file
/// opens with `(semantics`. Checked from the other side, by counting, so that a continuation
/// line indented to look like an entry would be caught.
/// A head with no meaning is a rule nobody can write, so the two lists are compared both ways
/// and the difference is named rather than counted.
///
/// The heads the IR has and the model does not are memory, and they are the list below rather
/// than an allowance for anything missing. What a load of four bytes means depends on which end
/// of the value sits at the lowest address, which is a fact about the target, so those entries
/// live in the target's model and the two that exist there today are written out.
///
/// A half is loaded and never stored, which is why `load.f16` is below and `store.f16` is not.
/// The lowering pass rewrites every store of a half into a store of the sixteen bits, because the
/// instruction that gets those bits out of a vector register and straight into memory is above
/// the baseline this target compiles for.
/// And nothing here is a meaning for a head no instruction has.
///
/// There are exceptions and the list below is all of them. `value.iN` is how a rule writes an
/// operand that is already computed and sitting in a register, so no opcode is ever called that.
/// `power_of_two.iN` and `ctz.iN` are arithmetic on the constants a rule matched, which is what a
/// guard asks about and what a computed replacement works out, and the machine executes neither.
/// Everything else in the file is an instruction or a typo.
/// The heads that are not instructions: an operand the rule already has, and the arithmetic the
/// rule does on the constants it matched.
/// That arithmetic has a meaning at every width a rule may ask it at.
///
/// A head with no entry is a rule the verifier refuses to read, and the refusal names the head
/// rather than the width, so the four are written out here instead of being found one at a time
/// by whoever writes the first rule at a width nobody covered.
/// One bit is the width the rewrite rules of `rucc-opt` are about as much as any other, so its
/// meanings are here rather than in a target's model. They were in one, back when a target's
/// model was the only model there was.