xref: /aosp_15_r20/art/compiler/utils/assembler.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2011 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_COMPILER_UTILS_ASSEMBLER_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_COMPILER_UTILS_ASSEMBLER_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include <vector>
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
23*795d594fSAndroid Build Coastguard Worker 
24*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set.h"
25*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set_features.h"
26*795d594fSAndroid Build Coastguard Worker #include "arm/constants_arm.h"
27*795d594fSAndroid Build Coastguard Worker #include "base/arena_allocator.h"
28*795d594fSAndroid Build Coastguard Worker #include "base/arena_object.h"
29*795d594fSAndroid Build Coastguard Worker #include "base/array_ref.h"
30*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
31*795d594fSAndroid Build Coastguard Worker #include "base/memory_region.h"
32*795d594fSAndroid Build Coastguard Worker #include "base/pointer_size.h"
33*795d594fSAndroid Build Coastguard Worker #include "dwarf/debug_frame_opcode_writer.h"
34*795d594fSAndroid Build Coastguard Worker #include "label.h"
35*795d594fSAndroid Build Coastguard Worker #include "managed_register.h"
36*795d594fSAndroid Build Coastguard Worker #include "offsets.h"
37*795d594fSAndroid Build Coastguard Worker #include "x86/constants_x86.h"
38*795d594fSAndroid Build Coastguard Worker #include "x86_64/constants_x86_64.h"
39*795d594fSAndroid Build Coastguard Worker 
40*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
41*795d594fSAndroid Build Coastguard Worker 
42*795d594fSAndroid Build Coastguard Worker class Assembler;
43*795d594fSAndroid Build Coastguard Worker class AssemblerBuffer;
44*795d594fSAndroid Build Coastguard Worker 
45*795d594fSAndroid Build Coastguard Worker // Assembler fixups are positions in generated code that require processing
46*795d594fSAndroid Build Coastguard Worker // after the code has been copied to executable memory. This includes building
47*795d594fSAndroid Build Coastguard Worker // relocation information.
48*795d594fSAndroid Build Coastguard Worker class AssemblerFixup {
49*795d594fSAndroid Build Coastguard Worker  public:
50*795d594fSAndroid Build Coastguard Worker   virtual void Process(const MemoryRegion& region, int position) = 0;
~AssemblerFixup()51*795d594fSAndroid Build Coastguard Worker   virtual ~AssemblerFixup() {}
52*795d594fSAndroid Build Coastguard Worker 
53*795d594fSAndroid Build Coastguard Worker  private:
54*795d594fSAndroid Build Coastguard Worker   AssemblerFixup* previous_;
55*795d594fSAndroid Build Coastguard Worker   int position_;
56*795d594fSAndroid Build Coastguard Worker 
previous()57*795d594fSAndroid Build Coastguard Worker   AssemblerFixup* previous() const { return previous_; }
set_previous(AssemblerFixup * previous_in)58*795d594fSAndroid Build Coastguard Worker   void set_previous(AssemblerFixup* previous_in) { previous_ = previous_in; }
59*795d594fSAndroid Build Coastguard Worker 
position()60*795d594fSAndroid Build Coastguard Worker   int position() const { return position_; }
set_position(int position_in)61*795d594fSAndroid Build Coastguard Worker   void set_position(int position_in) { position_ = position_in; }
62*795d594fSAndroid Build Coastguard Worker 
63*795d594fSAndroid Build Coastguard Worker   friend class AssemblerBuffer;
64*795d594fSAndroid Build Coastguard Worker };
65*795d594fSAndroid Build Coastguard Worker 
66*795d594fSAndroid Build Coastguard Worker // Parent of all queued slow paths, emitted during finalization
67*795d594fSAndroid Build Coastguard Worker class SlowPath : public DeletableArenaObject<kArenaAllocAssembler> {
68*795d594fSAndroid Build Coastguard Worker  public:
SlowPath()69*795d594fSAndroid Build Coastguard Worker   SlowPath() : next_(nullptr) {}
~SlowPath()70*795d594fSAndroid Build Coastguard Worker   virtual ~SlowPath() {}
71*795d594fSAndroid Build Coastguard Worker 
Continuation()72*795d594fSAndroid Build Coastguard Worker   Label* Continuation() { return &continuation_; }
Entry()73*795d594fSAndroid Build Coastguard Worker   Label* Entry() { return &entry_; }
74*795d594fSAndroid Build Coastguard Worker   // Generate code for slow path
75*795d594fSAndroid Build Coastguard Worker   virtual void Emit(Assembler *sp_asm) = 0;
76*795d594fSAndroid Build Coastguard Worker 
77*795d594fSAndroid Build Coastguard Worker  protected:
78*795d594fSAndroid Build Coastguard Worker   // Entry branched to by fast path
79*795d594fSAndroid Build Coastguard Worker   Label entry_;
80*795d594fSAndroid Build Coastguard Worker   // Optional continuation that is branched to at the end of the slow path
81*795d594fSAndroid Build Coastguard Worker   Label continuation_;
82*795d594fSAndroid Build Coastguard Worker   // Next in linked list of slow paths
83*795d594fSAndroid Build Coastguard Worker   SlowPath *next_;
84*795d594fSAndroid Build Coastguard Worker 
85*795d594fSAndroid Build Coastguard Worker  private:
86*795d594fSAndroid Build Coastguard Worker   friend class AssemblerBuffer;
87*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(SlowPath);
88*795d594fSAndroid Build Coastguard Worker };
89*795d594fSAndroid Build Coastguard Worker 
90*795d594fSAndroid Build Coastguard Worker class AssemblerBuffer {
91*795d594fSAndroid Build Coastguard Worker  public:
92*795d594fSAndroid Build Coastguard Worker   explicit AssemblerBuffer(ArenaAllocator* allocator);
93*795d594fSAndroid Build Coastguard Worker   ~AssemblerBuffer();
94*795d594fSAndroid Build Coastguard Worker 
GetAllocator()95*795d594fSAndroid Build Coastguard Worker   ArenaAllocator* GetAllocator() {
96*795d594fSAndroid Build Coastguard Worker     return allocator_;
97*795d594fSAndroid Build Coastguard Worker   }
98*795d594fSAndroid Build Coastguard Worker 
99*795d594fSAndroid Build Coastguard Worker   // Basic support for emitting, loading, and storing.
Emit(T value)100*795d594fSAndroid Build Coastguard Worker   template<typename T> void Emit(T value) {
101*795d594fSAndroid Build Coastguard Worker     CHECK(HasEnsuredCapacity());
102*795d594fSAndroid Build Coastguard Worker     *reinterpret_cast<T*>(cursor_) = value;
103*795d594fSAndroid Build Coastguard Worker     cursor_ += sizeof(T);
104*795d594fSAndroid Build Coastguard Worker   }
105*795d594fSAndroid Build Coastguard Worker 
Load(size_t position)106*795d594fSAndroid Build Coastguard Worker   template<typename T> T Load(size_t position) {
107*795d594fSAndroid Build Coastguard Worker     CHECK_LE(position, Size() - static_cast<int>(sizeof(T)));
108*795d594fSAndroid Build Coastguard Worker     return *reinterpret_cast<T*>(contents_ + position);
109*795d594fSAndroid Build Coastguard Worker   }
110*795d594fSAndroid Build Coastguard Worker 
Store(size_t position,T value)111*795d594fSAndroid Build Coastguard Worker   template<typename T> void Store(size_t position, T value) {
112*795d594fSAndroid Build Coastguard Worker     CHECK_LE(position, Size() - static_cast<int>(sizeof(T)));
113*795d594fSAndroid Build Coastguard Worker     *reinterpret_cast<T*>(contents_ + position) = value;
114*795d594fSAndroid Build Coastguard Worker   }
115*795d594fSAndroid Build Coastguard Worker 
Resize(size_t new_size)116*795d594fSAndroid Build Coastguard Worker   void Resize(size_t new_size) {
117*795d594fSAndroid Build Coastguard Worker     if (new_size > Capacity()) {
118*795d594fSAndroid Build Coastguard Worker       ExtendCapacity(new_size);
119*795d594fSAndroid Build Coastguard Worker     }
120*795d594fSAndroid Build Coastguard Worker     cursor_ = contents_ + new_size;
121*795d594fSAndroid Build Coastguard Worker   }
122*795d594fSAndroid Build Coastguard Worker 
Move(size_t newposition,size_t oldposition,size_t size)123*795d594fSAndroid Build Coastguard Worker   void Move(size_t newposition, size_t oldposition, size_t size) {
124*795d594fSAndroid Build Coastguard Worker     // Move a chunk of the buffer from oldposition to newposition.
125*795d594fSAndroid Build Coastguard Worker     DCHECK_LE(oldposition + size, Size());
126*795d594fSAndroid Build Coastguard Worker     DCHECK_LE(newposition + size, Size());
127*795d594fSAndroid Build Coastguard Worker     memmove(contents_ + newposition, contents_ + oldposition, size);
128*795d594fSAndroid Build Coastguard Worker   }
129*795d594fSAndroid Build Coastguard Worker 
130*795d594fSAndroid Build Coastguard Worker   // Emit a fixup at the current location.
EmitFixup(AssemblerFixup * fixup)131*795d594fSAndroid Build Coastguard Worker   void EmitFixup(AssemblerFixup* fixup) {
132*795d594fSAndroid Build Coastguard Worker     fixup->set_previous(fixup_);
133*795d594fSAndroid Build Coastguard Worker     fixup->set_position(Size());
134*795d594fSAndroid Build Coastguard Worker     fixup_ = fixup;
135*795d594fSAndroid Build Coastguard Worker   }
136*795d594fSAndroid Build Coastguard Worker 
EnqueueSlowPath(SlowPath * slowpath)137*795d594fSAndroid Build Coastguard Worker   void EnqueueSlowPath(SlowPath* slowpath) {
138*795d594fSAndroid Build Coastguard Worker     if (slow_path_ == nullptr) {
139*795d594fSAndroid Build Coastguard Worker       slow_path_ = slowpath;
140*795d594fSAndroid Build Coastguard Worker     } else {
141*795d594fSAndroid Build Coastguard Worker       SlowPath* cur = slow_path_;
142*795d594fSAndroid Build Coastguard Worker       for ( ; cur->next_ != nullptr ; cur = cur->next_) {}
143*795d594fSAndroid Build Coastguard Worker       cur->next_ = slowpath;
144*795d594fSAndroid Build Coastguard Worker     }
145*795d594fSAndroid Build Coastguard Worker   }
146*795d594fSAndroid Build Coastguard Worker 
EmitSlowPaths(Assembler * sp_asm)147*795d594fSAndroid Build Coastguard Worker   void EmitSlowPaths(Assembler* sp_asm) {
148*795d594fSAndroid Build Coastguard Worker     SlowPath* cur = slow_path_;
149*795d594fSAndroid Build Coastguard Worker     SlowPath* next = nullptr;
150*795d594fSAndroid Build Coastguard Worker     slow_path_ = nullptr;
151*795d594fSAndroid Build Coastguard Worker     for ( ; cur != nullptr ; cur = next) {
152*795d594fSAndroid Build Coastguard Worker       cur->Emit(sp_asm);
153*795d594fSAndroid Build Coastguard Worker       next = cur->next_;
154*795d594fSAndroid Build Coastguard Worker       delete cur;
155*795d594fSAndroid Build Coastguard Worker     }
156*795d594fSAndroid Build Coastguard Worker   }
157*795d594fSAndroid Build Coastguard Worker 
158*795d594fSAndroid Build Coastguard Worker   // Get the size of the emitted code.
Size()159*795d594fSAndroid Build Coastguard Worker   size_t Size() const {
160*795d594fSAndroid Build Coastguard Worker     CHECK_GE(cursor_, contents_);
161*795d594fSAndroid Build Coastguard Worker     return cursor_ - contents_;
162*795d594fSAndroid Build Coastguard Worker   }
163*795d594fSAndroid Build Coastguard Worker 
contents()164*795d594fSAndroid Build Coastguard Worker   uint8_t* contents() const { return contents_; }
165*795d594fSAndroid Build Coastguard Worker 
166*795d594fSAndroid Build Coastguard Worker   // Copy the assembled instructions into the specified memory block.
167*795d594fSAndroid Build Coastguard Worker   void CopyInstructions(const MemoryRegion& region);
168*795d594fSAndroid Build Coastguard Worker 
169*795d594fSAndroid Build Coastguard Worker   // To emit an instruction to the assembler buffer, the EnsureCapacity helper
170*795d594fSAndroid Build Coastguard Worker   // must be used to guarantee that the underlying data area is big enough to
171*795d594fSAndroid Build Coastguard Worker   // hold the emitted instruction. Usage:
172*795d594fSAndroid Build Coastguard Worker   //
173*795d594fSAndroid Build Coastguard Worker   //     AssemblerBuffer buffer;
174*795d594fSAndroid Build Coastguard Worker   //     AssemblerBuffer::EnsureCapacity ensured(&buffer);
175*795d594fSAndroid Build Coastguard Worker   //     ... emit bytes for single instruction ...
176*795d594fSAndroid Build Coastguard Worker 
177*795d594fSAndroid Build Coastguard Worker #ifndef NDEBUG
178*795d594fSAndroid Build Coastguard Worker 
179*795d594fSAndroid Build Coastguard Worker   class EnsureCapacity {
180*795d594fSAndroid Build Coastguard Worker    public:
EnsureCapacity(AssemblerBuffer * buffer)181*795d594fSAndroid Build Coastguard Worker     explicit EnsureCapacity(AssemblerBuffer* buffer) {
182*795d594fSAndroid Build Coastguard Worker       if (buffer->cursor() > buffer->limit()) {
183*795d594fSAndroid Build Coastguard Worker         buffer->ExtendCapacity(buffer->Size() + kMinimumGap);
184*795d594fSAndroid Build Coastguard Worker       }
185*795d594fSAndroid Build Coastguard Worker       // In debug mode, we save the assembler buffer along with the gap
186*795d594fSAndroid Build Coastguard Worker       // size before we start emitting to the buffer. This allows us to
187*795d594fSAndroid Build Coastguard Worker       // check that any single generated instruction doesn't overflow the
188*795d594fSAndroid Build Coastguard Worker       // limit implied by the minimum gap size.
189*795d594fSAndroid Build Coastguard Worker       buffer_ = buffer;
190*795d594fSAndroid Build Coastguard Worker       gap_ = ComputeGap();
191*795d594fSAndroid Build Coastguard Worker       // Make sure that extending the capacity leaves a big enough gap
192*795d594fSAndroid Build Coastguard Worker       // for any kind of instruction.
193*795d594fSAndroid Build Coastguard Worker       CHECK_GE(gap_, kMinimumGap);
194*795d594fSAndroid Build Coastguard Worker       // Mark the buffer as having ensured the capacity.
195*795d594fSAndroid Build Coastguard Worker       CHECK(!buffer->HasEnsuredCapacity());  // Cannot nest.
196*795d594fSAndroid Build Coastguard Worker       buffer->has_ensured_capacity_ = true;
197*795d594fSAndroid Build Coastguard Worker     }
198*795d594fSAndroid Build Coastguard Worker 
~EnsureCapacity()199*795d594fSAndroid Build Coastguard Worker     ~EnsureCapacity() {
200*795d594fSAndroid Build Coastguard Worker       // Unmark the buffer, so we cannot emit after this.
201*795d594fSAndroid Build Coastguard Worker       buffer_->has_ensured_capacity_ = false;
202*795d594fSAndroid Build Coastguard Worker       // Make sure the generated instruction doesn't take up more
203*795d594fSAndroid Build Coastguard Worker       // space than the minimum gap.
204*795d594fSAndroid Build Coastguard Worker       int delta = gap_ - ComputeGap();
205*795d594fSAndroid Build Coastguard Worker       CHECK_LE(delta, kMinimumGap);
206*795d594fSAndroid Build Coastguard Worker     }
207*795d594fSAndroid Build Coastguard Worker 
208*795d594fSAndroid Build Coastguard Worker    private:
209*795d594fSAndroid Build Coastguard Worker     AssemblerBuffer* buffer_;
210*795d594fSAndroid Build Coastguard Worker     int gap_;
211*795d594fSAndroid Build Coastguard Worker 
ComputeGap()212*795d594fSAndroid Build Coastguard Worker     int ComputeGap() { return buffer_->Capacity() - buffer_->Size(); }
213*795d594fSAndroid Build Coastguard Worker   };
214*795d594fSAndroid Build Coastguard Worker 
215*795d594fSAndroid Build Coastguard Worker   bool has_ensured_capacity_;
HasEnsuredCapacity()216*795d594fSAndroid Build Coastguard Worker   bool HasEnsuredCapacity() const { return has_ensured_capacity_; }
217*795d594fSAndroid Build Coastguard Worker 
218*795d594fSAndroid Build Coastguard Worker #else
219*795d594fSAndroid Build Coastguard Worker 
220*795d594fSAndroid Build Coastguard Worker   class EnsureCapacity {
221*795d594fSAndroid Build Coastguard Worker    public:
EnsureCapacity(AssemblerBuffer * buffer)222*795d594fSAndroid Build Coastguard Worker     explicit EnsureCapacity(AssemblerBuffer* buffer) {
223*795d594fSAndroid Build Coastguard Worker       if (buffer->cursor() > buffer->limit()) {
224*795d594fSAndroid Build Coastguard Worker         buffer->ExtendCapacity(buffer->Size() + kMinimumGap);
225*795d594fSAndroid Build Coastguard Worker       }
226*795d594fSAndroid Build Coastguard Worker     }
227*795d594fSAndroid Build Coastguard Worker   };
228*795d594fSAndroid Build Coastguard Worker 
229*795d594fSAndroid Build Coastguard Worker   // When building the C++ tests, assertion code is enabled. To allow
230*795d594fSAndroid Build Coastguard Worker   // asserting that the user of the assembler buffer has ensured the
231*795d594fSAndroid Build Coastguard Worker   // capacity needed for emitting, we add a placeholder method in non-debug mode.
HasEnsuredCapacity()232*795d594fSAndroid Build Coastguard Worker   bool HasEnsuredCapacity() const { return true; }
233*795d594fSAndroid Build Coastguard Worker 
234*795d594fSAndroid Build Coastguard Worker #endif
235*795d594fSAndroid Build Coastguard Worker 
236*795d594fSAndroid Build Coastguard Worker   // Returns the position in the instruction stream.
GetPosition()237*795d594fSAndroid Build Coastguard Worker   int GetPosition() { return  cursor_ - contents_; }
238*795d594fSAndroid Build Coastguard Worker 
Capacity()239*795d594fSAndroid Build Coastguard Worker   size_t Capacity() const {
240*795d594fSAndroid Build Coastguard Worker     CHECK_GE(limit_, contents_);
241*795d594fSAndroid Build Coastguard Worker     return (limit_ - contents_) + kMinimumGap;
242*795d594fSAndroid Build Coastguard Worker   }
243*795d594fSAndroid Build Coastguard Worker 
244*795d594fSAndroid Build Coastguard Worker   // Unconditionally increase the capacity.
245*795d594fSAndroid Build Coastguard Worker   // The provided `min_capacity` must be higher than current `Capacity()`.
246*795d594fSAndroid Build Coastguard Worker   void ExtendCapacity(size_t min_capacity);
247*795d594fSAndroid Build Coastguard Worker 
248*795d594fSAndroid Build Coastguard Worker   void ProcessFixups();
249*795d594fSAndroid Build Coastguard Worker 
250*795d594fSAndroid Build Coastguard Worker  private:
251*795d594fSAndroid Build Coastguard Worker   // The limit is set to kMinimumGap bytes before the end of the data area.
252*795d594fSAndroid Build Coastguard Worker   // This leaves enough space for the longest possible instruction and allows
253*795d594fSAndroid Build Coastguard Worker   // for a single, fast space check per instruction.
254*795d594fSAndroid Build Coastguard Worker   static constexpr int kMinimumGap = 32;
255*795d594fSAndroid Build Coastguard Worker 
256*795d594fSAndroid Build Coastguard Worker   ArenaAllocator* const allocator_;
257*795d594fSAndroid Build Coastguard Worker   uint8_t* contents_;
258*795d594fSAndroid Build Coastguard Worker   uint8_t* cursor_;
259*795d594fSAndroid Build Coastguard Worker   uint8_t* limit_;
260*795d594fSAndroid Build Coastguard Worker   AssemblerFixup* fixup_;
261*795d594fSAndroid Build Coastguard Worker #ifndef NDEBUG
262*795d594fSAndroid Build Coastguard Worker   bool fixups_processed_;
263*795d594fSAndroid Build Coastguard Worker #endif
264*795d594fSAndroid Build Coastguard Worker 
265*795d594fSAndroid Build Coastguard Worker   // Head of linked list of slow paths
266*795d594fSAndroid Build Coastguard Worker   SlowPath* slow_path_;
267*795d594fSAndroid Build Coastguard Worker 
cursor()268*795d594fSAndroid Build Coastguard Worker   uint8_t* cursor() const { return cursor_; }
limit()269*795d594fSAndroid Build Coastguard Worker   uint8_t* limit() const { return limit_; }
270*795d594fSAndroid Build Coastguard Worker 
271*795d594fSAndroid Build Coastguard Worker   // Process the fixup chain starting at the given fixup. The offset is
272*795d594fSAndroid Build Coastguard Worker   // non-zero for fixups in the body if the preamble is non-empty.
273*795d594fSAndroid Build Coastguard Worker   void ProcessFixups(const MemoryRegion& region);
274*795d594fSAndroid Build Coastguard Worker 
275*795d594fSAndroid Build Coastguard Worker   // Compute the limit based on the data area and the capacity. See
276*795d594fSAndroid Build Coastguard Worker   // description of kMinimumGap for the reasoning behind the value.
ComputeLimit(uint8_t * data,size_t capacity)277*795d594fSAndroid Build Coastguard Worker   static uint8_t* ComputeLimit(uint8_t* data, size_t capacity) {
278*795d594fSAndroid Build Coastguard Worker     return data + capacity - kMinimumGap;
279*795d594fSAndroid Build Coastguard Worker   }
280*795d594fSAndroid Build Coastguard Worker 
281*795d594fSAndroid Build Coastguard Worker   friend class AssemblerFixup;
282*795d594fSAndroid Build Coastguard Worker };
283*795d594fSAndroid Build Coastguard Worker 
284*795d594fSAndroid Build Coastguard Worker // The purpose of this class is to ensure that we do not have to explicitly
285*795d594fSAndroid Build Coastguard Worker // call the AdvancePC method (which is good for convenience and correctness).
286*795d594fSAndroid Build Coastguard Worker class DebugFrameOpCodeWriterForAssembler final
287*795d594fSAndroid Build Coastguard Worker     : public dwarf::DebugFrameOpCodeWriter<> {
288*795d594fSAndroid Build Coastguard Worker  public:
289*795d594fSAndroid Build Coastguard Worker   struct DelayedAdvancePC {
290*795d594fSAndroid Build Coastguard Worker     uint32_t stream_pos;
291*795d594fSAndroid Build Coastguard Worker     uint32_t pc;
292*795d594fSAndroid Build Coastguard Worker   };
293*795d594fSAndroid Build Coastguard Worker 
294*795d594fSAndroid Build Coastguard Worker   // This method is called the by the opcode writers.
295*795d594fSAndroid Build Coastguard Worker   void ImplicitlyAdvancePC() final;
296*795d594fSAndroid Build Coastguard Worker 
DebugFrameOpCodeWriterForAssembler(Assembler * buffer)297*795d594fSAndroid Build Coastguard Worker   explicit DebugFrameOpCodeWriterForAssembler(Assembler* buffer)
298*795d594fSAndroid Build Coastguard Worker       : dwarf::DebugFrameOpCodeWriter<>(/* enabled= */ false),
299*795d594fSAndroid Build Coastguard Worker         assembler_(buffer),
300*795d594fSAndroid Build Coastguard Worker         delay_emitting_advance_pc_(false),
301*795d594fSAndroid Build Coastguard Worker         delayed_advance_pcs_() {
302*795d594fSAndroid Build Coastguard Worker   }
303*795d594fSAndroid Build Coastguard Worker 
~DebugFrameOpCodeWriterForAssembler()304*795d594fSAndroid Build Coastguard Worker   ~DebugFrameOpCodeWriterForAssembler() {
305*795d594fSAndroid Build Coastguard Worker     DCHECK(delayed_advance_pcs_.empty());
306*795d594fSAndroid Build Coastguard Worker   }
307*795d594fSAndroid Build Coastguard Worker 
308*795d594fSAndroid Build Coastguard Worker   // Tell the writer to delay emitting advance PC info.
309*795d594fSAndroid Build Coastguard Worker   // The assembler must explicitly process all the delayed advances.
DelayEmittingAdvancePCs()310*795d594fSAndroid Build Coastguard Worker   void DelayEmittingAdvancePCs() {
311*795d594fSAndroid Build Coastguard Worker     delay_emitting_advance_pc_ = true;
312*795d594fSAndroid Build Coastguard Worker   }
313*795d594fSAndroid Build Coastguard Worker 
314*795d594fSAndroid Build Coastguard Worker   // Override the last delayed PC. The new PC can be out of order.
OverrideDelayedPC(size_t pc)315*795d594fSAndroid Build Coastguard Worker   void OverrideDelayedPC(size_t pc) {
316*795d594fSAndroid Build Coastguard Worker     DCHECK(delay_emitting_advance_pc_);
317*795d594fSAndroid Build Coastguard Worker     if (enabled_) {
318*795d594fSAndroid Build Coastguard Worker       DCHECK(!delayed_advance_pcs_.empty());
319*795d594fSAndroid Build Coastguard Worker       delayed_advance_pcs_.back().pc = pc;
320*795d594fSAndroid Build Coastguard Worker     }
321*795d594fSAndroid Build Coastguard Worker   }
322*795d594fSAndroid Build Coastguard Worker 
323*795d594fSAndroid Build Coastguard Worker   // Return the number of delayed advance PC entries.
NumberOfDelayedAdvancePCs()324*795d594fSAndroid Build Coastguard Worker   size_t NumberOfDelayedAdvancePCs() const {
325*795d594fSAndroid Build Coastguard Worker     return delayed_advance_pcs_.size();
326*795d594fSAndroid Build Coastguard Worker   }
327*795d594fSAndroid Build Coastguard Worker 
328*795d594fSAndroid Build Coastguard Worker   // Release the CFI stream and advance PC infos so that the assembler can patch it.
329*795d594fSAndroid Build Coastguard Worker   std::pair<std::vector<uint8_t>, std::vector<DelayedAdvancePC>>
ReleaseStreamAndPrepareForDelayedAdvancePC()330*795d594fSAndroid Build Coastguard Worker   ReleaseStreamAndPrepareForDelayedAdvancePC() {
331*795d594fSAndroid Build Coastguard Worker     DCHECK(delay_emitting_advance_pc_);
332*795d594fSAndroid Build Coastguard Worker     delay_emitting_advance_pc_ = false;
333*795d594fSAndroid Build Coastguard Worker     std::pair<std::vector<uint8_t>, std::vector<DelayedAdvancePC>> result;
334*795d594fSAndroid Build Coastguard Worker     result.first.swap(opcodes_);
335*795d594fSAndroid Build Coastguard Worker     result.second.swap(delayed_advance_pcs_);
336*795d594fSAndroid Build Coastguard Worker     return result;
337*795d594fSAndroid Build Coastguard Worker   }
338*795d594fSAndroid Build Coastguard Worker 
339*795d594fSAndroid Build Coastguard Worker   // Reserve space for the CFI stream.
ReserveCFIStream(size_t capacity)340*795d594fSAndroid Build Coastguard Worker   void ReserveCFIStream(size_t capacity) {
341*795d594fSAndroid Build Coastguard Worker     opcodes_.reserve(capacity);
342*795d594fSAndroid Build Coastguard Worker   }
343*795d594fSAndroid Build Coastguard Worker 
344*795d594fSAndroid Build Coastguard Worker   // Append raw data to the CFI stream.
AppendRawData(const std::vector<uint8_t> & raw_data,size_t first,size_t last)345*795d594fSAndroid Build Coastguard Worker   void AppendRawData(const std::vector<uint8_t>& raw_data, size_t first, size_t last) {
346*795d594fSAndroid Build Coastguard Worker     DCHECK_LE(0u, first);
347*795d594fSAndroid Build Coastguard Worker     DCHECK_LE(first, last);
348*795d594fSAndroid Build Coastguard Worker     DCHECK_LE(last, raw_data.size());
349*795d594fSAndroid Build Coastguard Worker     opcodes_.insert(opcodes_.end(), raw_data.begin() + first, raw_data.begin() + last);
350*795d594fSAndroid Build Coastguard Worker   }
351*795d594fSAndroid Build Coastguard Worker 
352*795d594fSAndroid Build Coastguard Worker  private:
353*795d594fSAndroid Build Coastguard Worker   Assembler* assembler_;
354*795d594fSAndroid Build Coastguard Worker   bool delay_emitting_advance_pc_;
355*795d594fSAndroid Build Coastguard Worker   std::vector<DelayedAdvancePC> delayed_advance_pcs_;
356*795d594fSAndroid Build Coastguard Worker };
357*795d594fSAndroid Build Coastguard Worker 
358*795d594fSAndroid Build Coastguard Worker class Assembler : public DeletableArenaObject<kArenaAllocAssembler> {
359*795d594fSAndroid Build Coastguard Worker  public:
360*795d594fSAndroid Build Coastguard Worker   // Finalize the code; emit slow paths, fixup branches, add literal pool, etc.
FinalizeCode()361*795d594fSAndroid Build Coastguard Worker   virtual void FinalizeCode() {
362*795d594fSAndroid Build Coastguard Worker     buffer_.EmitSlowPaths(this);
363*795d594fSAndroid Build Coastguard Worker     buffer_.ProcessFixups();
364*795d594fSAndroid Build Coastguard Worker   }
365*795d594fSAndroid Build Coastguard Worker 
366*795d594fSAndroid Build Coastguard Worker   // Size of generated code
CodeSize()367*795d594fSAndroid Build Coastguard Worker   virtual size_t CodeSize() const { return buffer_.Size(); }
CodeBufferBaseAddress()368*795d594fSAndroid Build Coastguard Worker   virtual const uint8_t* CodeBufferBaseAddress() const { return buffer_.contents(); }
369*795d594fSAndroid Build Coastguard Worker   // CodePosition() is a non-const method similar to CodeSize(), which is used to
370*795d594fSAndroid Build Coastguard Worker   // record positions within the code buffer for the purpose of signal handling
371*795d594fSAndroid Build Coastguard Worker   // (stack overflow checks and implicit null checks may trigger signals and the
372*795d594fSAndroid Build Coastguard Worker   // signal handlers expect them right before the recorded positions).
373*795d594fSAndroid Build Coastguard Worker   // On most architectures CodePosition() should be equivalent to CodeSize(), but
374*795d594fSAndroid Build Coastguard Worker   // the MIPS assembler needs to be aware of this recording, so it doesn't put
375*795d594fSAndroid Build Coastguard Worker   // the instructions that can trigger signals into branch delay slots. Handling
376*795d594fSAndroid Build Coastguard Worker   // signals from instructions in delay slots is a bit problematic and should be
377*795d594fSAndroid Build Coastguard Worker   // avoided.
378*795d594fSAndroid Build Coastguard Worker   // TODO: Re-evaluate whether we still need this now that MIPS support has been removed.
CodePosition()379*795d594fSAndroid Build Coastguard Worker   virtual size_t CodePosition() { return CodeSize(); }
380*795d594fSAndroid Build Coastguard Worker 
381*795d594fSAndroid Build Coastguard Worker   // Copy instructions out of assembly buffer into the given region of memory
CopyInstructions(const MemoryRegion & region)382*795d594fSAndroid Build Coastguard Worker   virtual void CopyInstructions(const MemoryRegion& region) {
383*795d594fSAndroid Build Coastguard Worker     buffer_.CopyInstructions(region);
384*795d594fSAndroid Build Coastguard Worker   }
385*795d594fSAndroid Build Coastguard Worker 
386*795d594fSAndroid Build Coastguard Worker   // TODO: Implement with disassembler.
Comment(const char * format,...)387*795d594fSAndroid Build Coastguard Worker   virtual void Comment([[maybe_unused]] const char* format, ...) {}
388*795d594fSAndroid Build Coastguard Worker 
389*795d594fSAndroid Build Coastguard Worker   virtual void Bind(Label* label) = 0;
390*795d594fSAndroid Build Coastguard Worker   virtual void Jump(Label* label) = 0;
391*795d594fSAndroid Build Coastguard Worker 
~Assembler()392*795d594fSAndroid Build Coastguard Worker   virtual ~Assembler() {}
393*795d594fSAndroid Build Coastguard Worker 
394*795d594fSAndroid Build Coastguard Worker   /**
395*795d594fSAndroid Build Coastguard Worker    * @brief Buffer of DWARF's Call Frame Information opcodes.
396*795d594fSAndroid Build Coastguard Worker    * @details It is used by debuggers and other tools to unwind the call stack.
397*795d594fSAndroid Build Coastguard Worker    */
cfi()398*795d594fSAndroid Build Coastguard Worker   DebugFrameOpCodeWriterForAssembler& cfi() { return cfi_; }
399*795d594fSAndroid Build Coastguard Worker 
GetAllocator()400*795d594fSAndroid Build Coastguard Worker   ArenaAllocator* GetAllocator() {
401*795d594fSAndroid Build Coastguard Worker     return buffer_.GetAllocator();
402*795d594fSAndroid Build Coastguard Worker   }
403*795d594fSAndroid Build Coastguard Worker 
GetBuffer()404*795d594fSAndroid Build Coastguard Worker   AssemblerBuffer* GetBuffer() {
405*795d594fSAndroid Build Coastguard Worker     return &buffer_;
406*795d594fSAndroid Build Coastguard Worker   }
407*795d594fSAndroid Build Coastguard Worker 
408*795d594fSAndroid Build Coastguard Worker  protected:
Assembler(ArenaAllocator * allocator)409*795d594fSAndroid Build Coastguard Worker   explicit Assembler(ArenaAllocator* allocator) : buffer_(allocator), cfi_(this) {}
410*795d594fSAndroid Build Coastguard Worker 
411*795d594fSAndroid Build Coastguard Worker   AssemblerBuffer buffer_;
412*795d594fSAndroid Build Coastguard Worker 
413*795d594fSAndroid Build Coastguard Worker   DebugFrameOpCodeWriterForAssembler cfi_;
414*795d594fSAndroid Build Coastguard Worker };
415*795d594fSAndroid Build Coastguard Worker 
416*795d594fSAndroid Build Coastguard Worker enum ScaleFactor {
417*795d594fSAndroid Build Coastguard Worker   TIMES_1 = 0,
418*795d594fSAndroid Build Coastguard Worker   TIMES_2 = 1,
419*795d594fSAndroid Build Coastguard Worker   TIMES_4 = 2,
420*795d594fSAndroid Build Coastguard Worker   TIMES_8 = 3
421*795d594fSAndroid Build Coastguard Worker };
422*795d594fSAndroid Build Coastguard Worker 
423*795d594fSAndroid Build Coastguard Worker }  // namespace art
424*795d594fSAndroid Build Coastguard Worker 
425*795d594fSAndroid Build Coastguard Worker #endif  // ART_COMPILER_UTILS_ASSEMBLER_H_
426