Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 // | 4 // |
| 5 // Modified by the Subzero authors. | 5 // Modified by the Subzero authors. |
| 6 // | 6 // |
| 7 //===- subzero/src/assembler.h - Integrated assembler -----------*- C++ -*-===// | 7 //===- subzero/src/assembler.h - Integrated assembler -----------*- C++ -*-===// |
| 8 // | 8 // |
| 9 // The Subzero Code Generator | 9 // The Subzero Code Generator |
| 10 // | 10 // |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 33 class Assembler; | 33 class Assembler; |
| 34 class AssemblerFixup; | 34 class AssemblerFixup; |
| 35 class AssemblerBuffer; | 35 class AssemblerBuffer; |
| 36 class ConstantRelocatable; | 36 class ConstantRelocatable; |
| 37 class MemoryRegion; | 37 class MemoryRegion; |
| 38 | 38 |
| 39 // Assembler fixups are positions in generated code that hold relocation | 39 // Assembler fixups are positions in generated code that hold relocation |
| 40 // information that needs to be processed before finalizing the code | 40 // information that needs to be processed before finalizing the code |
| 41 // into executable memory. | 41 // into executable memory. |
| 42 class AssemblerFixup { | 42 class AssemblerFixup { |
| 43 AssemblerFixup(const AssemblerFixup &) = delete; | |
| 44 AssemblerFixup &operator=(const AssemblerFixup &) = delete; | |
| 45 | |
| 43 public: | 46 public: |
| 44 virtual void Process(const MemoryRegion ®ion, intptr_t position) = 0; | 47 virtual void Process(const MemoryRegion ®ion, intptr_t position) = 0; |
| 45 | 48 |
| 46 // It would be ideal if the destructor method could be made private, | 49 // It would be ideal if the destructor method could be made private, |
| 47 // but the g++ compiler complains when this is subclassed. | 50 // but the g++ compiler complains when this is subclassed. |
| 48 virtual ~AssemblerFixup() { llvm_unreachable("~AssemblerFixup used"); } | 51 virtual ~AssemblerFixup() { llvm_unreachable("~AssemblerFixup used"); } |
| 49 | 52 |
| 50 intptr_t position() const { return position_; } | 53 intptr_t position() const { return position_; } |
| 51 | 54 |
| 52 FixupKind kind() const { return kind_; } | 55 FixupKind kind() const { return kind_; } |
| 53 | 56 |
| 54 const ConstantRelocatable *value() const { return value_; } | 57 const ConstantRelocatable *value() const { return value_; } |
| 55 | 58 |
| 56 protected: | 59 protected: |
| 57 AssemblerFixup(FixupKind Kind, const ConstantRelocatable *Value) | 60 AssemblerFixup(FixupKind Kind, const ConstantRelocatable *Value) |
| 58 : position_(0), kind_(Kind), value_(Value) {} | 61 : position_(0), kind_(Kind), value_(Value) {} |
| 59 | 62 |
| 60 private: | 63 private: |
| 61 intptr_t position_; | 64 intptr_t position_; |
| 62 FixupKind kind_; | 65 FixupKind kind_; |
| 63 const ConstantRelocatable *value_; | 66 const ConstantRelocatable *value_; |
| 64 | 67 |
| 65 void set_position(intptr_t position) { position_ = position; } | 68 void set_position(intptr_t position) { position_ = position; } |
| 66 | 69 |
| 67 AssemblerFixup(const AssemblerFixup &) = delete; | |
| 68 AssemblerFixup &operator=(const AssemblerFixup &) = delete; | |
| 69 friend class AssemblerBuffer; | 70 friend class AssemblerBuffer; |
| 70 }; | 71 }; |
| 71 | 72 |
| 72 // Assembler buffers are used to emit binary code. They grow on demand. | 73 // Assembler buffers are used to emit binary code. They grow on demand. |
| 73 class AssemblerBuffer { | 74 class AssemblerBuffer { |
| 75 AssemblerBuffer(const AssemblerBuffer &) = delete; | |
| 76 AssemblerBuffer &operator=(const AssemblerBuffer &) = delete; | |
| 77 | |
| 74 public: | 78 public: |
| 75 AssemblerBuffer(Assembler &); | 79 AssemblerBuffer(Assembler &); |
| 76 ~AssemblerBuffer(); | 80 ~AssemblerBuffer(); |
| 77 | 81 |
| 78 // Basic support for emitting, loading, and storing. | 82 // Basic support for emitting, loading, and storing. |
| 79 template <typename T> void Emit(T value) { | 83 template <typename T> void Emit(T value) { |
| 80 assert(HasEnsuredCapacity()); | 84 assert(HasEnsuredCapacity()); |
| 81 *reinterpret_cast<T *>(cursor_) = value; | 85 *reinterpret_cast<T *>(cursor_) = value; |
| 82 cursor_ += sizeof(T); | 86 cursor_ += sizeof(T); |
| 83 } | 87 } |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 111 void FinalizeInstructions(const MemoryRegion ®ion); | 115 void FinalizeInstructions(const MemoryRegion ®ion); |
| 112 | 116 |
| 113 // To emit an instruction to the assembler buffer, the EnsureCapacity helper | 117 // To emit an instruction to the assembler buffer, the EnsureCapacity helper |
| 114 // must be used to guarantee that the underlying data area is big enough to | 118 // must be used to guarantee that the underlying data area is big enough to |
| 115 // hold the emitted instruction. Usage: | 119 // hold the emitted instruction. Usage: |
| 116 // | 120 // |
| 117 // AssemblerBuffer buffer; | 121 // AssemblerBuffer buffer; |
| 118 // AssemblerBuffer::EnsureCapacity ensured(&buffer); | 122 // AssemblerBuffer::EnsureCapacity ensured(&buffer); |
| 119 // ... emit bytes for single instruction ... | 123 // ... emit bytes for single instruction ... |
| 120 | 124 |
| 121 #if defined(DEBUG) | 125 #if defined(DEBUG) |
|
Jim Stichnoth
2014/10/16 18:19:53
Should this be "#if !defined(NDEBUG)"? I.e., is t
jvoung (off chromium)
2014/10/16 19:02:37
Ah yes, I forgot to change this when first bringin
| |
| 122 class EnsureCapacity { | 126 class EnsureCapacity { |
| 127 EnsureCapacity(const EnsureCapacity &) = delete; | |
| 128 EnsureCapacity &operator=(const EnsureCapacity &) = delete; | |
| 129 | |
| 123 public: | 130 public: |
| 124 explicit EnsureCapacity(AssemblerBuffer *buffer); | 131 explicit EnsureCapacity(AssemblerBuffer *buffer); |
| 125 ~EnsureCapacity(); | 132 ~EnsureCapacity(); |
| 126 | 133 |
| 127 private: | 134 private: |
| 128 AssemblerBuffer *buffer_; | 135 AssemblerBuffer *buffer_; |
| 129 intptr_t gap_; | 136 intptr_t gap_; |
| 130 | 137 |
| 131 intptr_t ComputeGap() { return buffer_->Capacity() - buffer_->Size(); } | 138 intptr_t ComputeGap() { return buffer_->Capacity() - buffer_->Size(); } |
| 132 }; | 139 }; |
| 133 | 140 |
| 134 bool has_ensured_capacity_; | 141 bool has_ensured_capacity_; |
| 135 bool HasEnsuredCapacity() const { return has_ensured_capacity_; } | 142 bool HasEnsuredCapacity() const { return has_ensured_capacity_; } |
| 136 #else | 143 #else |
| 137 class EnsureCapacity { | 144 class EnsureCapacity { |
| 138 public: | 145 EnsureCapacity(const EnsureCapacity &) = delete; |
| 146 EnsureCapacity &operator=(const EnsureCapacity &) = delete; | |
| 147 | |
| 148 public: | |
| 139 explicit EnsureCapacity(AssemblerBuffer *buffer) { | 149 explicit EnsureCapacity(AssemblerBuffer *buffer) { |
| 140 if (buffer->cursor() >= buffer->limit()) | 150 if (buffer->cursor() >= buffer->limit()) |
| 141 buffer->ExtendCapacity(); | 151 buffer->ExtendCapacity(); |
| 142 } | 152 } |
| 143 }; | 153 }; |
| 144 | 154 |
| 145 // When building the C++ tests, assertion code is enabled. To allow | 155 // When building the C++ tests, assertion code is enabled. To allow |
| 146 // asserting that the user of the assembler buffer has ensured the | 156 // asserting that the user of the assembler buffer has ensured the |
| 147 // capacity needed for emitting, we add a dummy method in non-debug mode. | 157 // capacity needed for emitting, we add a dummy method in non-debug mode. |
| 148 bool HasEnsuredCapacity() const { return true; } | 158 bool HasEnsuredCapacity() const { return true; } |
| 149 #endif | 159 #endif |
|
Jim Stichnoth
2014/10/16 18:19:53
My personal preference for commenting large #if re
jvoung (off chromium)
2014/10/16 19:02:37
Done, I think -- all these double negations w/ !ND
| |
| 150 | 160 |
| 151 // Returns the position in the instruction stream. | 161 // Returns the position in the instruction stream. |
| 152 intptr_t GetPosition() const { return cursor_ - contents_; } | 162 intptr_t GetPosition() const { return cursor_ - contents_; } |
| 153 | 163 |
| 154 // For bringup only. | 164 // For bringup only. |
| 155 AssemblerFixup *GetLatestFixup() const; | 165 AssemblerFixup *GetLatestFixup() const; |
| 156 | 166 |
| 157 private: | 167 private: |
| 158 // The limit is set to kMinimumGap bytes before the end of the data area. | 168 // The limit is set to kMinimumGap bytes before the end of the data area. |
| 159 // This leaves enough space for the longest possible instruction and allows | 169 // This leaves enough space for the longest possible instruction and allows |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 184 static uintptr_t ComputeLimit(uintptr_t data, intptr_t capacity) { | 194 static uintptr_t ComputeLimit(uintptr_t data, intptr_t capacity) { |
| 185 return data + capacity - kMinimumGap; | 195 return data + capacity - kMinimumGap; |
| 186 } | 196 } |
| 187 | 197 |
| 188 void ExtendCapacity(); | 198 void ExtendCapacity(); |
| 189 | 199 |
| 190 friend class AssemblerFixup; | 200 friend class AssemblerFixup; |
| 191 }; | 201 }; |
| 192 | 202 |
| 193 class Assembler { | 203 class Assembler { |
| 204 Assembler(const Assembler &) = delete; | |
| 205 Assembler &operator=(const Assembler &) = delete; | |
| 206 | |
| 194 public: | 207 public: |
| 195 Assembler() {} | 208 Assembler() {} |
| 196 ~Assembler() {} | 209 ~Assembler() {} |
| 197 | 210 |
| 198 // Allocate a chunk of bytes using the per-Assembler allocator. | 211 // Allocate a chunk of bytes using the per-Assembler allocator. |
| 199 uintptr_t AllocateBytes(size_t bytes) { | 212 uintptr_t AllocateBytes(size_t bytes) { |
| 200 // For now, alignment is not related to NaCl bundle alignment, since | 213 // For now, alignment is not related to NaCl bundle alignment, since |
| 201 // the buffer's GetPosition is relative to the base. So NaCl bundle | 214 // the buffer's GetPosition is relative to the base. So NaCl bundle |
| 202 // alignment checks can be relative to that base. Later, the buffer | 215 // alignment checks can be relative to that base. Later, the buffer |
| 203 // will be copied out to a ".text" section (or an in memory-buffer | 216 // will be copied out to a ".text" section (or an in memory-buffer |
| 204 // that can be mprotect'ed with executable permission), and that | 217 // that can be mprotect'ed with executable permission), and that |
| 205 // second buffer should be aligned for NaCl. | 218 // second buffer should be aligned for NaCl. |
| 206 const size_t Alignment = 16; | 219 const size_t Alignment = 16; |
| 207 return reinterpret_cast<uintptr_t>(Allocator.Allocate(bytes, Alignment)); | 220 return reinterpret_cast<uintptr_t>(Allocator.Allocate(bytes, Alignment)); |
| 208 } | 221 } |
| 209 | 222 |
| 210 // Allocate data of type T using the per-Assembler allocator. | 223 // Allocate data of type T using the per-Assembler allocator. |
| 211 template <typename T> T *Allocate() { return Allocator.Allocate<T>(); } | 224 template <typename T> T *Allocate() { return Allocator.Allocate<T>(); } |
| 212 | 225 |
| 213 private: | 226 private: |
| 214 llvm::BumpPtrAllocator Allocator; | 227 llvm::BumpPtrAllocator Allocator; |
| 215 | |
| 216 Assembler(const Assembler &) = delete; | |
| 217 Assembler &operator=(const Assembler &) = delete; | |
| 218 }; | 228 }; |
| 219 | 229 |
| 220 } // end of namespace Ice | 230 } // end of namespace Ice |
| 221 | 231 |
| 222 #endif // SUBZERO_SRC_ASSEMBLER_H_ | 232 #endif // SUBZERO_SRC_ASSEMBLER_H_ |
| OLD | NEW |