c98e2dc66cc16671aba39c973e571844c2d89796
[oota-llvm.git] / include / llvm / Support / Endian.h
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/Config/config.h"
18 #include "llvm/System/SwapByteOrder.h"
19 #include "llvm/Support/type_traits.h"
20
21 namespace llvm {
22 namespace support {
23
24 enum endianness {big, little};
25 enum alignment {unaligned, aligned};
26
27 template<typename value_type, int host, int target>
28 static typename enable_if_c<host == target, value_type>::type
29 SwapByteOrderIfDifferent(value_type value) {
30   // Target endianess is the same as the host. Just pass the value through.
31   return value;
32 }
33
34 template<typename value_type, int host, int target>
35 static typename enable_if_c<host != target, value_type>::type
36 SwapByteOrderIfDifferent(value_type value) {
37     return sys::SwapByteOrder<value_type>(value);
38 }
39
40 namespace detail {
41
42 template<typename value_type, alignment align>
43 struct alignment_access_helper;
44
45 template<typename value_type>
46 struct alignment_access_helper<value_type, aligned>
47 {
48   value_type val;
49 };
50
51 // Provides unaligned loads and stores.
52 #pragma pack(push)
53 #pragma pack(1)
54 template<typename value_type>
55 struct alignment_access_helper<value_type, unaligned>
56 {
57   value_type val;
58 };
59 #pragma pack(pop)
60
61 } // end namespace detail
62
63 #if defined(LLVM_IS_HOST_BIG_ENDIAN) \
64  || defined(_BIG_ENDIAN) || defined(__BIG_ENDIAN__)
65 static const endianness host_endianness = big;
66 #else
67 static const endianness host_endianness = little;
68 #endif
69
70 struct endian {
71   template<typename value_type, alignment align>
72   static value_type read_le(const void *memory) {
73     return SwapByteOrderIfDifferent<value_type, host_endianness, little>(
74       reinterpret_cast<const detail::alignment_access_helper
75         <value_type, align> *>(memory)->val);
76   }
77
78   template<typename value_type, alignment align>
79   static void write_le(void *memory, value_type value) {
80     reinterpret_cast<detail::alignment_access_helper<value_type, align> *>
81       (memory)->val =
82         SwapByteOrderIfDifferent< value_type
83                                 , host_endianness
84                                 , little>(value);
85   }
86
87   template<typename value_type, alignment align>
88   static value_type read_be(const void *memory) {
89     return SwapByteOrderIfDifferent<value_type, host_endianness, big>(
90       reinterpret_cast<const detail::alignment_access_helper
91         <value_type, align> *>(memory)->val);
92   }
93
94   template<typename value_type, alignment align>
95   static void write_be(void *memory, value_type value) {
96     reinterpret_cast<detail::alignment_access_helper
97       <value_type, align> *>(memory)->val =
98         SwapByteOrderIfDifferent< value_type
99                                 , host_endianness
100                                 , big>(value);
101   }
102 };
103
104 namespace detail {
105
106 template<typename value_type,
107          endianness target_endianness,
108          alignment target_alignment>
109 class packed_endian_specific_integral;
110
111 template<typename value_type>
112 class packed_endian_specific_integral<value_type, little, unaligned> {
113 public:
114   operator value_type() const {
115     return endian::read_le<value_type, unaligned>(Value);
116   }
117 private:
118   uint8_t Value[sizeof(value_type)];
119 };
120
121 template<typename value_type>
122 class packed_endian_specific_integral<value_type, big, unaligned> {
123 public:
124   operator value_type() const {
125     return endian::read_be<value_type, unaligned>(Value);
126   }
127 private:
128   uint8_t Value[sizeof(value_type)];
129 };
130
131 template<typename value_type>
132 class packed_endian_specific_integral<value_type, little, aligned> {
133 public:
134   operator value_type() const {
135     return endian::read_le<value_type, aligned>(&Value);
136   }
137 private:
138   value_type Value;
139 };
140
141 template<typename value_type>
142 class packed_endian_specific_integral<value_type, big, aligned> {
143 public:
144   operator value_type() const {
145     return endian::read_be<value_type, aligned>(&Value);
146   }
147 private:
148   value_type Value;
149 };
150
151 } // end namespace detail
152
153 typedef detail::packed_endian_specific_integral
154                   <uint8_t, little, unaligned>  ulittle8_t;
155 typedef detail::packed_endian_specific_integral
156                   <uint16_t, little, unaligned> ulittle16_t;
157 typedef detail::packed_endian_specific_integral
158                   <uint32_t, little, unaligned> ulittle32_t;
159 typedef detail::packed_endian_specific_integral
160                   <uint64_t, little, unaligned> ulittle64_t;
161
162 typedef detail::packed_endian_specific_integral
163                    <int8_t, little, unaligned>  little8_t;
164 typedef detail::packed_endian_specific_integral
165                    <int16_t, little, unaligned> little16_t;
166 typedef detail::packed_endian_specific_integral
167                    <int32_t, little, unaligned> little32_t;
168 typedef detail::packed_endian_specific_integral
169                    <int64_t, little, unaligned> little64_t;
170
171 typedef detail::packed_endian_specific_integral
172                     <uint8_t, little, aligned>  aligned_ulittle8_t;
173 typedef detail::packed_endian_specific_integral
174                     <uint16_t, little, aligned> aligned_ulittle16_t;
175 typedef detail::packed_endian_specific_integral
176                     <uint32_t, little, aligned> aligned_ulittle32_t;
177 typedef detail::packed_endian_specific_integral
178                     <uint64_t, little, aligned> aligned_ulittle64_t;
179
180 typedef detail::packed_endian_specific_integral
181                      <int8_t, little, aligned>  aligned_little8_t;
182 typedef detail::packed_endian_specific_integral
183                      <int16_t, little, aligned> aligned_little16_t;
184 typedef detail::packed_endian_specific_integral
185                      <int32_t, little, aligned> aligned_little32_t;
186 typedef detail::packed_endian_specific_integral
187                      <int64_t, little, aligned> aligned_little64_t;
188
189 typedef detail::packed_endian_specific_integral
190                   <uint8_t, big, unaligned>     ubig8_t;
191 typedef detail::packed_endian_specific_integral
192                   <uint16_t, big, unaligned>    ubig16_t;
193 typedef detail::packed_endian_specific_integral
194                   <uint32_t, big, unaligned>    ubig32_t;
195 typedef detail::packed_endian_specific_integral
196                   <uint64_t, big, unaligned>    ubig64_t;
197
198 typedef detail::packed_endian_specific_integral
199                    <int8_t, big, unaligned>     big8_t;
200 typedef detail::packed_endian_specific_integral
201                    <int16_t, big, unaligned>    big16_t;
202 typedef detail::packed_endian_specific_integral
203                    <int32_t, big, unaligned>    big32_t;
204 typedef detail::packed_endian_specific_integral
205                    <int64_t, big, unaligned>    big64_t;
206
207 typedef detail::packed_endian_specific_integral
208                     <uint8_t, big, aligned>     aligned_ubig8_t;
209 typedef detail::packed_endian_specific_integral
210                     <uint16_t, big, aligned>    aligned_ubig16_t;
211 typedef detail::packed_endian_specific_integral
212                     <uint32_t, big, aligned>    aligned_ubig32_t;
213 typedef detail::packed_endian_specific_integral
214                     <uint64_t, big, aligned>    aligned_ubig64_t;
215
216 typedef detail::packed_endian_specific_integral
217                      <int8_t, big, aligned>     aligned_big8_t;
218 typedef detail::packed_endian_specific_integral
219                      <int16_t, big, aligned>    aligned_big16_t;
220 typedef detail::packed_endian_specific_integral
221                      <int32_t, big, aligned>    aligned_big32_t;
222 typedef detail::packed_endian_specific_integral
223                      <int64_t, big, aligned>    aligned_big64_t;
224
225 } // end namespace llvm
226 } // end namespace support
227
228 #endif