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 |