1//===- Endian.h - Utilities for IO with endian specific data ----*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file declares generic functions to read and write endian specific data. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef LLVM_SUPPORT_ENDIAN_H 15#define LLVM_SUPPORT_ENDIAN_H 16 17#include "llvm/Support/Host.h" 18#include "llvm/Support/SwapByteOrder.h" 19#include "llvm/Support/type_traits.h" 20 21namespace llvm { 22namespace support { 23 24enum endianness {big, little}; 25enum alignment {unaligned, aligned}; 26 27namespace detail { 28 29template<typename value_type, alignment align> 30struct alignment_access_helper; 31 32template<typename value_type> 33struct alignment_access_helper<value_type, aligned> 34{ 35 value_type val; 36}; 37 38// Provides unaligned loads and stores. 39#pragma pack(push) 40#pragma pack(1) 41template<typename value_type> 42struct alignment_access_helper<value_type, unaligned> 43{ 44 value_type val; 45}; 46#pragma pack(pop) 47 48} // end namespace detail 49 50namespace endian { 51 template<typename value_type, alignment align> 52 inline value_type read_le(const void *memory) { 53 value_type t = 54 reinterpret_cast<const detail::alignment_access_helper 55 <value_type, align> *>(memory)->val; 56 if (sys::isBigEndianHost()) 57 return sys::SwapByteOrder(t); 58 return t; 59 } 60 61 template<typename value_type, alignment align> 62 inline void write_le(void *memory, value_type value) { 63 if (sys::isBigEndianHost()) 64 value = sys::SwapByteOrder(value); 65 reinterpret_cast<detail::alignment_access_helper<value_type, align> *> 66 (memory)->val = value; 67 } 68 69 template<typename value_type, alignment align> 70 inline value_type read_be(const void *memory) { 71 value_type t = 72 reinterpret_cast<const detail::alignment_access_helper 73 <value_type, align> *>(memory)->val; 74 if (sys::isLittleEndianHost()) 75 return sys::SwapByteOrder(t); 76 return t; 77 } 78 79 template<typename value_type, alignment align> 80 inline void write_be(void *memory, value_type value) { 81 if (sys::isLittleEndianHost()) 82 value = sys::SwapByteOrder(value); 83 reinterpret_cast<detail::alignment_access_helper<value_type, align> *> 84 (memory)->val = value; 85 } 86} 87 88namespace detail { 89 90template<typename value_type, 91 endianness endian, 92 alignment align> 93class packed_endian_specific_integral; 94 95template<typename value_type> 96class packed_endian_specific_integral<value_type, little, unaligned> { 97public: 98 operator value_type() const { 99 return endian::read_le<value_type, unaligned>(Value); 100 } 101 void operator=(value_type newValue) { 102 endian::write_le<value_type, unaligned>((void *)&Value, newValue); 103 } 104private: 105 uint8_t Value[sizeof(value_type)]; 106}; 107 108template<typename value_type> 109class packed_endian_specific_integral<value_type, big, unaligned> { 110public: 111 operator value_type() const { 112 return endian::read_be<value_type, unaligned>(Value); 113 } 114 void operator=(value_type newValue) { 115 endian::write_be<value_type, unaligned>((void *)&Value, newValue); 116 } 117private: 118 uint8_t Value[sizeof(value_type)]; 119}; 120 121template<typename value_type> 122class packed_endian_specific_integral<value_type, little, aligned> { 123public: 124 operator value_type() const { 125 return endian::read_le<value_type, aligned>(&Value); 126 } 127 void operator=(value_type newValue) { 128 endian::write_le<value_type, aligned>((void *)&Value, newValue); 129 } 130private: 131 value_type Value; 132}; 133 134template<typename value_type> 135class packed_endian_specific_integral<value_type, big, aligned> { 136public: 137 operator value_type() const { 138 return endian::read_be<value_type, aligned>(&Value); 139 } 140 void operator=(value_type newValue) { 141 endian::write_be<value_type, aligned>((void *)&Value, newValue); 142 } 143private: 144 value_type Value; 145}; 146 147} // end namespace detail 148 149typedef detail::packed_endian_specific_integral 150 <uint8_t, little, unaligned> ulittle8_t; 151typedef detail::packed_endian_specific_integral 152 <uint16_t, little, unaligned> ulittle16_t; 153typedef detail::packed_endian_specific_integral 154 <uint32_t, little, unaligned> ulittle32_t; 155typedef detail::packed_endian_specific_integral 156 <uint64_t, little, unaligned> ulittle64_t; 157 158typedef detail::packed_endian_specific_integral 159 <int8_t, little, unaligned> little8_t; 160typedef detail::packed_endian_specific_integral 161 <int16_t, little, unaligned> little16_t; 162typedef detail::packed_endian_specific_integral 163 <int32_t, little, unaligned> little32_t; 164typedef detail::packed_endian_specific_integral 165 <int64_t, little, unaligned> little64_t; 166 167typedef detail::packed_endian_specific_integral 168 <uint8_t, little, aligned> aligned_ulittle8_t; 169typedef detail::packed_endian_specific_integral 170 <uint16_t, little, aligned> aligned_ulittle16_t; 171typedef detail::packed_endian_specific_integral 172 <uint32_t, little, aligned> aligned_ulittle32_t; 173typedef detail::packed_endian_specific_integral 174 <uint64_t, little, aligned> aligned_ulittle64_t; 175 176typedef detail::packed_endian_specific_integral 177 <int8_t, little, aligned> aligned_little8_t; 178typedef detail::packed_endian_specific_integral 179 <int16_t, little, aligned> aligned_little16_t; 180typedef detail::packed_endian_specific_integral 181 <int32_t, little, aligned> aligned_little32_t; 182typedef detail::packed_endian_specific_integral 183 <int64_t, little, aligned> aligned_little64_t; 184 185typedef detail::packed_endian_specific_integral 186 <uint8_t, big, unaligned> ubig8_t; 187typedef detail::packed_endian_specific_integral 188 <uint16_t, big, unaligned> ubig16_t; 189typedef detail::packed_endian_specific_integral 190 <uint32_t, big, unaligned> ubig32_t; 191typedef detail::packed_endian_specific_integral 192 <uint64_t, big, unaligned> ubig64_t; 193 194typedef detail::packed_endian_specific_integral 195 <int8_t, big, unaligned> big8_t; 196typedef detail::packed_endian_specific_integral 197 <int16_t, big, unaligned> big16_t; 198typedef detail::packed_endian_specific_integral 199 <int32_t, big, unaligned> big32_t; 200typedef detail::packed_endian_specific_integral 201 <int64_t, big, unaligned> big64_t; 202 203typedef detail::packed_endian_specific_integral 204 <uint8_t, big, aligned> aligned_ubig8_t; 205typedef detail::packed_endian_specific_integral 206 <uint16_t, big, aligned> aligned_ubig16_t; 207typedef detail::packed_endian_specific_integral 208 <uint32_t, big, aligned> aligned_ubig32_t; 209typedef detail::packed_endian_specific_integral 210 <uint64_t, big, aligned> aligned_ubig64_t; 211 212typedef detail::packed_endian_specific_integral 213 <int8_t, big, aligned> aligned_big8_t; 214typedef detail::packed_endian_specific_integral 215 <int16_t, big, aligned> aligned_big16_t; 216typedef detail::packed_endian_specific_integral 217 <int32_t, big, aligned> aligned_big32_t; 218typedef detail::packed_endian_specific_integral 219 <int64_t, big, aligned> aligned_big64_t; 220 221} // end namespace llvm 222} // end namespace support 223 224#endif 225