Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2008-2017, Petr Kobalicek 3 : 4 : This software is provided 'as-is', without any express or implied 5 : warranty. In no event will the authors be held liable for any damages 6 : arising from the use of this software. 7 : 8 : Permission is granted to anyone to use this software for any purpose, 9 : including commercial applications, and to alter it and redistribute it 10 : freely, subject to the following restrictions: 11 : 12 : 1. The origin of this software must not be misrepresented; you must not 13 : claim that you wrote the original software. If you use this software 14 : in a product, an acknowledgment in the product documentation would be 15 : appreciated but is not required. 16 : 2. Altered source versions must be plainly marked as such, and must not be 17 : misrepresented as being the original software. 18 : 3. This notice may not be removed or altered from any source distribution. 19 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ 20 : #ifndef __PLUMED_asmjit_constpool_h 21 : #define __PLUMED_asmjit_constpool_h 22 : #ifdef __PLUMED_HAS_ASMJIT 23 : #pragma GCC diagnostic push 24 : #pragma GCC diagnostic ignored "-Wpedantic" 25 : // [AsmJit] 26 : // Complete x86/x64 JIT and Remote Assembler for C++. 27 : // 28 : // [License] 29 : // Zlib - See LICENSE.md file in the package. 30 : 31 : // [Guard] 32 : #ifndef _ASMJIT_BASE_CONSTPOOL_H 33 : #define _ASMJIT_BASE_CONSTPOOL_H 34 : 35 : // [Dependencies] 36 : #include "./zone.h" 37 : 38 : // [Api-Begin] 39 : #include "./asmjit_apibegin.h" 40 : 41 : namespace PLMD { 42 : namespace asmjit { 43 : 44 : //! \addtogroup asmjit_base 45 : //! \{ 46 : 47 : // ============================================================================ 48 : // [asmjit::ConstPool] 49 : // ============================================================================ 50 : 51 : //! Constant pool. 52 : class ConstPool { 53 : public: 54 : ASMJIT_NONCOPYABLE(ConstPool) 55 : 56 : enum { 57 : kIndex1 = 0, 58 : kIndex2 = 1, 59 : kIndex4 = 2, 60 : kIndex8 = 3, 61 : kIndex16 = 4, 62 : kIndex32 = 5, 63 : kIndexCount = 6 64 : }; 65 : 66 : // -------------------------------------------------------------------------- 67 : // [Gap] 68 : // -------------------------------------------------------------------------- 69 : 70 : //! \internal 71 : //! 72 : //! Zone-allocated const-pool gap. 73 : struct Gap { 74 : Gap* _next; //!< Pointer to the next gap 75 : size_t _offset; //!< Offset of the gap. 76 : size_t _length; //!< Remaining bytes of the gap (basically a gap size). 77 : }; 78 : 79 : // -------------------------------------------------------------------------- 80 : // [Node] 81 : // -------------------------------------------------------------------------- 82 : 83 : //! \internal 84 : //! 85 : //! Zone-allocated const-pool node. 86 : struct Node { 87 : ASMJIT_INLINE void* getData() const noexcept { 88 0 : return static_cast<void*>(const_cast<ConstPool::Node*>(this) + 1); 89 : } 90 : 91 : Node* _link[2]; //!< Left/Right nodes. 92 : uint32_t _level : 31; //!< Horizontal level for balance. 93 : uint32_t _shared : 1; //!< If this constant is shared with another. 94 : uint32_t _offset; //!< Data offset from the beginning of the pool. 95 : }; 96 : 97 : // -------------------------------------------------------------------------- 98 : // [Tree] 99 : // -------------------------------------------------------------------------- 100 : 101 : //! \internal 102 : //! 103 : //! Zone-allocated const-pool tree. 104 : struct Tree { 105 : enum { 106 : //! Maximum tree height == log2(1 << 64). 107 : kHeightLimit = 64 108 : }; 109 : 110 : // -------------------------------------------------------------------------- 111 : // [Construction / Destruction] 112 : // -------------------------------------------------------------------------- 113 : 114 : ASMJIT_INLINE Tree(size_t dataSize = 0) noexcept 115 0 : : _root(nullptr), 116 0 : _length(0), 117 0 : _dataSize(dataSize) {} 118 0 : ASMJIT_INLINE ~Tree() {} 119 : 120 : // -------------------------------------------------------------------------- 121 : // [Reset] 122 : // -------------------------------------------------------------------------- 123 : 124 : ASMJIT_INLINE void reset() noexcept { 125 0 : _root = nullptr; 126 0 : _length = 0; 127 : } 128 : 129 : // -------------------------------------------------------------------------- 130 : // [Accessors] 131 : // -------------------------------------------------------------------------- 132 : 133 : ASMJIT_INLINE bool isEmpty() const noexcept { return _length == 0; } 134 : ASMJIT_INLINE size_t getLength() const noexcept { return _length; } 135 : 136 : ASMJIT_INLINE void setDataSize(size_t dataSize) noexcept { 137 : ASMJIT_ASSERT(isEmpty()); 138 0 : _dataSize = dataSize; 139 : } 140 : 141 : // -------------------------------------------------------------------------- 142 : // [Ops] 143 : // -------------------------------------------------------------------------- 144 : 145 : ASMJIT_API Node* get(const void* data) noexcept; 146 : ASMJIT_API void put(Node* node) noexcept; 147 : 148 : // -------------------------------------------------------------------------- 149 : // [Iterate] 150 : // -------------------------------------------------------------------------- 151 : 152 : template<typename Visitor> 153 : ASMJIT_INLINE void iterate(Visitor& visitor) const noexcept { 154 0 : Node* node = const_cast<Node*>(_root); 155 0 : if (!node) return; 156 : 157 : Node* stack[kHeightLimit]; 158 : size_t top = 0; 159 : 160 : for (;;) { 161 0 : Node* left = node->_link[0]; 162 0 : if (left != nullptr) { 163 : ASMJIT_ASSERT(top != kHeightLimit); 164 0 : stack[top++] = node; 165 : 166 : node = left; 167 0 : continue; 168 : } 169 : 170 0 : Visit: 171 : visitor.visit(node); 172 0 : node = node->_link[1]; 173 0 : if (node != nullptr) 174 0 : continue; 175 : 176 0 : if (top == 0) 177 : return; 178 : 179 0 : node = stack[--top]; 180 0 : goto Visit; 181 : } 182 : } 183 : 184 : // -------------------------------------------------------------------------- 185 : // [Helpers] 186 : // -------------------------------------------------------------------------- 187 : 188 : static ASMJIT_INLINE Node* _newNode(Zone* zone, const void* data, size_t size, size_t offset, bool shared) noexcept { 189 0 : Node* node = zone->allocT<Node>(sizeof(Node) + size); 190 0 : if (ASMJIT_UNLIKELY(!node)) return nullptr; 191 : 192 0 : node->_link[0] = nullptr; 193 0 : node->_link[1] = nullptr; 194 0 : node->_level = 1; 195 0 : node->_shared = shared; 196 0 : node->_offset = static_cast<uint32_t>(offset); 197 : 198 : ::memcpy(node->getData(), data, size); 199 0 : return node; 200 : } 201 : 202 : // -------------------------------------------------------------------------- 203 : // [Members] 204 : // -------------------------------------------------------------------------- 205 : 206 : Node* _root; //!< Root of the tree 207 : size_t _length; //!< Length of the tree (count of nodes). 208 : size_t _dataSize; //!< Size of the data. 209 : }; 210 : 211 : // -------------------------------------------------------------------------- 212 : // [Construction / Destruction] 213 : // -------------------------------------------------------------------------- 214 : 215 : ASMJIT_API ConstPool(Zone* zone) noexcept; 216 : ASMJIT_API ~ConstPool() noexcept; 217 : 218 : // -------------------------------------------------------------------------- 219 : // [Reset] 220 : // -------------------------------------------------------------------------- 221 : 222 : ASMJIT_API void reset(Zone* zone) noexcept; 223 : 224 : // -------------------------------------------------------------------------- 225 : // [Ops] 226 : // -------------------------------------------------------------------------- 227 : 228 : //! Get whether the constant-pool is empty. 229 : ASMJIT_INLINE bool isEmpty() const noexcept { return _size == 0; } 230 : //! Get the size of the constant-pool in bytes. 231 0 : ASMJIT_INLINE size_t getSize() const noexcept { return _size; } 232 : //! Get minimum alignment. 233 0 : ASMJIT_INLINE size_t getAlignment() const noexcept { return _alignment; } 234 : 235 : //! Add a constant to the constant pool. 236 : //! 237 : //! The constant must have known size, which is 1, 2, 4, 8, 16 or 32 bytes. 238 : //! The constant is added to the pool only if it doesn't not exist, otherwise 239 : //! cached value is returned. 240 : //! 241 : //! AsmJit is able to subdivide added constants, so for example if you add 242 : //! 8-byte constant 0x1122334455667788 it will create the following slots: 243 : //! 244 : //! 8-byte: 0x1122334455667788 245 : //! 4-byte: 0x11223344, 0x55667788 246 : //! 247 : //! The reason is that when combining MMX/SSE/AVX code some patterns are used 248 : //! frequently. However, AsmJit is not able to reallocate a constant that has 249 : //! been already added. For example if you try to add 4-byte constant and then 250 : //! 8-byte constant having the same 4-byte pattern as the previous one, two 251 : //! independent slots will be generated by the pool. 252 : ASMJIT_API Error add(const void* data, size_t size, size_t& dstOffset) noexcept; 253 : 254 : // -------------------------------------------------------------------------- 255 : // [Fill] 256 : // -------------------------------------------------------------------------- 257 : 258 : //! Fill the destination with the constants from the pool. 259 : ASMJIT_API void fill(void* dst) const noexcept; 260 : 261 : // -------------------------------------------------------------------------- 262 : // [Members] 263 : // -------------------------------------------------------------------------- 264 : 265 : Zone* _zone; //!< Zone allocator. 266 : Tree _tree[kIndexCount]; //!< Tree per size. 267 : Gap* _gaps[kIndexCount]; //!< Gaps per size. 268 : Gap* _gapPool; //!< Gaps pool 269 : 270 : size_t _size; //!< Size of the pool (in bytes). 271 : size_t _alignment; //!< Required pool alignment. 272 : }; 273 : 274 : //! \} 275 : 276 : } // asmjit namespace 277 : } // namespace PLMD 278 : 279 : // [Api-End] 280 : #include "./asmjit_apiend.h" 281 : 282 : // [Guard] 283 : #endif // _ASMJIT_BASE_CONSTPOOL_H 284 : #pragma GCC diagnostic pop 285 : #endif // __PLUMED_HAS_ASMJIT 286 : #endif