12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/*
22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project
32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License.
62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at
72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software
112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and
142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License.
152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */
16a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
17166db04e259ca51838c311891598664deeed85adIan Rogers#ifndef ART_COMPILER_UTILS_ASSEMBLER_H_
18166db04e259ca51838c311891598664deeed85adIan Rogers#define ART_COMPILER_UTILS_ASSEMBLER_H_
19a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
202c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers#include <vector>
212c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
22d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "arch/instruction_set.h"
238c434dcc78d497e18590461700894d1c3e96013dGoran Jakovljevic#include "arch/instruction_set_features.h"
244fda4eb799c95be266f52aaf3461a440ea86b841David Srbecky#include "arm/constants_arm.h"
25d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko#include "base/arena_allocator.h"
26d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko#include "base/arena_object.h"
2707ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h"
28761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/macros.h"
294fda4eb799c95be266f52aaf3461a440ea86b841David Srbecky#include "debug/dwarf/debug_frame_opcode_writer.h"
3085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe#include "label.h"
31578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "managed_register.h"
32578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "memory_region.h"
33d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "mips/constants_mips.h"
34578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "offsets.h"
35d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "x86/constants_x86.h"
36d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "x86_64/constants_x86_64.h"
37a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
386b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapironamespace art {
39a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
40a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiroclass Assembler;
41a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiroclass AssemblerBuffer;
42a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
43a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro// Assembler fixups are positions in generated code that require processing
44a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro// after the code has been copied to executable memory. This includes building
45a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro// relocation information.
46a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiroclass AssemblerFixup {
47a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro public:
48a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  virtual void Process(const MemoryRegion& region, int position) = 0;
49a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  virtual ~AssemblerFixup() {}
50a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
51a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro private:
52a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  AssemblerFixup* previous_;
53a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  int position_;
54a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
55a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  AssemblerFixup* previous() const { return previous_; }
56277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe  void set_previous(AssemblerFixup* previous_in) { previous_ = previous_in; }
57a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
58a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  int position() const { return position_; }
59277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe  void set_position(int position_in) { position_ = position_in; }
60a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
61a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  friend class AssemblerBuffer;
62a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro};
63a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
6445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers// Parent of all queued slow paths, emitted during finalization
65d1ee80948144526b985afb44a0574248cf7da58aVladimir Markoclass SlowPath : public DeletableArenaObject<kArenaAllocAssembler> {
6645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers public:
672cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  SlowPath() : next_(nullptr) {}
6845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  virtual ~SlowPath() {}
6945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
7045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  Label* Continuation() { return &continuation_; }
7145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  Label* Entry() { return &entry_; }
7245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Generate code for slow path
7345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  virtual void Emit(Assembler *sp_asm) = 0;
7445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
7545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers protected:
7645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Entry branched to by fast path
7745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  Label entry_;
7845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Optional continuation that is branched to at the end of the slow path
7945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  Label continuation_;
8045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Next in linked list of slow paths
8145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  SlowPath *next_;
8245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
8302e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier private:
8445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  friend class AssemblerBuffer;
8545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  DISALLOW_COPY_AND_ASSIGN(SlowPath);
8645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers};
8745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
88a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiroclass AssemblerBuffer {
89a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro public:
90d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko  explicit AssemblerBuffer(ArenaAllocator* arena);
91a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  ~AssemblerBuffer();
92a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
93d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko  ArenaAllocator* GetArena() {
94d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko    return arena_;
95d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko  }
96d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko
97a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  // Basic support for emitting, loading, and storing.
98a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  template<typename T> void Emit(T value) {
99a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro    CHECK(HasEnsuredCapacity());
100a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro    *reinterpret_cast<T*>(cursor_) = value;
101a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro    cursor_ += sizeof(T);
102a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  }
103a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
104a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  template<typename T> T Load(size_t position) {
105a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro    CHECK_LE(position, Size() - static_cast<int>(sizeof(T)));
106a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro    return *reinterpret_cast<T*>(contents_ + position);
107a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  }
108a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
109a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  template<typename T> void Store(size_t position, T value) {
110a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro    CHECK_LE(position, Size() - static_cast<int>(sizeof(T)));
111a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro    *reinterpret_cast<T*>(contents_ + position) = value;
112a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  }
113a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
114cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  void Resize(size_t new_size) {
115cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    if (new_size > Capacity()) {
116cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko      ExtendCapacity(new_size);
117cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    }
118cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    cursor_ = contents_ + new_size;
119cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  }
120cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko
121cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  void Move(size_t newposition, size_t oldposition, size_t size) {
122cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    // Move a chunk of the buffer from oldposition to newposition.
123cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    DCHECK_LE(oldposition + size, Size());
124cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    DCHECK_LE(newposition + size, Size());
125cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko    memmove(contents_ + newposition, contents_ + oldposition, size);
12665fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison  }
12765fcc2cf3c5cd97b84330c094908f3a6a7a8d4e7Dave Allison
128a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  // Emit a fixup at the current location.
129a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  void EmitFixup(AssemblerFixup* fixup) {
130a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro    fixup->set_previous(fixup_);
131a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro    fixup->set_position(Size());
132a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro    fixup_ = fixup;
133a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  }
134a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
13545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void EnqueueSlowPath(SlowPath* slowpath) {
1362cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    if (slow_path_ == nullptr) {
13745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers      slow_path_ = slowpath;
13845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    } else {
13945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers      SlowPath* cur = slow_path_;
1402cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      for ( ; cur->next_ != nullptr ; cur = cur->next_) {}
14145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers      cur->next_ = slowpath;
14245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    }
14345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
14445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
14545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  void EmitSlowPaths(Assembler* sp_asm) {
14645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    SlowPath* cur = slow_path_;
1472cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    SlowPath* next = nullptr;
1482cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    slow_path_ = nullptr;
1492cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    for ( ; cur != nullptr ; cur = next) {
15045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers      cur->Emit(sp_asm);
15145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers      next = cur->next_;
15245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers      delete cur;
15345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers    }
15445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  }
15545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
156a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  // Get the size of the emitted code.
157a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  size_t Size() const {
158a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro    CHECK_GE(cursor_, contents_);
159a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro    return cursor_ - contents_;
160a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  }
161a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
16213735955f39b3b304c37d2b2840663c131262c18Ian Rogers  uint8_t* contents() const { return contents_; }
163a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
164a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  // Copy the assembled instructions into the specified memory block
165a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  // and apply all fixups.
166a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  void FinalizeInstructions(const MemoryRegion& region);
167a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
168a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  // To emit an instruction to the assembler buffer, the EnsureCapacity helper
169a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  // must be used to guarantee that the underlying data area is big enough to
170a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  // hold the emitted instruction. Usage:
171a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  //
172a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  //     AssemblerBuffer buffer;
173a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  //     AssemblerBuffer::EnsureCapacity ensured(&buffer);
174a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  //     ... emit bytes for single instruction ...
175a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
17631f1f4fa9472774de69664bdb4612045a7f91cd8Elliott Hughes#ifndef NDEBUG
177a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
178a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  class EnsureCapacity {
179a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro   public:
180a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro    explicit EnsureCapacity(AssemblerBuffer* buffer) {
181b44ed124352a0e3c6338a4d01b604c7c6462e673Vladimir Marko      if (buffer->cursor() > buffer->limit()) {
182b44ed124352a0e3c6338a4d01b604c7c6462e673Vladimir Marko        buffer->ExtendCapacity(buffer->Size() + kMinimumGap);
18331f1f4fa9472774de69664bdb4612045a7f91cd8Elliott Hughes      }
184a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro      // In debug mode, we save the assembler buffer along with the gap
185a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro      // size before we start emitting to the buffer. This allows us to
186a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro      // check that any single generated instruction doesn't overflow the
187a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro      // limit implied by the minimum gap size.
188a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro      buffer_ = buffer;
189a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro      gap_ = ComputeGap();
190a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro      // Make sure that extending the capacity leaves a big enough gap
191a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro      // for any kind of instruction.
192a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro      CHECK_GE(gap_, kMinimumGap);
193a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro      // Mark the buffer as having ensured the capacity.
194a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro      CHECK(!buffer->HasEnsuredCapacity());  // Cannot nest.
195a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro      buffer->has_ensured_capacity_ = true;
196a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro    }
197a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
198a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro    ~EnsureCapacity() {
199a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro      // Unmark the buffer, so we cannot emit after this.
200a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro      buffer_->has_ensured_capacity_ = false;
201a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro      // Make sure the generated instruction doesn't take up more
202a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro      // space than the minimum gap.
203a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro      int delta = gap_ - ComputeGap();
204b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers      CHECK_LE(delta, kMinimumGap);
205a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro    }
206a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
207a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro   private:
208a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro    AssemblerBuffer* buffer_;
209a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro    int gap_;
210a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
211a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro    int ComputeGap() { return buffer_->Capacity() - buffer_->Size(); }
212a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  };
213a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
214a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  bool has_ensured_capacity_;
215a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  bool HasEnsuredCapacity() const { return has_ensured_capacity_; }
216a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
217a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro#else
218a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
219a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  class EnsureCapacity {
220a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro   public:
221a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro    explicit EnsureCapacity(AssemblerBuffer* buffer) {
222b44ed124352a0e3c6338a4d01b604c7c6462e673Vladimir Marko      if (buffer->cursor() > buffer->limit()) {
223b44ed124352a0e3c6338a4d01b604c7c6462e673Vladimir Marko        buffer->ExtendCapacity(buffer->Size() + kMinimumGap);
224b44ed124352a0e3c6338a4d01b604c7c6462e673Vladimir Marko      }
225a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro    }
226a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  };
227a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
228a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  // When building the C++ tests, assertion code is enabled. To allow
229a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  // asserting that the user of the assembler buffer has ensured the
230a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  // capacity needed for emitting, we add a dummy method in non-debug mode.
231a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  bool HasEnsuredCapacity() const { return true; }
232a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
233a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro#endif
234a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
235a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  // Returns the position in the instruction stream.
236a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  int GetPosition() { return  cursor_ - contents_; }
237a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
238b44ed124352a0e3c6338a4d01b604c7c6462e673Vladimir Marko  size_t Capacity() const {
239b44ed124352a0e3c6338a4d01b604c7c6462e673Vladimir Marko    CHECK_GE(limit_, contents_);
240b44ed124352a0e3c6338a4d01b604c7c6462e673Vladimir Marko    return (limit_ - contents_) + kMinimumGap;
241b44ed124352a0e3c6338a4d01b604c7c6462e673Vladimir Marko  }
242b44ed124352a0e3c6338a4d01b604c7c6462e673Vladimir Marko
243b44ed124352a0e3c6338a4d01b604c7c6462e673Vladimir Marko  // Unconditionally increase the capacity.
244b44ed124352a0e3c6338a4d01b604c7c6462e673Vladimir Marko  // The provided `min_capacity` must be higher than current `Capacity()`.
245b44ed124352a0e3c6338a4d01b604c7c6462e673Vladimir Marko  void ExtendCapacity(size_t min_capacity);
2467cffc3b0004d32faffc552c0a59286f369b21504Andreas Gampe
247a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro private:
248a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  // The limit is set to kMinimumGap bytes before the end of the data area.
249a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  // This leaves enough space for the longest possible instruction and allows
250a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  // for a single, fast space check per instruction.
251a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  static const int kMinimumGap = 32;
252a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
253d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko  ArenaAllocator* arena_;
25413735955f39b3b304c37d2b2840663c131262c18Ian Rogers  uint8_t* contents_;
25513735955f39b3b304c37d2b2840663c131262c18Ian Rogers  uint8_t* cursor_;
25613735955f39b3b304c37d2b2840663c131262c18Ian Rogers  uint8_t* limit_;
257a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  AssemblerFixup* fixup_;
258b48b9eb6d181a1f52e2e605cf26a21505f1d46edIan Rogers#ifndef NDEBUG
259a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  bool fixups_processed_;
260b48b9eb6d181a1f52e2e605cf26a21505f1d46edIan Rogers#endif
261a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
26245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  // Head of linked list of slow paths
26345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers  SlowPath* slow_path_;
26445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers
26513735955f39b3b304c37d2b2840663c131262c18Ian Rogers  uint8_t* cursor() const { return cursor_; }
26613735955f39b3b304c37d2b2840663c131262c18Ian Rogers  uint8_t* limit() const { return limit_; }
267a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
268a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  // Process the fixup chain starting at the given fixup. The offset is
269a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  // non-zero for fixups in the body if the preamble is non-empty.
270a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  void ProcessFixups(const MemoryRegion& region);
271a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
272a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  // Compute the limit based on the data area and the capacity. See
273a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  // description of kMinimumGap for the reasoning behind the value.
27413735955f39b3b304c37d2b2840663c131262c18Ian Rogers  static uint8_t* ComputeLimit(uint8_t* data, size_t capacity) {
275a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro    return data + capacity - kMinimumGap;
276a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  }
277a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
278a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro  friend class AssemblerFixup;
279a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro};
280a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
281dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky// The purpose of this class is to ensure that we do not have to explicitly
282dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky// call the AdvancePC method (which is good for convenience and correctness).
283dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbeckyclass DebugFrameOpCodeWriterForAssembler FINAL
284dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky    : public dwarf::DebugFrameOpCodeWriter<> {
285dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky public:
28610ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  struct DelayedAdvancePC {
28710ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    uint32_t stream_pos;
28810ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    uint32_t pc;
28910ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  };
29010ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko
291dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky  // This method is called the by the opcode writers.
292dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky  virtual void ImplicitlyAdvancePC() FINAL;
293dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky
294dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky  explicit DebugFrameOpCodeWriterForAssembler(Assembler* buffer)
29510ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko      : dwarf::DebugFrameOpCodeWriter<>(false /* enabled */),
29610ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko        assembler_(buffer),
29710ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko        delay_emitting_advance_pc_(false),
29810ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko        delayed_advance_pcs_() {
29910ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  }
30010ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko
30110ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  ~DebugFrameOpCodeWriterForAssembler() {
30210ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    DCHECK(delayed_advance_pcs_.empty());
30310ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  }
30410ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko
30510ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  // Tell the writer to delay emitting advance PC info.
30610ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  // The assembler must explicitly process all the delayed advances.
30710ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  void DelayEmittingAdvancePCs() {
30810ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    delay_emitting_advance_pc_ = true;
30910ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  }
31010ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko
31110ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  // Override the last delayed PC. The new PC can be out of order.
31210ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  void OverrideDelayedPC(size_t pc) {
31310ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    DCHECK(delay_emitting_advance_pc_);
31410ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    DCHECK(!delayed_advance_pcs_.empty());
31510ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    delayed_advance_pcs_.back().pc = pc;
31610ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  }
31710ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko
31810ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  // Return the number of delayed advance PC entries.
31910ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  size_t NumberOfDelayedAdvancePCs() const {
32010ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    return delayed_advance_pcs_.size();
32110ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  }
32210ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko
32310ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  // Release the CFI stream and advance PC infos so that the assembler can patch it.
32410ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  std::pair<std::vector<uint8_t>, std::vector<DelayedAdvancePC>>
32510ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  ReleaseStreamAndPrepareForDelayedAdvancePC() {
32610ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    DCHECK(delay_emitting_advance_pc_);
32710ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    delay_emitting_advance_pc_ = false;
32810ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    std::pair<std::vector<uint8_t>, std::vector<DelayedAdvancePC>> result;
32910ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    result.first.swap(opcodes_);
33010ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    result.second.swap(delayed_advance_pcs_);
33110ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    return result;
33210ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  }
33310ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko
33410ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  // Reserve space for the CFI stream.
33510ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  void ReserveCFIStream(size_t capacity) {
33610ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    opcodes_.reserve(capacity);
33710ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  }
33810ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko
33910ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  // Append raw data to the CFI stream.
34010ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  void AppendRawData(const std::vector<uint8_t>& raw_data, size_t first, size_t last) {
34110ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    DCHECK_LE(0u, first);
34210ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    DCHECK_LE(first, last);
34310ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    DCHECK_LE(last, raw_data.size());
34410ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko    opcodes_.insert(opcodes_.end(), raw_data.begin() + first, raw_data.begin() + last);
345dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky  }
346dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky
347dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky private:
348dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky  Assembler* assembler_;
34910ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  bool delay_emitting_advance_pc_;
35010ef6941648aad04d54527d4a7a6070bf7065e88Vladimir Marko  std::vector<DelayedAdvancePC> delayed_advance_pcs_;
351dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky};
352dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky
353d1ee80948144526b985afb44a0574248cf7da58aVladimir Markoclass Assembler : public DeletableArenaObject<kArenaAllocAssembler> {
3542c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers public:
355d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko  static std::unique_ptr<Assembler> Create(
356d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko      ArenaAllocator* arena,
357d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko      InstructionSet instruction_set,
358d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko      const InstructionSetFeatures* instruction_set_features = nullptr);
3592c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
360cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  // Finalize the code; emit slow paths, fixup branches, add literal pool, etc.
361cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko  virtual void FinalizeCode() { buffer_.EmitSlowPaths(this); }
3622c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
3632c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  // Size of generated code
364ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  virtual size_t CodeSize() const { return buffer_.Size(); }
365eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames  virtual const uint8_t* CodeBufferBaseAddress() const { return buffer_.contents(); }
3662c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
3672c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  // Copy instructions out of assembly buffer into the given region of memory
368ed8dd492e43cbaaa435c4892447072c84dbaf2dcSerban Constantinescu  virtual void FinalizeInstructions(const MemoryRegion& region) {
3692c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers    buffer_.FinalizeInstructions(region);
3702c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  }
3712c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
372d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray  // TODO: Implement with disassembler.
3734b8f1ecd3aa5a29ec1463ff88fee9db365f257dcRoland Levillain  virtual void Comment(const char* format ATTRIBUTE_UNUSED, ...) {}
374d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray
3752c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  // Emit code that will create an activation on the stack
3762c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  virtual void BuildFrame(size_t frame_size, ManagedRegister method_reg,
377b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers                          const std::vector<ManagedRegister>& callee_save_regs,
378fca82208f7128fcda09b6a4743199308332558a2Dmitry Petrochenko                          const ManagedRegisterEntrySpills& entry_spills) = 0;
3792c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
3802c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  // Emit code that will remove an activation from the stack
3812c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  virtual void RemoveFrame(size_t frame_size,
382bdb0391258abc54bf77c676e36847d28a783bfe5Ian Rogers                           const std::vector<ManagedRegister>& callee_save_regs) = 0;
3832c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
3842c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  virtual void IncreaseFrameSize(size_t adjust) = 0;
3852c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  virtual void DecreaseFrameSize(size_t adjust) = 0;
3862c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
3872c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  // Store routines
3882c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  virtual void Store(FrameOffset offs, ManagedRegister src, size_t size) = 0;
3892c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  virtual void StoreRef(FrameOffset dest, ManagedRegister src) = 0;
3902c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  virtual void StoreRawPtr(FrameOffset dest, ManagedRegister src) = 0;
3912c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
3922c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  virtual void StoreImmediateToFrame(FrameOffset dest, uint32_t imm,
3932c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers                                     ManagedRegister scratch) = 0;
3942c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
395dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  virtual void StoreImmediateToThread32(ThreadOffset<4> dest, uint32_t imm,
396dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers                                        ManagedRegister scratch);
397dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  virtual void StoreImmediateToThread64(ThreadOffset<8> dest, uint32_t imm,
398dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers                                        ManagedRegister scratch);
3992c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
400dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  virtual void StoreStackOffsetToThread32(ThreadOffset<4> thr_offs,
401dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers                                          FrameOffset fr_offs,
402dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers                                          ManagedRegister scratch);
403dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  virtual void StoreStackOffsetToThread64(ThreadOffset<8> thr_offs,
404dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers                                          FrameOffset fr_offs,
405dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers                                          ManagedRegister scratch);
4062c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
407dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  virtual void StoreStackPointerToThread32(ThreadOffset<4> thr_offs);
408dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  virtual void StoreStackPointerToThread64(ThreadOffset<8> thr_offs);
4092c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
4102c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  virtual void StoreSpanning(FrameOffset dest, ManagedRegister src,
4112c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers                             FrameOffset in_off, ManagedRegister scratch) = 0;
4122c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
4132c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  // Load routines
4142c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  virtual void Load(ManagedRegister dest, FrameOffset src, size_t size) = 0;
4152c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
416dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  virtual void LoadFromThread32(ManagedRegister dest, ThreadOffset<4> src, size_t size);
417dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  virtual void LoadFromThread64(ManagedRegister dest, ThreadOffset<8> src, size_t size);
4185a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers
419e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  virtual void LoadRef(ManagedRegister dest, FrameOffset src) = 0;
4204d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain  // If unpoison_reference is true and kPoisonReference is true, then we negate the read reference.
421e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier  virtual void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs,
4224d02711ea578dbb789abb30cbaf12f9926e13d81Roland Levillain                       bool unpoison_reference) = 0;
4232c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
424dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  virtual void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) = 0;
4252c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
426dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  virtual void LoadRawPtrFromThread32(ManagedRegister dest, ThreadOffset<4> offs);
427dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  virtual void LoadRawPtrFromThread64(ManagedRegister dest, ThreadOffset<8> offs);
4282c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
4292c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  // Copying routines
430b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers  virtual void Move(ManagedRegister dest, ManagedRegister src, size_t size) = 0;
4312c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
432dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  virtual void CopyRawPtrFromThread32(FrameOffset fr_offs, ThreadOffset<4> thr_offs,
433dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers                                      ManagedRegister scratch);
434dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  virtual void CopyRawPtrFromThread64(FrameOffset fr_offs, ThreadOffset<8> thr_offs,
435dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers                                      ManagedRegister scratch);
4362c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
437dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  virtual void CopyRawPtrToThread32(ThreadOffset<4> thr_offs, FrameOffset fr_offs,
438dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers                                    ManagedRegister scratch);
439dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  virtual void CopyRawPtrToThread64(ThreadOffset<8> thr_offs, FrameOffset fr_offs,
440dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers                                    ManagedRegister scratch);
4412c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
4422c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  virtual void CopyRef(FrameOffset dest, FrameOffset src,
4432c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers                       ManagedRegister scratch) = 0;
4442c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
445a09aea2cf9b56571aa146a4ae42303751e17825fElliott Hughes  virtual void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) = 0;
4462c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
447dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers  virtual void Copy(FrameOffset dest, ManagedRegister src_base, Offset src_offset,
448dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers                    ManagedRegister scratch, size_t size) = 0;
449dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers
4505a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers  virtual void Copy(ManagedRegister dest_base, Offset dest_offset, FrameOffset src,
4515a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers                    ManagedRegister scratch, size_t size) = 0;
4525a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers
453dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers  virtual void Copy(FrameOffset dest, FrameOffset src_base, Offset src_offset,
454dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers                    ManagedRegister scratch, size_t size) = 0;
455dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers
4565a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers  virtual void Copy(ManagedRegister dest, Offset dest_offset,
4575a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers                    ManagedRegister src, Offset src_offset,
4585a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers                    ManagedRegister scratch, size_t size) = 0;
4595a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers
4605a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers  virtual void Copy(FrameOffset dest, Offset dest_offset, FrameOffset src, Offset src_offset,
4615a7a74a042e73a355f5cedffa0d2faf5340028faIan Rogers                    ManagedRegister scratch, size_t size) = 0;
462dc51b79e65abcdad094ccd5e5a2caf5153433d49Ian Rogers
463e5de95b3f9609e02fefd7cda7b21f30c9412eb4cIan Rogers  virtual void MemoryBarrier(ManagedRegister scratch) = 0;
464e5de95b3f9609e02fefd7cda7b21f30c9412eb4cIan Rogers
46558136caeec7cb677bb83c2eafd1f4bab5afd96c8jeffhao  // Sign extension
46658136caeec7cb677bb83c2eafd1f4bab5afd96c8jeffhao  virtual void SignExtend(ManagedRegister mreg, size_t size) = 0;
46758136caeec7cb677bb83c2eafd1f4bab5afd96c8jeffhao
468cee4d0c1c2faacf0eae748a24cc7e455e067d977jeffhao  // Zero extension
469cee4d0c1c2faacf0eae748a24cc7e455e067d977jeffhao  virtual void ZeroExtend(ManagedRegister mreg, size_t size) = 0;
470cee4d0c1c2faacf0eae748a24cc7e455e067d977jeffhao
4712c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  // Exploit fast access in managed code to Thread::Current()
4722c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  virtual void GetCurrentThread(ManagedRegister tr) = 0;
4732c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  virtual void GetCurrentThread(FrameOffset dest_offset,
4742c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers                                ManagedRegister scratch) = 0;
4752c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
4762cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  // Set up out_reg to hold a Object** into the handle scope, or to be null if the
4772c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  // value is null and null_allowed. in_reg holds a possibly stale reference
478eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  // that can be used to avoid loading the handle scope entry to see if the value is
4792cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  // null.
480eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  virtual void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset,
4812c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers                               ManagedRegister in_reg, bool null_allowed) = 0;
4822c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
4832cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  // Set up out_off to hold a Object** into the handle scope, or to be null if the
4842c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  // value is null and null_allowed.
485eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  virtual void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset,
4862c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers                               ManagedRegister scratch, bool null_allowed) = 0;
4872c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
488eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  // src holds a handle scope entry (Object**) load this into dst
489eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  virtual void LoadReferenceFromHandleScope(ManagedRegister dst,
4902c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers                                     ManagedRegister src) = 0;
4912c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
4922c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  // Heap::VerifyObject on src. In some cases (such as a reference to this) we
4932c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  // know that src may not be null.
4942c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  virtual void VerifyObject(ManagedRegister src, bool could_be_null) = 0;
4952c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  virtual void VerifyObject(FrameOffset src, bool could_be_null) = 0;
4962c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
4972c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  // Call to address held at [base+offset]
4982c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  virtual void Call(ManagedRegister base, Offset offset,
4992c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers                    ManagedRegister scratch) = 0;
5002c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  virtual void Call(FrameOffset base, Offset offset,
5012c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers                    ManagedRegister scratch) = 0;
502dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  virtual void CallFromThread32(ThreadOffset<4> offset, ManagedRegister scratch);
503dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers  virtual void CallFromThread64(ThreadOffset<8> offset, ManagedRegister scratch);
5042c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
5052c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  // Generate code to check if Thread::Current()->exception_ is non-null
5062c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  // and branch to a ExceptionSlowPath if it is.
50700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  virtual void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) = 0;
5082c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
50985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  virtual void Bind(Label* label) = 0;
51085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe  virtual void Jump(Label* label) = 0;
51185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe
5122c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  virtual ~Assembler() {}
5132c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
514dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky  /**
515dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky   * @brief Buffer of DWARF's Call Frame Information opcodes.
516dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky   * @details It is used by debuggers and other tools to unwind the call stack.
517dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky   */
518dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky  DebugFrameOpCodeWriterForAssembler& cfi() { return cfi_; }
519dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky
5202c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers protected:
521d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko  explicit Assembler(ArenaAllocator* arena) : buffer_(arena), cfi_(this) {}
522d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko
523d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko  ArenaAllocator* GetArena() {
524d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko    return buffer_.GetArena();
525d1ee80948144526b985afb44a0574248cf7da58aVladimir Marko  }
5262c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
5272c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers  AssemblerBuffer buffer_;
528dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky
529dd97393aca1a3ff2abec4dc4f78d7724300971bcDavid Srbecky  DebugFrameOpCodeWriterForAssembler cfi_;
5302c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers};
5312c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
5326b6b5f0e67ce03f38223a525612955663bc1799bCarl Shapiro}  // namespace art
533a5d5cfda6239d8876937e75eba43222f639d2447Carl Shapiro
534166db04e259ca51838c311891598664deeed85adIan Rogers#endif  // ART_COMPILER_UTILS_ASSEMBLER_H_
535