• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# MacroAssembler and Assembler Code Generation Behaviours
2
3This design document describes the way that the Assembler and MacroAssembler
4generate code. This has wide implications, including buffer management,
5instruction-precise generation and related control over code generation.
6
7**NOTE**: This document describes design decisions, but the code does not
8implement or match everything that is described in this document.
9TODO: Work on the code to achieve what is expressed in this document, and update
10the documentation.
11
12## Basic Use-Cases
13
14### Simple Code Generation
15
16For normal code generation, the MacroAssembler should be used. We recommend this
17even if the caller doesn't require the macro behaviour, because it acts as a
18(partial) fail-safe in case calling code accidentally passes out-of-range
19immediates and suchlike. The MacroAssembler is also able to check and emit
20literal pools.
21
22Note that the MacroAssembler is allowed to emit an arbitrary amount of code in
23order to achieve the requested effect. (Note that "arbitrary" includes no code,
24for macros with no effect other than to advance the PC.) In practical terms, a
25macro can effectively generate a huge amount of code if it needs to emit a
26literal pool (for example).
27
28### Precise Code Generation
29
30Sometimes, the caller needs to generate a very precise code sequence. The
31typical use-case is where code needs to be patched. In these cases, the
32MacroAssembler must not be used, but the Assembler can be called directly. Since
33the caller most likely has a MacroAssembler object, we provide
34ExactAssemblyScope to restrict any MacroAssembler methods from being used for
35its duration, and allow access to the Assembler.
36
37### Fuzzy Cases: Approximate Size Limits
38
39Sometimes the caller wants the convenience and fail-safe features of the
40MacroAssembler, and isn't worried about the precise code sequence used, but
41needs to ensure that the total code size does not exceed the range of a branch
42(or similar PC-relative instruction). Veneers simplify many cases like this, but
43not all (and not necessarily optimally). For example, VIXL32's Switch-Case
44macros probably do not have sufficient range to cope with a literal pool in
45the middle.
46
47For these cases, we'd like to ensure that the MacroAssembler doesn't emit _too
48much_ code. This is very fuzzy, and in practice means avoiding pools, but
49allowing standard macros. The catch is that the caller must specify the upper
50limit on the size of the generated code.
51
52A corner-case that is relevant for VIXL32 (but mostly irrelevant for VIXL64) is
53that the protected region could easily be larger than the range of some
54load-literal instructions, so we should not actually _block_ the pool. For
55example, `vldr` has a range of about 1KB, but `tbh` can easily exceed this
56range. If one of the Cases generates an FP literal-load, the MacroAssembler
57needs to put the pool in the middle of the Switch-Case sequence.
58
59This case is currently accomodated by MacroAssembler::EnsureEmitFor.
60
61## Proposal
62
63These behaviours are similar to (or the same as) existing cases to avoid
64breaking backwards compatibility. Several potentially-unsafe scopes have been
65deprecated, and a few have been given more flexibility.
66
67Each scope utility will behave in the same way for VIXL64 as for VIXL32, even if
68the implementations differ.
69
70### `CodeBufferCheckScope(Assembler* assm, size_t size, ...)`
71
72- Allow code emission from the specified `Assembler`.
73- Optionally reserve space in the `CodeBuffer` (if it is managed by VIXL).
74- Optionally, on destruction, check the size of the generated code.
75  (The size can be either exact or a maximum size.)
76
77This scope exists so that callers can use an Assembler by itself, without even
78instantiating a MacroAssembler.
79
80### `CodeBufferCheckScope(MacroAssembler* masm, ...)`
81
82- DEPRECATED
83
84Otherwise, this is the same as `CodeBufferCheckScope(Assembler*)`.
85
86It is unfortunate that this scope allows the Assembler and MacroAssembler to be
87mixed freely; this can cause numerous problems. For example, the Assembler
88doesn't know about the pools, so use of the Assembler can push the pools out of
89range. This was acceptable in VIXL64, where the pool range is very large, but
90not in VIXL32.
91
92We should retain the existing functionality for a while, but mark the
93`MacroAssembler*` form as DEPRECATED. A suitable replacement is
94EmissionCheckScope, which allows the Assembler and MacroAssembler to be mixed,
95but also blocks pools and therefore avoids the problems that
96`CodeBufferCheckScope` has.
97
98### `EmissionCheckScope(MacroAssembler* masm, size_t size, AssertPolicy ...)`
99
100- Do the same as `CodeBufferCheckSCope`, but:
101  - If managed by VIXL, always reserve space in the `CodeBuffer`.
102  - Always check the (exact or maximum) size of the generated code on
103    destruction.
104- Emit pools if the specified size would push them out of range.
105- Block pools emission for the duration of the scope.
106
107This scope allows the `Assembler` and `MacroAssembler` to be freely and safely
108mixed for its duration.
109
110The MacroAssembler uses this to implement its own macros.
111
112### `ExactAssemblyScope(MacroAssembler* masm, ...)`
113
114- Do the same as `EmissionCheckScope`.
115- Block access to the MacroAssemblerInterface (using run-time assertions).
116
117This scope allows safely generating exact assembly code. Compared to
118`CodeBufferCheckScope`, it disables the `MacroAssembler`, and guarantees that
119no pools will be emitted during code generation.
120
121This replaces VIXL64's InstructionAccurateScope.
122
123### `BlockPoolsScope` (and variants)
124
125- DEPRECATED
126- Block the pools for the duration.
127
128These scopes really shouldn't be used outside VIXL itself. Since uses inside
129VIXL are minimal, we should mark it as DEPRECATED and replace our own uses with
130EmissionCheckScope or manual `MacroAssembler::BlockPools()` calls.
131
132Note that this scope made sense in VIXL64, where pool ranges are large and we
133have a large contingency region built into the pool checks. In VIXL32, where the
134ranges are tight, we can't generally afford to block the constant pools at
135arbitrary points, even for short sequences of instructions.
136
137### `InstructionAccurateScope`
138
139- DEPRECATED
140- Replaced by ExactAssemblyScope.
141
142When generating T32, we need something like InstructionAccurateScope to check
143the code _size_, rather than the instruction count, since the instruction size
144is much more likely to vary in a way that matters. However, it's not safe to
145just change `InstructionAccurateScope`'s behaviour because the constructor
146prototype would be unchanged, so there would be no compile-time warning for
147users.
148
149### `MacroAssembler::EnsureEmitFor`
150
151- Private to the MacroAssembler (but available, in a DEPRECATED form, to
152  VIXL64 users).
153- Ensure that there is space in the CodeBuffer so that `size` bytes can be
154  emitted contiguously.
155
156Pools are emitted if `size` bytes would push them out of range, but they are not
157actually blocked; pools can still be emitted during the specified range if they
158are used during the range.
159
160    __ EnsureEmitFor(4096);   // Might dump pools.
161    __ Add(...);
162    __ Add(...);              // These macros will not dump pools. They might
163    __ Add(...);              // emit multiple instructions.
164    __ Add(...);
165    __ Vldr(d0, 12345.0);     // Adds an entry to the literal pool (range ~1KB).
166    __ Add(...);
167    ...
168    __ Add(...);
169    __ Add(...);              // The pool containing 12345.0 will be dumped
170    __ Add(...);              // before the end of the EnsureEmitFor range.
171    __ Add(...);
172
173This is a one-shot call, not a scope utility, so there is no size checking
174available. For that reason, it is risky, but still useful in certain cases.
175There are also tricky corner-cases to consider. Most notably, if literals are
176added to the pool during the `EnsureEmitFor` range, a pool might still be
177generated in that range. This can be avoided by including the size of new
178literals in the size check, but because this is not a scope utility and has not
179destruction checks, we cannot assert that the usage was safe.
180
181Also note that this does not acquire the CodeBuffer, so it is not possible to
182use the Assembler after using this utility alone.
183
184## Usage Examples
185
186### Basic Usage
187
188    void fn(MacroAssembler* masm) {
189      // - Uses delegates if necessary.
190      // - Arbitrary length (including 0, potentially).
191      // - Can automatically reserve space in the code buffer.
192      // - Can automatically dump pools.
193      masm->Add(...);
194    }
195
196    void fn(MacroAssembler* masm) {
197      // - No delegates allowed.
198      //   - If a delegate is called, it should crash even in release mode.
199      //     (This helps to avoid security bugs derived from data-dependent code
200      //     generation.)
201      // - Always generates exactly one instruction.
202      // - No automatic buffer growth, but does check that there is space. (In
203      //   VIXL64, this is done by the CodeBuffer.)
204      // - In VIXL64, this requires that the code buffer has been "acquired".
205      //   Any of the EmissionCheckScopes can do this, as can ExactAssemblyScope
206      //   and CodeBufferCheckScope.
207      SingleEmissionCheckScope(masm);
208      masm->add(...);
209    }
210
211    void fn(Assembler* assm) {
212      // Identical to the MacroAssembler::add example, except that we must use
213      // CodeBufferCheckScope to acquire the buffer.
214      CodeBufferCheckScope(assm, ...);
215      assm->add(...);
216    }
217
218### Macros: Simple Code Generation
219
220    void MacroAssembler::Add(...) {
221      // A macro no larger than
222      // `MacroEmissionCheckScope::kTypicalMacroInstructionMaxSize`.
223      MacroEmissionCheckScope scope(...);
224      ...
225    }
226
227    void MacroAssembler::Printf(...) {
228      // A macro larger than
229      // `MacroEmissionCheckScope::kTypicalMacroInstructionMaxSize`.
230      // We start no scope, but rely only on upper-case macros which create
231      // their own MacroEmissionCheckScopes. Pools can be emitted during
232      // this large macro.
233      Add(...)
234      Ldr(...)
235      ...
236    }
237
238### Patchable Regions: Precise Code Generation
239
240    void fn(MacroAssembler* masm) {
241      __ Add(...);
242      __ Add(...);
243      __ Add(...);
244      {
245        // We want this sequence of instructions to be patched later, so we need
246        // to use instruction-accurate code generation with a predictable size.
247        // It is forbidden to use macros during this scope.
248        ExactAssemblyScope(masm, 4 * kInstructionSize);
249        __ bind(&patch_location);
250        __ add(...);
251        __ add(...);
252        __ add(...);
253        __ add(...);
254      }
255      __ Add(...);
256      __ Add(...);
257      __ Add(...);
258    }
259