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