X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=include%2Fllvm%2FSupport%2FEndian.h;h=bc93c9a66eef9a221a13ae534782c409ae06554e;hb=40288f72380d2951cd2d4034922c2c515acb6cfd;hp=81690605e87d391143d8d0f658065e77b5b74f91;hpb=2563e201c14bfd45605e151a68e0ce11e1fc0ee9;p=oota-llvm.git diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h index 81690605e87..bc93c9a66ee 100644 --- a/include/llvm/Support/Endian.h +++ b/include/llvm/Support/Endian.h @@ -38,7 +38,7 @@ namespace endian { template inline value_type byte_swap(value_type value) { if (endian != native && sys::IsBigEndianHost != (endian == big)) - return sys::SwapByteOrder(value); + sys::swapByteOrder(value); return value; } @@ -56,6 +56,16 @@ inline value_type read(const void *memory) { return byte_swap(ret); } +/// Read a value of a particular endianness from a buffer, and increment the +/// buffer past that value. +template +inline value_type readNext(const CharT *&memory) { + value_type ret = read(memory); + memory += sizeof(value_type); + return ret; +} + /// Write a value to memory with a particular endianness. template +using make_unsigned_t = typename std::make_unsigned::type; + +/// Read a value of a particular endianness from memory, for a location +/// that starts at the given bit offset within the first byte. +template +inline value_type readAtBitAlignment(const void *memory, uint64_t startBit) { + assert(startBit < 8); + if (startBit == 0) + return read(memory); + else { + // Read two values and compose the result from them. + value_type val[2]; + memcpy(&val[0], + LLVM_ASSUME_ALIGNED( + memory, (detail::PickAlignment::value)), + sizeof(value_type) * 2); + val[0] = byte_swap(val[0]); + val[1] = byte_swap(val[1]); + + // Shift bits from the lower value into place. + make_unsigned_t lowerVal = val[0] >> startBit; + // Mask off upper bits after right shift in case of signed type. + make_unsigned_t numBitsFirstVal = + (sizeof(value_type) * 8) - startBit; + lowerVal &= ((make_unsigned_t)1 << numBitsFirstVal) - 1; + + // Get the bits from the upper value. + make_unsigned_t upperVal = + val[1] & (((make_unsigned_t)1 << startBit) - 1); + // Shift them in to place. + upperVal <<= numBitsFirstVal; + + return lowerVal | upperVal; + } +} + +/// Write a value to memory with a particular endianness, for a location +/// that starts at the given bit offset within the first byte. +template +inline void writeAtBitAlignment(void *memory, value_type value, + uint64_t startBit) { + assert(startBit < 8); + if (startBit == 0) + write(memory, value); + else { + // Read two values and shift the result into them. + value_type val[2]; + memcpy(&val[0], + LLVM_ASSUME_ALIGNED( + memory, (detail::PickAlignment::value)), + sizeof(value_type) * 2); + val[0] = byte_swap(val[0]); + val[1] = byte_swap(val[1]); + + // Mask off any existing bits in the upper part of the lower value that + // we want to replace. + val[0] &= ((make_unsigned_t)1 << startBit) - 1; + make_unsigned_t numBitsFirstVal = + (sizeof(value_type) * 8) - startBit; + make_unsigned_t lowerVal = value; + if (startBit > 0) { + // Mask off the upper bits in the new value that are not going to go into + // the lower value. This avoids a left shift of a negative value, which + // is undefined behavior. + lowerVal &= (((make_unsigned_t)1 << numBitsFirstVal) - 1); + // Now shift the new bits into place + lowerVal <<= startBit; + } + val[0] |= lowerVal; + + // Mask off any existing bits in the lower part of the upper value that + // we want to replace. + val[1] &= ~(((make_unsigned_t)1 << startBit) - 1); + // Next shift the bits that go into the upper value into position. + make_unsigned_t upperVal = value >> numBitsFirstVal; + // Mask off upper bits after right shift in case of signed type. + upperVal &= ((make_unsigned_t)1 << startBit) - 1; + val[1] |= upperVal; + + // Finally, rewrite values. + val[0] = byte_swap(val[0]); + val[1] = byte_swap(val[1]); + memcpy(LLVM_ASSUME_ALIGNED( + memory, (detail::PickAlignment::value)), + &val[0], sizeof(value_type) * 2); + } +} } // end namespace endian namespace detail { @@ -84,14 +183,49 @@ struct packed_endian_specific_integral { (void*)Value.buffer, newValue); } + packed_endian_specific_integral &operator+=(value_type newValue) { + *this = *this + newValue; + return *this; + } + + packed_endian_specific_integral &operator-=(value_type newValue) { + *this = *this - newValue; + return *this; + } + + packed_endian_specific_integral &operator|=(value_type newValue) { + *this = *this | newValue; + return *this; + } + + packed_endian_specific_integral &operator&=(value_type newValue) { + *this = *this & newValue; + return *this; + } + private: AlignedCharArray::value, sizeof(value_type)> Value; + +public: + struct ref { + explicit ref(void *Ptr) : Ptr(Ptr) {} + + operator value_type() const { + return endian::read(Ptr); + } + + void operator=(value_type NewValue) { + endian::write(Ptr, NewValue); + } + + private: + void *Ptr; + }; }; + } // end namespace detail -typedef detail::packed_endian_specific_integral - ulittle8_t; typedef detail::packed_endian_specific_integral ulittle16_t; typedef detail::packed_endian_specific_integral @@ -99,8 +233,6 @@ typedef detail::packed_endian_specific_integral typedef detail::packed_endian_specific_integral ulittle64_t; -typedef detail::packed_endian_specific_integral - little8_t; typedef detail::packed_endian_specific_integral little16_t; typedef detail::packed_endian_specific_integral @@ -108,8 +240,6 @@ typedef detail::packed_endian_specific_integral typedef detail::packed_endian_specific_integral little64_t; -typedef detail::packed_endian_specific_integral - aligned_ulittle8_t; typedef detail::packed_endian_specific_integral aligned_ulittle16_t; typedef detail::packed_endian_specific_integral @@ -117,8 +247,6 @@ typedef detail::packed_endian_specific_integral typedef detail::packed_endian_specific_integral aligned_ulittle64_t; -typedef detail::packed_endian_specific_integral - aligned_little8_t; typedef detail::packed_endian_specific_integral aligned_little16_t; typedef detail::packed_endian_specific_integral @@ -126,8 +254,6 @@ typedef detail::packed_endian_specific_integral typedef detail::packed_endian_specific_integral aligned_little64_t; -typedef detail::packed_endian_specific_integral - ubig8_t; typedef detail::packed_endian_specific_integral ubig16_t; typedef detail::packed_endian_specific_integral @@ -135,8 +261,6 @@ typedef detail::packed_endian_specific_integral typedef detail::packed_endian_specific_integral ubig64_t; -typedef detail::packed_endian_specific_integral - big8_t; typedef detail::packed_endian_specific_integral big16_t; typedef detail::packed_endian_specific_integral @@ -144,8 +268,6 @@ typedef detail::packed_endian_specific_integral typedef detail::packed_endian_specific_integral big64_t; -typedef detail::packed_endian_specific_integral - aligned_ubig8_t; typedef detail::packed_endian_specific_integral aligned_ubig16_t; typedef detail::packed_endian_specific_integral @@ -153,8 +275,6 @@ typedef detail::packed_endian_specific_integral typedef detail::packed_endian_specific_integral aligned_ubig64_t; -typedef detail::packed_endian_specific_integral - aligned_big8_t; typedef detail::packed_endian_specific_integral aligned_big16_t; typedef detail::packed_endian_specific_integral @@ -175,7 +295,51 @@ typedef detail::packed_endian_specific_integral unaligned_int32_t; typedef detail::packed_endian_specific_integral unaligned_int64_t; -} // end namespace llvm + +namespace endian { +template inline T read(const void *P) { + return *(const detail::packed_endian_specific_integral *)P; +} + +template inline uint16_t read16(const void *P) { + return read(P); +} +template inline uint32_t read32(const void *P) { + return read(P); +} +template inline uint64_t read64(const void *P) { + return read(P); +} + +inline uint16_t read16le(const void *P) { return read16(P); } +inline uint32_t read32le(const void *P) { return read32(P); } +inline uint64_t read64le(const void *P) { return read64(P); } +inline uint16_t read16be(const void *P) { return read16(P); } +inline uint32_t read32be(const void *P) { return read32(P); } +inline uint64_t read64be(const void *P) { return read64(P); } + +template inline void write(void *P, T V) { + *(detail::packed_endian_specific_integral *)P = V; +} + +template inline void write16(void *P, uint16_t V) { + write(P, V); +} +template inline void write32(void *P, uint32_t V) { + write(P, V); +} +template inline void write64(void *P, uint64_t V) { + write(P, V); +} + +inline void write16le(void *P, uint16_t V) { write16(P, V); } +inline void write32le(void *P, uint32_t V) { write32(P, V); } +inline void write64le(void *P, uint64_t V) { write64(P, V); } +inline void write16be(void *P, uint16_t V) { write16(P, V); } +inline void write32be(void *P, uint32_t V) { write32(P, V); } +inline void write64be(void *P, uint64_t V) { write64(P, V); } +} // end namespace endian } // end namespace support +} // end namespace llvm #endif