OLD | NEW |
1 //===- subzero/src/IceAssembler.h - Integrated assembler --------*- C++ -*-===// | 1 //===- subzero/src/IceAssembler.h - Integrated assembler --------*- C++ -*-===// |
2 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 2 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
3 // for details. All rights reserved. Use of this source code is governed by a | 3 // for details. All rights reserved. Use of this source code is governed by a |
4 // BSD-style license that can be found in the LICENSE file. | 4 // BSD-style license that can be found in the LICENSE file. |
5 // | 5 // |
6 // Modified by the Subzero authors. | 6 // Modified by the Subzero authors. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // The Subzero Code Generator | 10 // The Subzero Code Generator |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 *reinterpret_cast<T *>(Contents + Position) = Value; | 56 *reinterpret_cast<T *>(Contents + Position) = Value; |
57 } | 57 } |
58 | 58 |
59 // Emit a fixup at the current location. | 59 // Emit a fixup at the current location. |
60 void emitFixup(AssemblerFixup *Fixup) { Fixup->set_position(size()); } | 60 void emitFixup(AssemblerFixup *Fixup) { Fixup->set_position(size()); } |
61 | 61 |
62 // Get the size of the emitted code. | 62 // Get the size of the emitted code. |
63 intptr_t size() const { return Cursor - Contents; } | 63 intptr_t size() const { return Cursor - Contents; } |
64 uintptr_t contents() const { return Contents; } | 64 uintptr_t contents() const { return Contents; } |
65 | 65 |
66 // To emit an instruction to the assembler buffer, the EnsureCapacity helper | 66 // To emit an instruction to the assembler buffer, the EnsureCapacity helper |
67 // must be used to guarantee that the underlying data area is big enough to | 67 // must be used to guarantee that the underlying data area is big enough to |
68 // hold the emitted instruction. Usage: | 68 // hold the emitted instruction. Usage: |
69 // | 69 // |
70 // AssemblerBuffer buffer; | 70 // AssemblerBuffer buffer; |
71 // AssemblerBuffer::EnsureCapacity ensured(&buffer); | 71 // AssemblerBuffer::EnsureCapacity ensured(&buffer); |
72 // ... emit bytes for single instruction ... | 72 // ... emit bytes for single instruction ... |
73 | 73 |
74 #ifndef NDEBUG | |
75 class EnsureCapacity { | 74 class EnsureCapacity { |
76 EnsureCapacity(const EnsureCapacity &) = delete; | 75 EnsureCapacity(const EnsureCapacity &) = delete; |
77 EnsureCapacity &operator=(const EnsureCapacity &) = delete; | 76 EnsureCapacity &operator=(const EnsureCapacity &) = delete; |
78 | 77 |
79 public: | 78 public: |
80 explicit EnsureCapacity(AssemblerBuffer *Buffer); | 79 explicit EnsureCapacity(AssemblerBuffer *Buffer) : Buffer(Buffer), Gap(0) { |
| 80 if (Buffer->cursor() >= Buffer->limit()) |
| 81 Buffer->extendCapacity(); |
| 82 if (buildAllowsAsserts()) |
| 83 validate(Buffer); |
| 84 } |
81 ~EnsureCapacity(); | 85 ~EnsureCapacity(); |
82 | 86 |
83 private: | 87 private: |
84 AssemblerBuffer *Buffer; | 88 AssemblerBuffer *Buffer; |
85 intptr_t Gap; | 89 intptr_t Gap; |
86 | 90 |
| 91 void validate(AssemblerBuffer *Buffer); |
87 intptr_t computeGap() { return Buffer->capacity() - Buffer->size(); } | 92 intptr_t computeGap() { return Buffer->capacity() - Buffer->size(); } |
88 }; | 93 }; |
89 | 94 |
90 bool HasEnsuredCapacity; | 95 bool HasEnsuredCapacity; |
91 bool hasEnsuredCapacity() const { return HasEnsuredCapacity; } | 96 bool hasEnsuredCapacity() const { |
92 #else // NDEBUG | 97 if (buildAllowsAsserts()) |
93 class EnsureCapacity { | 98 return HasEnsuredCapacity; |
94 EnsureCapacity(const EnsureCapacity &) = delete; | 99 // Disable the actual check in non-debug mode. |
95 EnsureCapacity &operator=(const EnsureCapacity &) = delete; | 100 return true; |
96 | 101 } |
97 public: | |
98 explicit EnsureCapacity(AssemblerBuffer *Buffer) { | |
99 if (Buffer->cursor() >= Buffer->limit()) | |
100 Buffer->extendCapacity(); | |
101 } | |
102 }; | |
103 | |
104 // When building the C++ tests, assertion code is enabled. To allow | |
105 // asserting that the user of the assembler buffer has ensured the | |
106 // capacity needed for emitting, we add a dummy method in non-debug mode. | |
107 bool hasEnsuredCapacity() const { return true; } | |
108 #endif // NDEBUG | |
109 | 102 |
110 // Returns the position in the instruction stream. | 103 // Returns the position in the instruction stream. |
111 intptr_t getPosition() const { return Cursor - Contents; } | 104 intptr_t getPosition() const { return Cursor - Contents; } |
112 | 105 |
113 // Create and track a fixup in the current function. | 106 // Create and track a fixup in the current function. |
114 AssemblerFixup *createFixup(FixupKind Kind, const Constant *Value); | 107 AssemblerFixup *createFixup(FixupKind Kind, const Constant *Value); |
115 | 108 |
116 const FixupRefList &fixups() const { return Fixups; } | 109 const FixupRefList &fixups() const { return Fixups; } |
117 | 110 |
118 void setSize(intptr_t NewSize) { | 111 void setSize(intptr_t NewSize) { |
119 assert(NewSize <= size()); | 112 assert(NewSize <= size()); |
120 Cursor = Contents + NewSize; | 113 Cursor = Contents + NewSize; |
121 } | 114 } |
122 | 115 |
123 private: | 116 private: |
124 // The limit is set to kMinimumGap bytes before the end of the data area. | 117 // The limit is set to kMinimumGap bytes before the end of the data area. |
125 // This leaves enough space for the longest possible instruction and allows | 118 // This leaves enough space for the longest possible instruction and allows |
126 // for a single, fast space check per instruction. | 119 // for a single, fast space check per instruction. |
127 static const intptr_t kMinimumGap = 32; | 120 static constexpr intptr_t kMinimumGap = 32; |
128 | 121 |
129 uintptr_t Contents; | 122 uintptr_t Contents; |
130 uintptr_t Cursor; | 123 uintptr_t Cursor; |
131 uintptr_t Limit; | 124 uintptr_t Limit; |
132 // The member variable is named Assemblr to avoid hiding the class Assembler. | 125 // The member variable is named Assemblr to avoid hiding the class Assembler. |
133 Assembler &Assemblr; | 126 Assembler &Assemblr; |
134 // List of pool-allocated fixups relative to the current function. | 127 // List of pool-allocated fixups relative to the current function. |
135 FixupRefList Fixups; | 128 FixupRefList Fixups; |
136 | 129 |
137 uintptr_t cursor() const { return Cursor; } | 130 uintptr_t cursor() const { return Cursor; } |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 protected: | 219 protected: |
227 // Buffer's constructor uses the Allocator, so it needs to appear after it. | 220 // Buffer's constructor uses the Allocator, so it needs to appear after it. |
228 // TODO(jpp): dependencies on construction order are a nice way of shooting | 221 // TODO(jpp): dependencies on construction order are a nice way of shooting |
229 // yourself in the foot. Fix this. | 222 // yourself in the foot. Fix this. |
230 AssemblerBuffer Buffer; | 223 AssemblerBuffer Buffer; |
231 }; | 224 }; |
232 | 225 |
233 } // end of namespace Ice | 226 } // end of namespace Ice |
234 | 227 |
235 #endif // SUBZERO_SRC_ICEASSEMBLER_H_ | 228 #endif // SUBZERO_SRC_ICEASSEMBLER_H_ |
OLD | NEW |