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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
//! Instruction encoders, the integrated assembler, inline assembly and relaxation.
//!
//! Design: `spec/11-asm-objects-debug.md`. Layer rank 11, see `spec/18-package-layout.md`.
//!
//! # Status
//!
//! What is written are the two things a compiler does with a machine function: the assembly text
//! `-S` produces, which is [`print()`], and the bytes of a text section, which is [`assemble`].
//! Section 11.1 asks for one instruction description behind both, and there is one: the walk over
//! a function is the same walk in both files, reading the same list out of `rucc-target`, and the
//! only difference is whether an instruction is written down by name or handed to the encoder. So
//! the listing and the object file cannot come to disagree about what an instruction is.
//!
//! What [`assemble`] hands back with the bytes is what the linker has to be told: where each
//! function starts and how long it is, and every place in the bytes that names something this
//! file does not contain. The jumps inside a function are not among them, because by the end of a
//! function every block has a place and they are filled in here.
//!
//! A build that asked for debug information gets one more thing: where each machine instruction
//! began and which span of the source it came from. Spans rather than files and lines, because this
//! layer has no source map and the thing that has one is the driver, which is also the only place a
//! `-ffile-prefix-map` still has paths to rewrite.
//!
//! The variables a file defines are here for the same reason and in the same shape. [`globals`] is
//! the one walk over a module's globals, and what it gives back is a list of pieces that
//! [`print()`] writes down as directives and [`Globals::image`] writes down as bytes, so a `.long`
//! in a listing and the four bytes in the object beside it cannot come to disagree either. Where a
//! variable goes is worked out there rather than named by the front end, and what a section is
//! called is the object format's business.
//!
//! [`read`] is the other direction: a file of assembly that somebody else wrote, turned into the
//! sections and names an object is written from. The directives and the labels are one half of it
//! and the instructions are the other, and a mnemonic with no bytes behind it is refused by name
//! with its line number rather than skipped. Nothing there describes the machine a second time:
//! the bytes of an instruction come from the one encoder in `rucc-target` that the compiler's own
//! output goes through, so a file this assembles and a file this compiles cannot disagree about
//! what an instruction is. Branch relaxation is not here yet, so a jump is four bytes of distance
//! whether it needs them or not, which is correct and longer than gas would have written.
//!
//! Every crate in the workspace is published, and publishing implies a promise. This one is
//! tier 3: its Rust API is explicitly unstable and will change without a major version bump.
//! Depend on the `rucc` binary's behaviour, not on this.
pub use crateprint;
pub use crate;
pub use crate;
pub use crateDirectives;
pub use crate;
use fmt;
use Interner;
use Func;
use ;
/// Whether any of these functions holds a template kept as text that the assembler cannot read on
/// its own, which is what decides that the unit is assembled from its listing rather than written
/// out as bytes directly. See [`x86_64::Form::Template`].
///
/// One that jumps to a label another template defines, switches section or aligns what follows is
/// only right in the listing, where every template is read as part of one file. Every other one is
/// read by itself where it is and laid down as bytes, which keeps the line table and the rest of
/// what `-g` writes, since those come out of [`assemble`] and not out of a listing.
/// The line a hot loop is kept inside, which is the cache line and the fetch block on the x86-64
/// machines this was measured on.
///
/// Where a small loop starts matters on those machines only as far as whether it crosses one of
/// these. The same thirty eight bytes of loop ran in 527M to 553M cycles wherever it fitted inside
/// one line and in 578M to 753M wherever it crossed, while gcc's rule of sixteen bytes when that is
/// near and eight otherwise kept it inside a line only half the time. That is `tamnd/rucc#1838`.
const LINE: usize = 64;
/// The most padding one loop is given, whatever it would take to keep it inside a line.
///
/// Half a line. With no limit the padding cost SQLite 1.01% of its text, with this one 0.48%, and
/// with a quarter of a line 0.16%, which is too little to reach the loop the rule was written for:
/// its head was twenty bytes short of the next line.
const MOST_PADDING: usize = 31;
/// The most padding worth putting in front of a loop that is `size` bytes from its head to the end
/// of the jump back to it, or nothing when no padding would keep it inside a line.
///
/// A loop longer than a line crosses one wherever it starts. A loop of one line or less crosses one
/// exactly when the padding to the next line is less than its size, so asking for the next line
/// with that much padding at most pads the loops that cross and leaves the ones that do not alone.
/// That is gas's `.p2align 6,,N`, which is what the listing writes, and [`loop_padding`] is the
/// same arithmetic for the object writer. The two are beside each other so that they are changed
/// together.
/// How many bytes of padding go in front of the head of a loop of that size that would otherwise
/// start `at` bytes into the section. See [`loop_room`].
/// The milestone in `spec/17-milestones.md` that fills this crate in.
pub const MILESTONE: &str = "M3";
/// A function this compiler could not write out as assembly.
///
/// Neither of these is a program's fault and neither should ever reach a user, since a machine
/// function that reaches here has been through the whole backend and the tests pin both of the
/// claims below. They are errors rather than assertions because the alternative to reporting one
/// is writing a listing that is quietly wrong, and a wrong listing is the failure section 11.1 is
/// written to prevent.