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