diff options
Diffstat (limited to 'lib/AsmJit/Util.h')
-rw-r--r-- | lib/AsmJit/Util.h | 933 |
1 files changed, 933 insertions, 0 deletions
diff --git a/lib/AsmJit/Util.h b/lib/AsmJit/Util.h new file mode 100644 index 0000000..da824a6 --- /dev/null +++ b/lib/AsmJit/Util.h @@ -0,0 +1,933 @@ +// AsmJit - Complete JIT Assembler for C++ Language. + +// Copyright (c) 2008-2010, Petr Kobalicek <kobalicek.petr@gmail.com> +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +// [Guard] +#ifndef _ASMJIT_UTIL_H +#define _ASMJIT_UTIL_H + +// [Dependencies] +#include "Build.h" + +#include <stdlib.h> +#include <string.h> + +namespace AsmJit { + +//! @addtogroup AsmJit_Util +//! @{ + +// ============================================================================ +// [AsmJit::Macros] +// ============================================================================ + +// Skip documenting this. +#if !defined(ASMJIT_NODOC) +struct ASMJIT_HIDDEN _DontInitialize {}; +struct ASMJIT_HIDDEN _Initialize {}; +#endif // !ASMJIT_NODOC + +// ============================================================================ +// [AsmJit::Util] +// ============================================================================ + +namespace Util { + +// ============================================================================ +// [AsmJit::Util::isInt?] +// ============================================================================ + +//! @brief Returns @c true if a given integer @a x is signed 8-bit integer +static inline bool isInt8(sysint_t x) ASMJIT_NOTHROW { return x >= -128 && x <= 127; } +//! @brief Returns @c true if a given integer @a x is unsigned 8-bit integer +static inline bool isUInt8(sysint_t x) ASMJIT_NOTHROW { return x >= 0 && x <= 255; } + +//! @brief Returns @c true if a given integer @a x is signed 16-bit integer +static inline bool isInt16(sysint_t x) ASMJIT_NOTHROW { return x >= -32768 && x <= 32767; } +//! @brief Returns @c true if a given integer @a x is unsigned 16-bit integer +static inline bool isUInt16(sysint_t x) ASMJIT_NOTHROW { return x >= 0 && x <= 65535; } + +//! @brief Returns @c true if a given integer @a x is signed 16-bit integer +static inline bool isInt32(sysint_t x) ASMJIT_NOTHROW +{ +#if defined(ASMJIT_X86) + return true; +#else + return x >= ASMJIT_INT64_C(-2147483648) && x <= ASMJIT_INT64_C(2147483647); +#endif +} +//! @brief Returns @c true if a given integer @a x is unsigned 16-bit integer +static inline bool isUInt32(sysint_t x) ASMJIT_NOTHROW +{ +#if defined(ASMJIT_X86) + return x >= 0; +#else + return x >= 0 && x <= ASMJIT_INT64_C(4294967295); +#endif +} + +// ============================================================================ +// [Bit Utils] +// ============================================================================ + +static inline uint32_t maskFromIndex(uint32_t x) +{ + return (1U << x); +} + +static inline uint32_t maskUpToIndex(uint32_t x) +{ + if (x >= 32) + return 0xFFFFFFFF; + else + return (1U << x) - 1; +} + +// From http://graphics.stanford.edu/~seander/bithacks.html . +static inline uint32_t bitCount(uint32_t x) +{ + x = x - ((x >> 1) & 0x55555555); + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + return ((x + (x >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; +} + +static inline uint32_t findFirstBit(uint32_t mask) ASMJIT_NOTHROW +{ + for (uint32_t i = 0, bit = 1; i < sizeof(uint32_t) * 8; i++, bit <<= 1) + { + if (mask & bit) return i; + } + + // INVALID_VALUE. + return 0xFFFFFFFF; +} + +// ============================================================================ +// [Alignment] +// ============================================================================ + +// Align variable @a x to 16-bytes. +template<typename T> +static inline T alignTo16(const T& x) +{ + return (x + (T)15) & (T)~15; +} + +// Return the size needed to align variable @a x to 16-bytes. +template<typename T> +static inline T deltaTo16(const T& x) +{ + T aligned = alignTo16(x); + return aligned - x; +} + +} // Util namespace + +// ============================================================================ +// [AsmJit::function_cast<>] +// ============================================================================ + +//! @brief Cast used to cast pointer to function. It's like reinterpret_cast<>, +//! but uses internally C style cast to work with MinGW. +//! +//! If you are using single compiler and @c reinterpret_cast<> works for you, +//! there is no reason to use @c AsmJit::function_cast<>. If you are writing +//! cross-platform software with various compiler support, consider using +//! @c AsmJit::function_cast<> instead of @c reinterpret_cast<>. +template<typename T, typename Z> +static inline T function_cast(Z* p) ASMJIT_NOTHROW { return (T)p; } + +// ============================================================================ +// [AsmJit::(X)MMData] +// ============================================================================ + +//! @brief Structure used for MMX specific data (64-bit). +//! +//! This structure can be used to load / store data from / to MMX register. +union ASMJIT_HIDDEN MMData +{ + // -------------------------------------------------------------------------- + // [Methods] + // -------------------------------------------------------------------------- + + //! @brief Set all eight signed 8-bit integers. + inline void setSB( + int8_t x0, int8_t x1, int8_t x2, int8_t x3, int8_t x4, int8_t x5, int8_t x6, int8_t x7) ASMJIT_NOTHROW + { + sb[0] = x0; sb[1] = x1; sb[2] = x2; sb[3] = x3; sb[4] = x4; sb[5] = x5; sb[6] = x6; sb[7] = x7; + } + + //! @brief Set all eight unsigned 8-bit integers. + inline void setUB( + uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4, uint8_t x5, uint8_t x6, uint8_t x7) ASMJIT_NOTHROW + { + ub[0] = x0; ub[1] = x1; ub[2] = x2; ub[3] = x3; ub[4] = x4; ub[5] = x5; ub[6] = x6; ub[7] = x7; + } + + //! @brief Set all four signed 16-bit integers. + inline void setSW( + int16_t x0, int16_t x1, int16_t x2, int16_t x3) ASMJIT_NOTHROW + { + sw[0] = x0; sw[1] = x1; sw[2] = x2; sw[3] = x3; + } + + //! @brief Set all four unsigned 16-bit integers. + inline void setUW( + uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3) ASMJIT_NOTHROW + { + uw[0] = x0; uw[1] = x1; uw[2] = x2; uw[3] = x3; + } + + //! @brief Set all two signed 32-bit integers. + inline void setSD( + int32_t x0, int32_t x1) ASMJIT_NOTHROW + { + sd[0] = x0; sd[1] = x1; + } + + //! @brief Set all two unsigned 32-bit integers. + inline void setUD( + uint32_t x0, uint32_t x1) ASMJIT_NOTHROW + { + ud[0] = x0; ud[1] = x1; + } + + //! @brief Set signed 64-bit integer. + inline void setSQ( + int64_t x0) ASMJIT_NOTHROW + { + sq[0] = x0; + } + + //! @brief Set unsigned 64-bit integer. + inline void setUQ( + uint64_t x0) ASMJIT_NOTHROW + { + uq[0] = x0; + } + + //! @brief Set all two SP-FP values. + inline void setSF( + float x0, float x1) ASMJIT_NOTHROW + { + sf[0] = x0; sf[1] = x1; + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! @brief Array of eight signed 8-bit integers. + int8_t sb[8]; + //! @brief Array of eight unsigned 8-bit integers. + uint8_t ub[8]; + //! @brief Array of four signed 16-bit integers. + int16_t sw[4]; + //! @brief Array of four unsigned 16-bit integers. + uint16_t uw[4]; + //! @brief Array of two signed 32-bit integers. + int32_t sd[2]; + //! @brief Array of two unsigned 32-bit integers. + uint32_t ud[2]; + //! @brief Array of one signed 64-bit integer. + int64_t sq[1]; + //! @brief Array of one unsigned 64-bit integer. + uint64_t uq[1]; + + //! @brief Array of two SP-FP values. + float sf[2]; +}; + +//! @brief Structure used for SSE specific data (128-bit). +//! +//! This structure can be used to load / store data from / to SSE register. +//! +//! @note Always align SSE data to 16-bytes. +union ASMJIT_HIDDEN XMMData +{ + // -------------------------------------------------------------------------- + // [Methods] + // -------------------------------------------------------------------------- + + //! @brief Set all sixteen signed 8-bit integers. + inline void setSB( + int8_t x0, int8_t x1, int8_t x2 , int8_t x3 , int8_t x4 , int8_t x5 , int8_t x6 , int8_t x7 , + int8_t x8, int8_t x9, int8_t x10, int8_t x11, int8_t x12, int8_t x13, int8_t x14, int8_t x15) ASMJIT_NOTHROW + { + sb[0] = x0; sb[1] = x1; sb[ 2] = x2 ; sb[3 ] = x3 ; sb[4 ] = x4 ; sb[5 ] = x5 ; sb[6 ] = x6 ; sb[7 ] = x7 ; + sb[8] = x8; sb[9] = x9; sb[10] = x10; sb[11] = x11; sb[12] = x12; sb[13] = x13; sb[14] = x14; sb[15] = x15; + } + + //! @brief Set all sixteen unsigned 8-bit integers. + inline void setUB( + uint8_t x0, uint8_t x1, uint8_t x2 , uint8_t x3 , uint8_t x4 , uint8_t x5 , uint8_t x6 , uint8_t x7 , + uint8_t x8, uint8_t x9, uint8_t x10, uint8_t x11, uint8_t x12, uint8_t x13, uint8_t x14, uint8_t x15) ASMJIT_NOTHROW + { + ub[0] = x0; ub[1] = x1; ub[ 2] = x2 ; ub[3 ] = x3 ; ub[4 ] = x4 ; ub[5 ] = x5 ; ub[6 ] = x6 ; ub[7 ] = x7 ; + ub[8] = x8; ub[9] = x9; ub[10] = x10; ub[11] = x11; ub[12] = x12; ub[13] = x13; ub[14] = x14; ub[15] = x15; + } + + //! @brief Set all eight signed 16-bit integers. + inline void setSW( + int16_t x0, int16_t x1, int16_t x2, int16_t x3, int16_t x4, int16_t x5, int16_t x6, int16_t x7) ASMJIT_NOTHROW + { + sw[0] = x0; sw[1] = x1; sw[2] = x2; sw[3] = x3; sw[4] = x4; sw[5] = x5; sw[6] = x6; sw[7] = x7; + } + + //! @brief Set all eight unsigned 16-bit integers. + inline void setUW( + uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3, uint16_t x4, uint16_t x5, uint16_t x6, uint16_t x7) ASMJIT_NOTHROW + { + uw[0] = x0; uw[1] = x1; uw[2] = x2; uw[3] = x3; uw[4] = x4; uw[5] = x5; uw[6] = x6; uw[7] = x7; + } + + //! @brief Set all four signed 32-bit integers. + inline void setSD( + int32_t x0, int32_t x1, int32_t x2, int32_t x3) ASMJIT_NOTHROW + { + sd[0] = x0; sd[1] = x1; sd[2] = x2; sd[3] = x3; + } + + //! @brief Set all four unsigned 32-bit integers. + inline void setUD( + uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3) ASMJIT_NOTHROW + { + ud[0] = x0; ud[1] = x1; ud[2] = x2; ud[3] = x3; + } + + //! @brief Set all two signed 64-bit integers. + inline void setSQ( + int64_t x0, int64_t x1) ASMJIT_NOTHROW + { + sq[0] = x0; sq[1] = x1; + } + + //! @brief Set all two unsigned 64-bit integers. + inline void setUQ( + uint64_t x0, uint64_t x1) ASMJIT_NOTHROW + { + uq[0] = x0; uq[1] = x1; + } + + //! @brief Set all four SP-FP floats. + inline void setSF( + float x0, float x1, float x2, float x3) ASMJIT_NOTHROW + { + sf[0] = x0; sf[1] = x1; sf[2] = x2; sf[3] = x3; + } + + //! @brief Set all two DP-FP floats. + inline void setDF( + double x0, double x1) ASMJIT_NOTHROW + { + df[0] = x0; df[1] = x1; + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! @brief Array of sixteen signed 8-bit integers. + int8_t sb[16]; + //! @brief Array of sixteen unsigned 8-bit integers. + uint8_t ub[16]; + //! @brief Array of eight signed 16-bit integers. + int16_t sw[8]; + //! @brief Array of eight unsigned 16-bit integers. + uint16_t uw[8]; + //! @brief Array of four signed 32-bit integers. + int32_t sd[4]; + //! @brief Array of four unsigned 32-bit integers. + uint32_t ud[4]; + //! @brief Array of two signed 64-bit integers. + int64_t sq[2]; + //! @brief Array of two unsigned 64-bit integers. + uint64_t uq[2]; + + //! @brief Array of four 32-bit single precision floating points. + float sf[4]; + //! @brief Array of two 64-bit double precision floating points. + double df[2]; +}; + +// ============================================================================ +// [AsmJit::Buffer] +// ============================================================================ + +//! @brief Buffer used to store instruction stream in AsmJit. +//! +//! This class can be dangerous, if you don't know how it works. Assembler +//! instruction stream is usually constructed by multiple calls of emit +//! functions that emits bytes, words, dwords or qwords. But to decrease +//! AsmJit library size and improve performance, we are not checking for +//! buffer overflow for each emit operation, but only once in highler level +//! emit instruction. +//! +//! So, if you want to use this class, you need to do buffer checking yourself +//! by using @c ensureSpace() method. It's designed to grow buffer if needed. +//! Threshold for growing is named @c growThreshold() and it means count of +//! bytes for emitting single operation. Default size is set to 16 bytes, +//! because x86 and x64 instruction can't be larger (so it's space to hold 1 +//! instruction). +//! +//! Example using Buffer: +//! +//! @code +//! // Buffer instance, growThreshold == 16 +//! // (no memory allocated in constructor). +//! AsmJit::Buffer buf(16); +//! +//! // Begin of emit stream, ensure space can fail on out of memory error. +//! if (buf.ensureSpace()) +//! { +//! // here, you can emit up to 16 (growThreshold) bytes +//! buf.emitByte(0x00); +//! buf.emitByte(0x01); +//! buf.emitByte(0x02); +//! buf.emitByte(0x03); +//! ... +//! } +//! @endcode +struct ASMJIT_API Buffer +{ + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + inline Buffer(sysint_t growThreshold = 16) ASMJIT_NOTHROW : + _data(NULL), + _cur(NULL), + _max(NULL), + _capacity(0), + _growThreshold(growThreshold) + { + } + + inline ~Buffer() ASMJIT_NOTHROW + { + if (_data) ASMJIT_FREE(_data); + } + + //! @brief Get start of buffer. + inline uint8_t* getData() const ASMJIT_NOTHROW { return _data; } + + //! @brief Get current pointer in code buffer. + inline uint8_t* getCur() const ASMJIT_NOTHROW { return _cur; } + + //! @brief Get maximum pointer in code buffer for growing. + inline uint8_t* getMax() const ASMJIT_NOTHROW { return _max; } + + //! @brief Get current offset in buffer. + inline sysint_t getOffset() const ASMJIT_NOTHROW { return (sysint_t)(_cur - _data); } + + //! @brief Get capacity of buffer. + inline sysint_t getCapacity() const ASMJIT_NOTHROW { return _capacity; } + + //! @brief Get grow threshold. + inline sysint_t getGrowThreshold() const ASMJIT_NOTHROW { return _growThreshold; } + + //! @brief Ensure space for next instruction + inline bool ensureSpace() ASMJIT_NOTHROW { return (_cur >= _max) ? grow() : true; } + + //! @brief Sets offset to @a o and returns previous offset. + //! + //! This method can be used to truncate buffer or it's used to + //! overwrite specific position in buffer by Assembler. + inline sysint_t toOffset(sysint_t o) ASMJIT_NOTHROW + { + ASMJIT_ASSERT(o < _capacity); + + sysint_t prev = (sysint_t)(_cur - _data); + _cur = _data + o; + return prev; + } + + //! @brief Reallocate buffer. + //! + //! It's only used for growing, buffer is never reallocated to smaller + //! number than current capacity() is. + bool realloc(sysint_t to) ASMJIT_NOTHROW; + + //! @brief Used to grow the buffer. + //! + //! It will typically realloc to twice size of capacity(), but if capacity() + //! is large, it will use smaller steps. + bool grow() ASMJIT_NOTHROW; + + //! @brief Clear everything, but not deallocate buffer. + void clear() ASMJIT_NOTHROW; + + //! @brief Free buffer and NULL all pointers. + void free() ASMJIT_NOTHROW; + + //! @brief Take ownership of the buffer data and purge @c Buffer instance. + uint8_t* take() ASMJIT_NOTHROW; + + // -------------------------------------------------------------------------- + // [Emit] + // -------------------------------------------------------------------------- + + //! @brief Emit Byte. + inline void emitByte(uint8_t x) ASMJIT_NOTHROW + { + *_cur++ = x; + } + + //! @brief Emit Word (2 bytes). + inline void emitWord(uint16_t x) ASMJIT_NOTHROW + { + *(uint16_t *)_cur = x; + _cur += 2; + } + + //! @brief Emit DWord (4 bytes). + inline void emitDWord(uint32_t x) ASMJIT_NOTHROW + { + *(uint32_t *)_cur = x; + _cur += 4; + } + + //! @brief Emit QWord (8 bytes). + inline void emitQWord(uint64_t x) ASMJIT_NOTHROW + { + *(uint64_t *)_cur = x; + _cur += 8; + } + + //! @brief Emit system signed integer (4 or 8 bytes). + inline void emitSysInt(sysint_t x) ASMJIT_NOTHROW + { + *(sysint_t *)_cur = x; + _cur += sizeof(sysint_t); + } + + //! @brief Emit system unsigned integer (4 or 8 bytes). + inline void emitSysUInt(sysuint_t x) ASMJIT_NOTHROW + { + *(sysuint_t *)_cur = x; + _cur += sizeof(sysuint_t); + } + + //! @brief Emit custom data. + void emitData(const void* ptr, sysuint_t len) ASMJIT_NOTHROW; + + // -------------------------------------------------------------------------- + // [Get / Set] + // -------------------------------------------------------------------------- + + //! @brief Set byte at position @a pos. + inline uint8_t getByteAt(sysint_t pos) const ASMJIT_NOTHROW + { + return *reinterpret_cast<const uint8_t*>(_data + pos); + } + + //! @brief Set word at position @a pos. + inline uint16_t getWordAt(sysint_t pos) const ASMJIT_NOTHROW + { + return *reinterpret_cast<const uint16_t*>(_data + pos); + } + + //! @brief Set word at position @a pos. + inline uint32_t getDWordAt(sysint_t pos) const ASMJIT_NOTHROW + { + return *reinterpret_cast<const uint32_t*>(_data + pos); + } + + //! @brief Set word at position @a pos. + inline uint64_t getQWordAt(sysint_t pos) const ASMJIT_NOTHROW + { + return *reinterpret_cast<const uint64_t*>(_data + pos); + } + + //! @brief Set byte at position @a pos. + inline void setByteAt(sysint_t pos, uint8_t x) ASMJIT_NOTHROW + { + *reinterpret_cast<uint8_t*>(_data + pos) = x; + } + + //! @brief Set word at position @a pos. + inline void setWordAt(sysint_t pos, uint16_t x) ASMJIT_NOTHROW + { + *reinterpret_cast<uint16_t*>(_data + pos) = x; + } + + //! @brief Set word at position @a pos. + inline void setDWordAt(sysint_t pos, uint32_t x) ASMJIT_NOTHROW + { + *reinterpret_cast<uint32_t*>(_data + pos) = x; + } + + //! @brief Set word at position @a pos. + inline void setQWordAt(sysint_t pos, uint64_t x) ASMJIT_NOTHROW + { + *reinterpret_cast<uint64_t*>(_data + pos) = x; + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + // All members are public, because they can be accessed and modified by + // Assembler/Compiler directly. + + //! @brief Beginning position of buffer. + uint8_t* _data; + //! @brief Current position in buffer. + uint8_t* _cur; + //! @brief Maximum position in buffer for realloc. + uint8_t* _max; + + //! @brief Buffer capacity (in bytes). + sysint_t _capacity; + + //! @brief Grow threshold + sysint_t _growThreshold; +}; + +// ============================================================================ +// [AsmJit::PodVector<>] +// ============================================================================ + +//! @brief Template used to store and manage array of POD data. +//! +//! This template has these adventages over other vector<> templates: +//! - Non-copyable (designed to be non-copyable, we want it) +//! - No copy-on-write (some implementations of stl can use it) +//! - Optimized for working only with POD types +//! - Uses ASMJIT_... memory management macros +template <typename T> +struct PodVector +{ + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! @brief Create new instance of PodVector template. Data will not + //! be allocated (will be NULL). + inline PodVector() ASMJIT_NOTHROW : _data(NULL), _length(0), _capacity(0) + { + } + + //! @brief Destroy PodVector and free all data. + inline ~PodVector() ASMJIT_NOTHROW + { + if (_data) ASMJIT_FREE(_data); + } + + // -------------------------------------------------------------------------- + // [Data] + // -------------------------------------------------------------------------- + + //! @brief Get vector data. + inline T* getData() ASMJIT_NOTHROW { return _data; } + //! @overload + inline const T* getData() const ASMJIT_NOTHROW { return _data; } + //! @brief Get vector length. + inline sysuint_t getLength() const ASMJIT_NOTHROW { return _length; } + //! @brief get vector capacity (allocation capacity). + inline sysuint_t getCapacity() const ASMJIT_NOTHROW { return _capacity; } + + // -------------------------------------------------------------------------- + // [Manipulation] + // -------------------------------------------------------------------------- + + //! @brief Clear vector data, but not free internal buffer. + void clear() ASMJIT_NOTHROW + { + _length = 0; + } + + //! @brief Clear vector data and free internal buffer. + void free() ASMJIT_NOTHROW + { + if (_data) + { + ASMJIT_FREE(_data); + _data = 0; + _length = 0; + _capacity = 0; + } + } + + //! @brief Prepend @a item to vector. + bool prepend(const T& item) ASMJIT_NOTHROW + { + if (_length == _capacity && !_grow()) return false; + + memmove(_data + 1, _data, sizeof(T) * _length); + memcpy(_data, &item, sizeof(T)); + + _length++; + return true; + } + + //! @brief Insert an @a item at the @a index. + bool insert(sysuint_t index, const T& item) ASMJIT_NOTHROW + { + ASMJIT_ASSERT(index <= _length); + if (_length == _capacity && !_grow()) return false; + + T* dst = _data + index; + memmove(dst + 1, dst, _length - index); + memcpy(dst, &item, sizeof(T)); + + _length++; + return true; + } + + //! @brief Append @a item to vector. + bool append(const T& item) ASMJIT_NOTHROW + { + if (_length == _capacity && !_grow()) return false; + + memcpy(_data + _length, &item, sizeof(T)); + + _length++; + return true; + } + + //! @brief Get index of @a val or (sysuint_t)-1 if not found. + sysuint_t indexOf(const T& val) const ASMJIT_NOTHROW + { + sysuint_t i = 0, len = _length; + for (i = 0; i < len; i++) { if (_data[i] == val) return i; } + return (sysuint_t)-1; + } + + //! @brief Remove element at index @a i. + void removeAt(sysuint_t i) ASMJIT_NOTHROW + { + ASMJIT_ASSERT(i < _length); + + T* dst = _data + i; + _length--; + memmove(dst, dst + 1, _length - i); + } + + //! @brief Swap this pod-vector with @a other. + void swap(PodVector<T>& other) ASMJIT_NOTHROW + { + T* _tmp_data = _data; + sysuint_t _tmp_length = _length; + sysuint_t _tmp_capacity = _capacity; + + _data = other._data; + _length = other._length; + _capacity = other._capacity; + + other._data = _tmp_data; + other._length = _tmp_length; + other._capacity = _tmp_capacity; + } + + //! @brief Get item at position @a i. + inline T& operator[](sysuint_t i) ASMJIT_NOTHROW + { + ASMJIT_ASSERT(i < _length); + return _data[i]; + } + //! @brief Get item at position @a i. + inline const T& operator[](sysuint_t i) const ASMJIT_NOTHROW + { + ASMJIT_ASSERT(i < _length); + return _data[i]; + } + + //! @brief Append the item and return address so it can be initialized. + T* newItem() ASMJIT_NOTHROW + { + if (_length == _capacity && !_grow()) return NULL; + return _data + (_length++); + } + + // -------------------------------------------------------------------------- + // [Private] + // -------------------------------------------------------------------------- + +private: + //! @brief Called to grow internal array. + bool _grow() ASMJIT_NOTHROW + { + return _realloc(_capacity < 16 ? 16 : _capacity * 2); + } + + //! @brief Realloc internal array to fit @a to items. + bool _realloc(sysuint_t to) ASMJIT_NOTHROW + { + ASMJIT_ASSERT(to >= _length); + + T* p = reinterpret_cast<T*>(_data + ? ASMJIT_REALLOC(_data, to * sizeof(T)) + : ASMJIT_MALLOC(to * sizeof(T))); + if (!p) return false; + + _data = p; + _capacity = to; + return true; + } + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + + //! @brief Items data. + T* _data; + //! @brief Length of buffer (count of items in array). + sysuint_t _length; + //! @brief Capacity of buffer (maximum items that can fit to current array). + sysuint_t _capacity; + +private: + ASMJIT_DISABLE_COPY(PodVector<T>) +}; + +// ============================================================================ +// [AsmJit::Zone] +// ============================================================================ + +//! @brief Memory allocator designed to fast alloc memory that will be freed +//! in one step. +//! +//! @note This is hackery for performance. Concept is that objects created +//! by @c Zone are freed all at once. This means that lifetime of +//! these objects are same as zone object itselt. +//! +//! All emittables, variables, labels and states allocated by @c Compiler are +//! allocated through @c Zone object. +struct ASMJIT_API Zone +{ + // -------------------------------------------------------------------------- + // [Construction / Destruction] + // -------------------------------------------------------------------------- + + //! @brief Create new instance of @c Zone. + //! @param chunkSize Default size for one zone chunk. + Zone(sysuint_t chunkSize) ASMJIT_NOTHROW; + + //! @brief Destroy zone instance. + ~Zone() ASMJIT_NOTHROW; + + // -------------------------------------------------------------------------- + // [Methods] + // -------------------------------------------------------------------------- + + //! @brief Allocate @c size bytes of memory and return pointer to it. + //! + //! Pointer allocated by this way will be valid until @c Zone object is + //! destroyed. To create class by this way use placement @c new and + //! @c delete operators: + //! + //! @code + //! // Example of allocating simple class + //! + //! // Your class + //! class Object + //! { + //! // members... + //! }; + //! + //! // Your function + //! void f() + //! { + //! // We are using AsmJit namespace + //! using namespace AsmJit + //! + //! // Create zone object with chunk size of 65536 bytes. + //! Zone zone(65536); + //! + //! // Create your objects using zone object allocating, for example: + //! Object* obj = new(zone.alloc(sizeof(YourClass))) Object(); + //! + //! // ... lifetime of your objects ... + //! + //! // Destroy your objects: + //! obj->~Object(); + //! + //! // Zone destructor will free all memory allocated through it, + //! // alternative is to call @c zone.freeAll(). + //! } + //! @endcode + void* zalloc(sysuint_t size) ASMJIT_NOTHROW; + + //! @brief Helper to duplicate string. + char* zstrdup(const char* str) ASMJIT_NOTHROW; + + //! @brief Free all allocated memory except first block that remains for reuse. + //! + //! Note that this method will invalidate all instances using this memory + //! allocated by this zone instance. + void clear() ASMJIT_NOTHROW; + + //! @brief Free all allocated memory at once. + //! + //! Note that this method will invalidate all instances using this memory + //! allocated by this zone instance. + void freeAll() ASMJIT_NOTHROW; + + //! @brief Get total size of allocated objects - by @c alloc(). + inline sysuint_t getTotal() const ASMJIT_NOTHROW { return _total; } + //! @brief Get (default) chunk size. + inline sysuint_t getChunkSize() const ASMJIT_NOTHROW { return _chunkSize; } + + // -------------------------------------------------------------------------- + // [Chunk] + // -------------------------------------------------------------------------- + + //! @internal + //! + //! @brief One allocated chunk of memory. + struct ASMJIT_HIDDEN Chunk + { + //! @brief Link to previous chunk. + Chunk* prev; + //! @brief Position in this chunk. + sysuint_t pos; + //! @brief Size of this chunk (in bytes). + sysuint_t size; + + //! @brief Data. + uint8_t data[sizeof(void*)]; + + //! @brief Get count of remaining (unused) bytes in chunk. + inline sysuint_t getRemainingBytes() const ASMJIT_NOTHROW { return size - pos; } + }; + + // -------------------------------------------------------------------------- + // [Members] + // -------------------------------------------------------------------------- + +private: + //! @brief Last allocated chunk of memory. + Chunk* _chunks; + //! @brief Total size of allocated objects - by @c alloc() method. + sysuint_t _total; + //! @brief One chunk size. + sysuint_t _chunkSize; +}; + +//! @} + +} // AsmJit namespace + +#endif // _ASMJIT_UTIL_H |