summaryrefslogtreecommitdiff
path: root/compiler/utils/assembler.h
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/utils/assembler.h')
-rw-r--r--compiler/utils/assembler.h103
1 files changed, 68 insertions, 35 deletions
diff --git a/compiler/utils/assembler.h b/compiler/utils/assembler.h
index f72f5e55ed..672e1503be 100644
--- a/compiler/utils/assembler.h
+++ b/compiler/utils/assembler.h
@@ -19,16 +19,17 @@
#include <vector>
+#include "arch/instruction_set.h"
#include "base/logging.h"
#include "base/macros.h"
#include "arm/constants_arm.h"
-#include "mips/constants_mips.h"
-#include "x86/constants_x86.h"
-#include "x86_64/constants_x86_64.h"
-#include "instruction_set.h"
#include "managed_register.h"
#include "memory_region.h"
+#include "mips/constants_mips.h"
#include "offsets.h"
+#include "x86/constants_x86.h"
+#include "x86_64/constants_x86_64.h"
+#include "dwarf/debug_frame_opcode_writer.h"
namespace art {
@@ -47,6 +48,9 @@ namespace arm64 {
namespace mips {
class MipsAssembler;
}
+namespace mips64 {
+ class Mips64Assembler;
+}
namespace x86 {
class X86Assembler;
}
@@ -56,19 +60,19 @@ namespace x86_64 {
class ExternalLabel {
public:
- ExternalLabel(const char* name, uword address)
- : name_(name), address_(address) {
- DCHECK(name != nullptr);
+ ExternalLabel(const char* name_in, uintptr_t address_in)
+ : name_(name_in), address_(address_in) {
+ DCHECK(name_in != nullptr);
}
const char* name() const { return name_; }
- uword address() const {
+ uintptr_t address() const {
return address_;
}
private:
const char* name_;
- const uword address_;
+ const uintptr_t address_;
};
class Label {
@@ -84,12 +88,12 @@ class Label {
// for unused labels.
int Position() const {
CHECK(!IsUnused());
- return IsBound() ? -position_ - kPointerSize : position_ - kPointerSize;
+ return IsBound() ? -position_ - sizeof(void*) : position_ - sizeof(void*);
}
int LinkPosition() const {
CHECK(IsLinked());
- return position_ - kPointerSize;
+ return position_ - sizeof(void*);
}
bool IsBound() const { return position_ < 0; }
@@ -105,20 +109,22 @@ class Label {
void BindTo(int position) {
CHECK(!IsBound());
- position_ = -position - kPointerSize;
+ position_ = -position - sizeof(void*);
CHECK(IsBound());
}
void LinkTo(int position) {
CHECK(!IsBound());
- position_ = position + kPointerSize;
+ position_ = position + sizeof(void*);
CHECK(IsLinked());
}
friend class arm::ArmAssembler;
friend class arm::Arm32Assembler;
friend class arm::Thumb2Assembler;
+ friend class arm64::Arm64Assembler;
friend class mips::MipsAssembler;
+ friend class mips64::Mips64Assembler;
friend class x86::X86Assembler;
friend class x86_64::X86_64Assembler;
@@ -139,10 +145,10 @@ class AssemblerFixup {
int position_;
AssemblerFixup* previous() const { return previous_; }
- void set_previous(AssemblerFixup* previous) { previous_ = previous; }
+ void set_previous(AssemblerFixup* previous_in) { previous_ = previous_in; }
int position() const { return position_; }
- void set_position(int position) { position_ = position; }
+ void set_position(int position_in) { position_ = position_in; }
friend class AssemblerBuffer;
};
@@ -150,7 +156,7 @@ class AssemblerFixup {
// Parent of all queued slow paths, emitted during finalization
class SlowPath {
public:
- SlowPath() : next_(NULL) {}
+ SlowPath() : next_(nullptr) {}
virtual ~SlowPath() {}
Label* Continuation() { return &continuation_; }
@@ -210,20 +216,20 @@ class AssemblerBuffer {
}
void EnqueueSlowPath(SlowPath* slowpath) {
- if (slow_path_ == NULL) {
+ if (slow_path_ == nullptr) {
slow_path_ = slowpath;
} else {
SlowPath* cur = slow_path_;
- for ( ; cur->next_ != NULL ; cur = cur->next_) {}
+ for ( ; cur->next_ != nullptr ; cur = cur->next_) {}
cur->next_ = slowpath;
}
}
void EmitSlowPaths(Assembler* sp_asm) {
SlowPath* cur = slow_path_;
- SlowPath* next = NULL;
- slow_path_ = NULL;
- for ( ; cur != NULL ; cur = next) {
+ SlowPath* next = nullptr;
+ slow_path_ = nullptr;
+ for ( ; cur != nullptr ; cur = next) {
cur->Emit(sp_asm);
next = cur->next_;
delete cur;
@@ -236,7 +242,7 @@ class AssemblerBuffer {
return cursor_ - contents_;
}
- byte* contents() const { return contents_; }
+ uint8_t* contents() const { return contents_; }
// Copy the assembled instructions into the specified memory block
// and apply all fixups.
@@ -316,9 +322,9 @@ class AssemblerBuffer {
// for a single, fast space check per instruction.
static const int kMinimumGap = 32;
- byte* contents_;
- byte* cursor_;
- byte* limit_;
+ uint8_t* contents_;
+ uint8_t* cursor_;
+ uint8_t* limit_;
AssemblerFixup* fixup_;
#ifndef NDEBUG
bool fixups_processed_;
@@ -327,8 +333,8 @@ class AssemblerBuffer {
// Head of linked list of slow paths
SlowPath* slow_path_;
- byte* cursor() const { return cursor_; }
- byte* limit() const { return limit_; }
+ uint8_t* cursor() const { return cursor_; }
+ uint8_t* limit() const { return limit_; }
size_t Capacity() const {
CHECK_GE(limit_, contents_);
return (limit_ - contents_) + kMinimumGap;
@@ -340,7 +346,7 @@ class AssemblerBuffer {
// Compute the limit based on the data area and the capacity. See
// description of kMinimumGap for the reasoning behind the value.
- static byte* ComputeLimit(byte* data, size_t capacity) {
+ static uint8_t* ComputeLimit(uint8_t* data, size_t capacity) {
return data + capacity - kMinimumGap;
}
@@ -349,6 +355,23 @@ class AssemblerBuffer {
friend class AssemblerFixup;
};
+// The purpose of this class is to ensure that we do not have to explicitly
+// call the AdvancePC method (which is good for convenience and correctness).
+class DebugFrameOpCodeWriterForAssembler FINAL
+ : public dwarf::DebugFrameOpCodeWriter<> {
+ public:
+ // This method is called the by the opcode writers.
+ virtual void ImplicitlyAdvancePC() FINAL;
+
+ explicit DebugFrameOpCodeWriterForAssembler(Assembler* buffer)
+ : dwarf::DebugFrameOpCodeWriter<>(),
+ assembler_(buffer) {
+ }
+
+ private:
+ Assembler* assembler_;
+};
+
class Assembler {
public:
static Assembler* Create(InstructionSet instruction_set);
@@ -365,7 +388,7 @@ class Assembler {
}
// TODO: Implement with disassembler.
- virtual void Comment(const char* format, ...) { }
+ virtual void Comment(const char* format, ...) { UNUSED(format); }
// Emit code that will create an activation on the stack
virtual void BuildFrame(size_t frame_size, ManagedRegister method_reg,
@@ -411,8 +434,10 @@ class Assembler {
virtual void LoadFromThread32(ManagedRegister dest, ThreadOffset<4> src, size_t size);
virtual void LoadFromThread64(ManagedRegister dest, ThreadOffset<8> src, size_t size);
- virtual void LoadRef(ManagedRegister dest, FrameOffset src) = 0;
- virtual void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs) = 0;
+ virtual void LoadRef(ManagedRegister dest, FrameOffset src) = 0;
+ // If poison_reference is true and kPoisonReference is true, then we negate the read reference.
+ virtual void LoadRef(ManagedRegister dest, ManagedRegister base, MemberOffset offs,
+ bool poison_reference) = 0;
virtual void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) = 0;
@@ -466,14 +491,14 @@ class Assembler {
virtual void GetCurrentThread(FrameOffset dest_offset,
ManagedRegister scratch) = 0;
- // Set up out_reg to hold a Object** into the handle scope, or to be NULL if the
+ // Set up out_reg to hold a Object** into the handle scope, or to be null if the
// value is null and null_allowed. in_reg holds a possibly stale reference
// that can be used to avoid loading the handle scope entry to see if the value is
- // NULL.
+ // null.
virtual void CreateHandleScopeEntry(ManagedRegister out_reg, FrameOffset handlescope_offset,
ManagedRegister in_reg, bool null_allowed) = 0;
- // Set up out_off to hold a Object** into the handle scope, or to be NULL if the
+ // Set up out_off to hold a Object** into the handle scope, or to be null if the
// value is null and null_allowed.
virtual void CreateHandleScopeEntry(FrameOffset out_off, FrameOffset handlescope_offset,
ManagedRegister scratch, bool null_allowed) = 0;
@@ -501,10 +526,18 @@ class Assembler {
virtual ~Assembler() {}
+ /**
+ * @brief Buffer of DWARF's Call Frame Information opcodes.
+ * @details It is used by debuggers and other tools to unwind the call stack.
+ */
+ DebugFrameOpCodeWriterForAssembler& cfi() { return cfi_; }
+
protected:
- Assembler() : buffer_() {}
+ Assembler() : buffer_(), cfi_(this) {}
AssemblerBuffer buffer_;
+
+ DebugFrameOpCodeWriterForAssembler cfi_;
};
} // namespace art