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