Endian.h revision 218885
1221828Sgrehan//===- Endian.h - Utilities for IO with endian specific data ----*- C++ -*-===//
2221828Sgrehan//
3221828Sgrehan//                     The LLVM Compiler Infrastructure
4221828Sgrehan//
5221828Sgrehan// This file is distributed under the University of Illinois Open Source
6221828Sgrehan// License. See LICENSE.TXT for details.
7221828Sgrehan//
8221828Sgrehan//===----------------------------------------------------------------------===//
9221828Sgrehan//
10221828Sgrehan// This file declares generic functions to read and write endian specific data.
11221828Sgrehan//
12221828Sgrehan//===----------------------------------------------------------------------===//
13221828Sgrehan
14221828Sgrehan#ifndef LLVM_SUPPORT_ENDIAN_H
15221828Sgrehan#define LLVM_SUPPORT_ENDIAN_H
16221828Sgrehan
17221828Sgrehan#include "llvm/Config/config.h"
18221828Sgrehan#include "llvm/Support/Host.h"
19221828Sgrehan#include "llvm/Support/SwapByteOrder.h"
20221828Sgrehan#include "llvm/Support/type_traits.h"
21221828Sgrehan
22221828Sgrehannamespace llvm {
23221828Sgrehannamespace support {
24221828Sgrehan
25221828Sgrehanenum endianness {big, little};
26221828Sgrehanenum alignment {unaligned, aligned};
27221828Sgrehan
28221828Sgrehannamespace detail {
29221828Sgrehan
30221828Sgrehantemplate<typename value_type, alignment align>
31221828Sgrehanstruct alignment_access_helper;
32221828Sgrehan
33221828Sgrehantemplate<typename value_type>
34256072Sneelstruct alignment_access_helper<value_type, aligned>
35256072Sneel{
36221828Sgrehan  value_type val;
37221828Sgrehan};
38221828Sgrehan
39222112Sneel// Provides unaligned loads and stores.
40222112Sneel#pragma pack(push)
41222112Sneel#pragma pack(1)
42221828Sgrehantemplate<typename value_type>
43221828Sgrehanstruct alignment_access_helper<value_type, unaligned>
44221828Sgrehan{
45221828Sgrehan  value_type val;
46221828Sgrehan};
47221828Sgrehan#pragma pack(pop)
48221828Sgrehan
49221828Sgrehan} // end namespace detail
50221828Sgrehan
51221828Sgrehannamespace endian {
52221828Sgrehan  template<typename value_type, alignment align>
53221828Sgrehan  static value_type read_le(const void *memory) {
54221828Sgrehan    value_type t =
55221828Sgrehan      reinterpret_cast<const detail::alignment_access_helper
56221828Sgrehan        <value_type, align> *>(memory)->val;
57221828Sgrehan    if (sys::isBigEndianHost())
58221828Sgrehan      return sys::SwapByteOrder(t);
59221828Sgrehan    return t;
60221828Sgrehan  }
61221828Sgrehan
62221828Sgrehan  template<typename value_type, alignment align>
63221828Sgrehan  static void write_le(void *memory, value_type value) {
64221828Sgrehan    if (sys::isBigEndianHost())
65221828Sgrehan      value = sys::SwapByteOrder(value);
66221828Sgrehan    reinterpret_cast<detail::alignment_access_helper<value_type, align> *>
67221828Sgrehan      (memory)->val = value;
68221828Sgrehan  }
69221828Sgrehan
70221828Sgrehan  template<typename value_type, alignment align>
71222112Sneel  static value_type read_be(const void *memory) {
72221828Sgrehan    value_type t =
73256072Sneel      reinterpret_cast<const detail::alignment_access_helper
74256072Sneel        <value_type, align> *>(memory)->val;
75256072Sneel    if (sys::isLittleEndianHost())
76256072Sneel      return sys::SwapByteOrder(t);
77256072Sneel    return t;
78256072Sneel  }
79256072Sneel
80256072Sneel  template<typename value_type, alignment align>
81256072Sneel  static void write_be(void *memory, value_type value) {
82221828Sgrehan    if (sys::isLittleEndianHost())
83221828Sgrehan      value = sys::SwapByteOrder(value);
84221828Sgrehan    reinterpret_cast<detail::alignment_access_helper<value_type, align> *>
85221828Sgrehan      (memory)->val = value;
86221828Sgrehan  }
87256645Sneel}
88221828Sgrehan
89221828Sgrehannamespace detail {
90221828Sgrehan
91221828Sgrehantemplate<typename value_type,
92221828Sgrehan         endianness endian,
93221828Sgrehan         alignment  align>
94221828Sgrehanclass packed_endian_specific_integral;
95221828Sgrehan
96221828Sgrehantemplate<typename value_type>
97221828Sgrehanclass packed_endian_specific_integral<value_type, little, unaligned> {
98221828Sgrehanpublic:
99221828Sgrehan  operator value_type() const {
100221828Sgrehan    return endian::read_le<value_type, unaligned>(Value);
101221828Sgrehan  }
102221828Sgrehanprivate:
103256072Sneel  uint8_t Value[sizeof(value_type)];
104221828Sgrehan};
105221828Sgrehan
106221828Sgrehantemplate<typename value_type>
107221828Sgrehanclass packed_endian_specific_integral<value_type, big, unaligned> {
108221828Sgrehanpublic:
109221828Sgrehan  operator value_type() const {
110221828Sgrehan    return endian::read_be<value_type, unaligned>(Value);
111221828Sgrehan  }
112221828Sgrehanprivate:
113221828Sgrehan  uint8_t Value[sizeof(value_type)];
114241921Sneel};
115256072Sneel
116221828Sgrehantemplate<typename value_type>
117221828Sgrehanclass packed_endian_specific_integral<value_type, little, aligned> {
118221828Sgrehanpublic:
119221828Sgrehan  operator value_type() const {
120221828Sgrehan    return endian::read_le<value_type, aligned>(&Value);
121221828Sgrehan  }
122241921Sneelprivate:
123256072Sneel  value_type Value;
124221828Sgrehan};
125221828Sgrehan
126221828Sgrehantemplate<typename value_type>
127221828Sgrehanclass packed_endian_specific_integral<value_type, big, aligned> {
128221828Sgrehanpublic:
129221828Sgrehan  operator value_type() const {
130221828Sgrehan    return endian::read_be<value_type, aligned>(&Value);
131221828Sgrehan  }
132221828Sgrehanprivate:
133221828Sgrehan  value_type Value;
134};
135
136} // end namespace detail
137
138typedef detail::packed_endian_specific_integral
139                  <uint8_t, little, unaligned>  ulittle8_t;
140typedef detail::packed_endian_specific_integral
141                  <uint16_t, little, unaligned> ulittle16_t;
142typedef detail::packed_endian_specific_integral
143                  <uint32_t, little, unaligned> ulittle32_t;
144typedef detail::packed_endian_specific_integral
145                  <uint64_t, little, unaligned> ulittle64_t;
146
147typedef detail::packed_endian_specific_integral
148                   <int8_t, little, unaligned>  little8_t;
149typedef detail::packed_endian_specific_integral
150                   <int16_t, little, unaligned> little16_t;
151typedef detail::packed_endian_specific_integral
152                   <int32_t, little, unaligned> little32_t;
153typedef detail::packed_endian_specific_integral
154                   <int64_t, little, unaligned> little64_t;
155
156typedef detail::packed_endian_specific_integral
157                    <uint8_t, little, aligned>  aligned_ulittle8_t;
158typedef detail::packed_endian_specific_integral
159                    <uint16_t, little, aligned> aligned_ulittle16_t;
160typedef detail::packed_endian_specific_integral
161                    <uint32_t, little, aligned> aligned_ulittle32_t;
162typedef detail::packed_endian_specific_integral
163                    <uint64_t, little, aligned> aligned_ulittle64_t;
164
165typedef detail::packed_endian_specific_integral
166                     <int8_t, little, aligned>  aligned_little8_t;
167typedef detail::packed_endian_specific_integral
168                     <int16_t, little, aligned> aligned_little16_t;
169typedef detail::packed_endian_specific_integral
170                     <int32_t, little, aligned> aligned_little32_t;
171typedef detail::packed_endian_specific_integral
172                     <int64_t, little, aligned> aligned_little64_t;
173
174typedef detail::packed_endian_specific_integral
175                  <uint8_t, big, unaligned>     ubig8_t;
176typedef detail::packed_endian_specific_integral
177                  <uint16_t, big, unaligned>    ubig16_t;
178typedef detail::packed_endian_specific_integral
179                  <uint32_t, big, unaligned>    ubig32_t;
180typedef detail::packed_endian_specific_integral
181                  <uint64_t, big, unaligned>    ubig64_t;
182
183typedef detail::packed_endian_specific_integral
184                   <int8_t, big, unaligned>     big8_t;
185typedef detail::packed_endian_specific_integral
186                   <int16_t, big, unaligned>    big16_t;
187typedef detail::packed_endian_specific_integral
188                   <int32_t, big, unaligned>    big32_t;
189typedef detail::packed_endian_specific_integral
190                   <int64_t, big, unaligned>    big64_t;
191
192typedef detail::packed_endian_specific_integral
193                    <uint8_t, big, aligned>     aligned_ubig8_t;
194typedef detail::packed_endian_specific_integral
195                    <uint16_t, big, aligned>    aligned_ubig16_t;
196typedef detail::packed_endian_specific_integral
197                    <uint32_t, big, aligned>    aligned_ubig32_t;
198typedef detail::packed_endian_specific_integral
199                    <uint64_t, big, aligned>    aligned_ubig64_t;
200
201typedef detail::packed_endian_specific_integral
202                     <int8_t, big, aligned>     aligned_big8_t;
203typedef detail::packed_endian_specific_integral
204                     <int16_t, big, aligned>    aligned_big16_t;
205typedef detail::packed_endian_specific_integral
206                     <int32_t, big, aligned>    aligned_big32_t;
207typedef 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
214