15e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer//===- Endian.h - Utilities for IO with endian specific data ----*- C++ -*-===//
25e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer//
35e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer//                     The LLVM Compiler Infrastructure
45e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer//
55e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer// This file is distributed under the University of Illinois Open Source
65e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer// License. See LICENSE.TXT for details.
75e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer//
85e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer//===----------------------------------------------------------------------===//
95e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer//
105e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer// This file declares generic functions to read and write endian specific data.
115e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer//
125e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer//===----------------------------------------------------------------------===//
135e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer
145e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer#ifndef LLVM_SUPPORT_ENDIAN_H
155e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer#define LLVM_SUPPORT_ENDIAN_H
165e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer
17c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer#include "llvm/Support/AlignOf.h"
181f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Host.h"
191f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/SwapByteOrder.h"
205e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer
215e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencernamespace llvm {
225e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencernamespace support {
23c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencerenum endianness {big, little, native};
245e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer
25c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer// These are named values for common alignments.
26c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencerenum {aligned = 0, unaligned = 1};
275e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer
285e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencernamespace detail {
29c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer  /// \brief ::value is either alignment, or alignof(T) if alignment is 0.
30c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer  template<class T, int alignment>
31c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer  struct PickAlignment {
32c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer    enum {value = alignment == 0 ? AlignOf<T>::Alignment : alignment};
33c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer  };
345e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer} // end namespace detail
355e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer
362e6048f8690105f7174e24ceba8e7c9f67009411Michael J. Spencernamespace endian {
3736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// Swap the bytes of value to match the given endianness.
38c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencertemplate<typename value_type, endianness endian>
39c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencerinline value_type byte_swap(value_type value) {
4021a01d1ea89dba97c4f9e1f9f41485729a4046bcRafael Espindola  if (endian != native && sys::IsBigEndianHost != (endian == big))
41c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    sys::swapByteOrder(value);
42c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer  return value;
43c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer}
442e6048f8690105f7174e24ceba8e7c9f67009411Michael J. Spencer
4536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// Read a value of a particular endianness from memory.
46c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencertemplate<typename value_type,
47c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer         endianness endian,
48c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer         std::size_t alignment>
49c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencerinline value_type read(const void *memory) {
50c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer  value_type ret;
51c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer
52c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer  memcpy(&ret,
53c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer         LLVM_ASSUME_ALIGNED(memory,
54c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer           (detail::PickAlignment<value_type, alignment>::value)),
55c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer         sizeof(value_type));
56c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer  return byte_swap<value_type, endian>(ret);
57c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer}
582e6048f8690105f7174e24ceba8e7c9f67009411Michael J. Spencer
5936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// Read a value of a particular endianness from a buffer, and increment the
6036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// buffer past that value.
614c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainartemplate<typename value_type, endianness endian, std::size_t alignment,
624c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar         typename CharT>
634c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarinline value_type readNext(const CharT *&memory) {
6436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  value_type ret = read<value_type, endian, alignment>(memory);
6536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  memory += sizeof(value_type);
6636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  return ret;
6736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}
6836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
6936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// Write a value to memory with a particular endianness.
70c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencertemplate<typename value_type,
71c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer         endianness endian,
72c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer         std::size_t alignment>
73c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencerinline void write(void *memory, value_type value) {
74c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer  value = byte_swap<value_type, endian>(value);
75c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer  memcpy(LLVM_ASSUME_ALIGNED(memory,
76c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer           (detail::PickAlignment<value_type, alignment>::value)),
77c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer         &value,
78c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer         sizeof(value_type));
792e6048f8690105f7174e24ceba8e7c9f67009411Michael J. Spencer}
80f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
81f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainartemplate <typename value_type>
82f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarusing make_unsigned_t = typename std::make_unsigned<value_type>::type;
83f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
84f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar/// Read a value of a particular endianness from memory, for a location
85f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar/// that starts at the given bit offset within the first byte.
86f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainartemplate <typename value_type, endianness endian, std::size_t alignment>
87f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline value_type readAtBitAlignment(const void *memory, uint64_t startBit) {
88f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  assert(startBit < 8);
89f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  if (startBit == 0)
90f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    return read<value_type, endian, alignment>(memory);
91f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  else {
92f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    // Read two values and compose the result from them.
93f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    value_type val[2];
94f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    memcpy(&val[0],
95f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar           LLVM_ASSUME_ALIGNED(
96f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar               memory, (detail::PickAlignment<value_type, alignment>::value)),
97f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar           sizeof(value_type) * 2);
98f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    val[0] = byte_swap<value_type, endian>(val[0]);
99f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    val[1] = byte_swap<value_type, endian>(val[1]);
100f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
101f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    // Shift bits from the lower value into place.
102f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    make_unsigned_t<value_type> lowerVal = val[0] >> startBit;
103f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    // Mask off upper bits after right shift in case of signed type.
104f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    make_unsigned_t<value_type> numBitsFirstVal =
105f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar        (sizeof(value_type) * 8) - startBit;
106f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    lowerVal &= ((make_unsigned_t<value_type>)1 << numBitsFirstVal) - 1;
107f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
108f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    // Get the bits from the upper value.
109f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    make_unsigned_t<value_type> upperVal =
110f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar        val[1] & (((make_unsigned_t<value_type>)1 << startBit) - 1);
111f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    // Shift them in to place.
112f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    upperVal <<= numBitsFirstVal;
113f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
114f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    return lowerVal | upperVal;
115f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  }
116f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar}
117f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
118f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar/// Write a value to memory with a particular endianness, for a location
119f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar/// that starts at the given bit offset within the first byte.
120f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainartemplate <typename value_type, endianness endian, std::size_t alignment>
121f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline void writeAtBitAlignment(void *memory, value_type value,
122f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar                                uint64_t startBit) {
123f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  assert(startBit < 8);
124f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  if (startBit == 0)
125f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    write<value_type, endian, alignment>(memory, value);
126f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  else {
127f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    // Read two values and shift the result into them.
128f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    value_type val[2];
129f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    memcpy(&val[0],
130f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar           LLVM_ASSUME_ALIGNED(
131f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar               memory, (detail::PickAlignment<value_type, alignment>::value)),
132f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar           sizeof(value_type) * 2);
133f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    val[0] = byte_swap<value_type, endian>(val[0]);
134f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    val[1] = byte_swap<value_type, endian>(val[1]);
135f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
136f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    // Mask off any existing bits in the upper part of the lower value that
137f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    // we want to replace.
138f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    val[0] &= ((make_unsigned_t<value_type>)1 << startBit) - 1;
139f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    make_unsigned_t<value_type> numBitsFirstVal =
140f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar        (sizeof(value_type) * 8) - startBit;
141f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    make_unsigned_t<value_type> lowerVal = value;
142f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    if (startBit > 0) {
143f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      // Mask off the upper bits in the new value that are not going to go into
144f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      // the lower value. This avoids a left shift of a negative value, which
145f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      // is undefined behavior.
146f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      lowerVal &= (((make_unsigned_t<value_type>)1 << numBitsFirstVal) - 1);
147f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      // Now shift the new bits into place
148f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      lowerVal <<= startBit;
149f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    }
150f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    val[0] |= lowerVal;
151f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
152f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    // Mask off any existing bits in the lower part of the upper value that
153f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    // we want to replace.
154f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    val[1] &= ~(((make_unsigned_t<value_type>)1 << startBit) - 1);
155f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    // Next shift the bits that go into the upper value into position.
156f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    make_unsigned_t<value_type> upperVal = value >> numBitsFirstVal;
157f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    // Mask off upper bits after right shift in case of signed type.
158f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    upperVal &= ((make_unsigned_t<value_type>)1 << startBit) - 1;
159f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    val[1] |= upperVal;
160f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
161f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    // Finally, rewrite values.
162f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    val[0] = byte_swap<value_type, endian>(val[0]);
163f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    val[1] = byte_swap<value_type, endian>(val[1]);
164f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    memcpy(LLVM_ASSUME_ALIGNED(
165f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar               memory, (detail::PickAlignment<value_type, alignment>::value)),
166f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar           &val[0], sizeof(value_type) * 2);
167f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  }
168f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar}
169c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer} // end namespace endian
1705e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer
1715e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencernamespace detail {
1725e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertemplate<typename value_type,
173fd7c230c85dbc9b1c5145319a0d5eaeb99f61176Michael J. Spencer         endianness endian,
174c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer         std::size_t alignment>
175c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencerstruct packed_endian_specific_integral {
176de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  packed_endian_specific_integral() = default;
177de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
178de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  explicit packed_endian_specific_integral(value_type val) { *this = val; }
179de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
1805e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer  operator value_type() const {
181c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer    return endian::read<value_type, endian, alignment>(
182c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer      (const void*)Value.buffer);
1835e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer  }
1845e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer
18524973c1063bfb7ac353732a4e8eb801830336c5fEli Bendersky  void operator=(value_type newValue) {
186c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer    endian::write<value_type, endian, alignment>(
187c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer      (void*)Value.buffer, newValue);
18824973c1063bfb7ac353732a4e8eb801830336c5fEli Bendersky  }
1895e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer
19037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  packed_endian_specific_integral &operator+=(value_type newValue) {
19137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    *this = *this + newValue;
19237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    return *this;
19337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  }
19437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
19537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  packed_endian_specific_integral &operator-=(value_type newValue) {
19637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    *this = *this - newValue;
19737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    return *this;
19837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  }
19937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
2006948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar  packed_endian_specific_integral &operator|=(value_type newValue) {
2016948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar    *this = *this | newValue;
2026948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar    return *this;
2036948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar  }
2046948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar
2056948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar  packed_endian_specific_integral &operator&=(value_type newValue) {
2066948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar    *this = *this & newValue;
2076948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar    return *this;
2086948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar  }
2096948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar
2105e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencerprivate:
211c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer  AlignedCharArray<PickAlignment<value_type, alignment>::value,
212c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer                   sizeof(value_type)> Value;
21337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
21437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinespublic:
21537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  struct ref {
21637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    explicit ref(void *Ptr) : Ptr(Ptr) {}
21737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
21837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    operator value_type() const {
21937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      return endian::read<value_type, endian, alignment>(Ptr);
22037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    }
22137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
22237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    void operator=(value_type NewValue) {
22337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      endian::write<value_type, endian, alignment>(Ptr, NewValue);
22437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    }
22537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
22637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  private:
22737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    void *Ptr;
22837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  };
2295e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer};
23037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
2315e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer} // end namespace detail
2325e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer
2335e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2345e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                  <uint16_t, little, unaligned> ulittle16_t;
2355e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2365e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                  <uint32_t, little, unaligned> ulittle32_t;
2375e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2385e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                  <uint64_t, little, unaligned> ulittle64_t;
2395e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer
2405e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2415e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                   <int16_t, little, unaligned> little16_t;
2425e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2435e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                   <int32_t, little, unaligned> little32_t;
2445e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2455e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                   <int64_t, little, unaligned> little64_t;
2465e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer
2475e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2485e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                    <uint16_t, little, aligned> aligned_ulittle16_t;
2495e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2505e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                    <uint32_t, little, aligned> aligned_ulittle32_t;
2515e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2525e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                    <uint64_t, little, aligned> aligned_ulittle64_t;
2535e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer
2545e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2555e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                     <int16_t, little, aligned> aligned_little16_t;
2565e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2575e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                     <int32_t, little, aligned> aligned_little32_t;
2585e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2595e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                     <int64_t, little, aligned> aligned_little64_t;
2605e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer
2615e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2625e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                  <uint16_t, big, unaligned>    ubig16_t;
2635e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2645e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                  <uint32_t, big, unaligned>    ubig32_t;
2655e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2665e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                  <uint64_t, big, unaligned>    ubig64_t;
2675e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer
2685e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2695e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                   <int16_t, big, unaligned>    big16_t;
2705e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2715e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                   <int32_t, big, unaligned>    big32_t;
2725e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2735e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                   <int64_t, big, unaligned>    big64_t;
2745e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer
2755e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2765e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                    <uint16_t, big, aligned>    aligned_ubig16_t;
2775e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2785e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                    <uint32_t, big, aligned>    aligned_ubig32_t;
2795e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2805e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                    <uint64_t, big, aligned>    aligned_ubig64_t;
2815e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer
2825e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2835e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                     <int16_t, big, aligned>    aligned_big16_t;
2845e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2855e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                     <int32_t, big, aligned>    aligned_big32_t;
2865e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencertypedef detail::packed_endian_specific_integral
2875e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer                     <int64_t, big, aligned>    aligned_big64_t;
2885e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer
289c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencertypedef detail::packed_endian_specific_integral
290c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer                  <uint16_t, native, unaligned> unaligned_uint16_t;
291c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencertypedef detail::packed_endian_specific_integral
292c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer                  <uint32_t, native, unaligned> unaligned_uint32_t;
293c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencertypedef detail::packed_endian_specific_integral
294c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer                  <uint64_t, native, unaligned> unaligned_uint64_t;
295c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer
296c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencertypedef detail::packed_endian_specific_integral
297c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer                   <int16_t, native, unaligned> unaligned_int16_t;
298c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencertypedef detail::packed_endian_specific_integral
299c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer                   <int32_t, native, unaligned> unaligned_int32_t;
300c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencertypedef detail::packed_endian_specific_integral
301c8b18df9a79ddb759d6a563dd7ebd90b85ae4918Michael J. Spencer                   <int64_t, native, unaligned> unaligned_int64_t;
3024c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar
3034c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainarnamespace endian {
304f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainartemplate <typename T, endianness E> inline T read(const void *P) {
305f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  return *(const detail::packed_endian_specific_integral<T, E, unaligned> *)P;
306f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar}
307f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
308f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainartemplate <endianness E> inline uint16_t read16(const void *P) {
309f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  return read<uint16_t, E>(P);
310f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar}
311f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainartemplate <endianness E> inline uint32_t read32(const void *P) {
312f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  return read<uint32_t, E>(P);
313f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar}
314f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainartemplate <endianness E> inline uint64_t read64(const void *P) {
315f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  return read<uint64_t, E>(P);
316f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar}
317f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
318f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline uint16_t read16le(const void *P) { return read16<little>(P); }
319f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline uint32_t read32le(const void *P) { return read32<little>(P); }
320f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline uint64_t read64le(const void *P) { return read64<little>(P); }
321f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline uint16_t read16be(const void *P) { return read16<big>(P); }
322f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline uint32_t read32be(const void *P) { return read32<big>(P); }
323f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline uint64_t read64be(const void *P) { return read64<big>(P); }
324f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
325f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainartemplate <typename T, endianness E> inline void write(void *P, T V) {
326f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  *(detail::packed_endian_specific_integral<T, E, unaligned> *)P = V;
327f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar}
328f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
329f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainartemplate <endianness E> inline void write16(void *P, uint16_t V) {
330f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  write<uint16_t, E>(P, V);
331f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar}
332f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainartemplate <endianness E> inline void write32(void *P, uint32_t V) {
333f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  write<uint32_t, E>(P, V);
334f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar}
335f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainartemplate <endianness E> inline void write64(void *P, uint64_t V) {
336f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  write<uint64_t, E>(P, V);
337f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar}
338f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
339f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline void write16le(void *P, uint16_t V) { write16<little>(P, V); }
340f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline void write32le(void *P, uint32_t V) { write32<little>(P, V); }
341f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline void write64le(void *P, uint64_t V) { write64<little>(P, V); }
342f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline void write16be(void *P, uint16_t V) { write16<big>(P, V); }
343f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline void write32be(void *P, uint32_t V) { write32<big>(P, V); }
344f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainarinline void write64be(void *P, uint64_t V) { write64<big>(P, V); }
3454c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar} // end namespace endian
3465e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer} // end namespace support
3474c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar} // end namespace llvm
3485e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer
3495e0b2bf657dd8b6b3bb58439e6cb293f3116687fMichael J. Spencer#endif
350