1218885Sdim//===- Endian.h - Utilities for IO with endian specific data ----*- C++ -*-===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10218885Sdim// This file declares generic functions to read and write endian specific data. 11218885Sdim// 12218885Sdim//===----------------------------------------------------------------------===// 13218885Sdim 14218885Sdim#ifndef LLVM_SUPPORT_ENDIAN_H 15218885Sdim#define LLVM_SUPPORT_ENDIAN_H 16218885Sdim 17249423Sdim#include "llvm/Support/AlignOf.h" 18218885Sdim#include "llvm/Support/Host.h" 19218885Sdim#include "llvm/Support/SwapByteOrder.h" 20218885Sdim#include "llvm/Support/type_traits.h" 21218885Sdim 22218885Sdimnamespace llvm { 23218885Sdimnamespace support { 24249423Sdimenum endianness {big, little, native}; 25218885Sdim 26249423Sdim// These are named values for common alignments. 27249423Sdimenum {aligned = 0, unaligned = 1}; 28218885Sdim 29218885Sdimnamespace detail { 30249423Sdim /// \brief ::value is either alignment, or alignof(T) if alignment is 0. 31249423Sdim template<class T, int alignment> 32249423Sdim struct PickAlignment { 33249423Sdim enum {value = alignment == 0 ? AlignOf<T>::Alignment : alignment}; 34249423Sdim }; 35218885Sdim} // end namespace detail 36218885Sdim 37218885Sdimnamespace endian { 38249423Sdimtemplate<typename value_type, endianness endian> 39249423Sdiminline value_type byte_swap(value_type value) { 40251662Sdim if (endian != native && sys::IsBigEndianHost != (endian == big)) 41249423Sdim return sys::SwapByteOrder(value); 42249423Sdim return value; 43249423Sdim} 44218885Sdim 45249423Sdimtemplate<typename value_type, 46249423Sdim endianness endian, 47249423Sdim std::size_t alignment> 48249423Sdiminline value_type read(const void *memory) { 49249423Sdim value_type ret; 50218885Sdim 51249423Sdim memcpy(&ret, 52249423Sdim LLVM_ASSUME_ALIGNED(memory, 53249423Sdim (detail::PickAlignment<value_type, alignment>::value)), 54249423Sdim sizeof(value_type)); 55249423Sdim return byte_swap<value_type, endian>(ret); 56249423Sdim} 57218885Sdim 58249423Sdimtemplate<typename value_type, 59249423Sdim endianness endian, 60249423Sdim std::size_t alignment> 61249423Sdiminline void write(void *memory, value_type value) { 62249423Sdim value = byte_swap<value_type, endian>(value); 63249423Sdim memcpy(LLVM_ASSUME_ALIGNED(memory, 64249423Sdim (detail::PickAlignment<value_type, alignment>::value)), 65249423Sdim &value, 66249423Sdim sizeof(value_type)); 67218885Sdim} 68249423Sdim} // end namespace endian 69218885Sdim 70218885Sdimnamespace detail { 71218885Sdimtemplate<typename value_type, 72218885Sdim endianness endian, 73249423Sdim std::size_t alignment> 74249423Sdimstruct packed_endian_specific_integral { 75218885Sdim operator value_type() const { 76249423Sdim return endian::read<value_type, endian, alignment>( 77249423Sdim (const void*)Value.buffer); 78218885Sdim } 79218885Sdim 80234353Sdim void operator=(value_type newValue) { 81249423Sdim endian::write<value_type, endian, alignment>( 82249423Sdim (void*)Value.buffer, newValue); 83234353Sdim } 84218885Sdim 85218885Sdimprivate: 86249423Sdim AlignedCharArray<PickAlignment<value_type, alignment>::value, 87249423Sdim sizeof(value_type)> Value; 88218885Sdim}; 89218885Sdim} // end namespace detail 90218885Sdim 91218885Sdimtypedef detail::packed_endian_specific_integral 92218885Sdim <uint8_t, little, unaligned> ulittle8_t; 93218885Sdimtypedef detail::packed_endian_specific_integral 94218885Sdim <uint16_t, little, unaligned> ulittle16_t; 95218885Sdimtypedef detail::packed_endian_specific_integral 96218885Sdim <uint32_t, little, unaligned> ulittle32_t; 97218885Sdimtypedef detail::packed_endian_specific_integral 98218885Sdim <uint64_t, little, unaligned> ulittle64_t; 99218885Sdim 100218885Sdimtypedef detail::packed_endian_specific_integral 101218885Sdim <int8_t, little, unaligned> little8_t; 102218885Sdimtypedef detail::packed_endian_specific_integral 103218885Sdim <int16_t, little, unaligned> little16_t; 104218885Sdimtypedef detail::packed_endian_specific_integral 105218885Sdim <int32_t, little, unaligned> little32_t; 106218885Sdimtypedef detail::packed_endian_specific_integral 107218885Sdim <int64_t, little, unaligned> little64_t; 108218885Sdim 109218885Sdimtypedef detail::packed_endian_specific_integral 110218885Sdim <uint8_t, little, aligned> aligned_ulittle8_t; 111218885Sdimtypedef detail::packed_endian_specific_integral 112218885Sdim <uint16_t, little, aligned> aligned_ulittle16_t; 113218885Sdimtypedef detail::packed_endian_specific_integral 114218885Sdim <uint32_t, little, aligned> aligned_ulittle32_t; 115218885Sdimtypedef detail::packed_endian_specific_integral 116218885Sdim <uint64_t, little, aligned> aligned_ulittle64_t; 117218885Sdim 118218885Sdimtypedef detail::packed_endian_specific_integral 119218885Sdim <int8_t, little, aligned> aligned_little8_t; 120218885Sdimtypedef detail::packed_endian_specific_integral 121218885Sdim <int16_t, little, aligned> aligned_little16_t; 122218885Sdimtypedef detail::packed_endian_specific_integral 123218885Sdim <int32_t, little, aligned> aligned_little32_t; 124218885Sdimtypedef detail::packed_endian_specific_integral 125218885Sdim <int64_t, little, aligned> aligned_little64_t; 126218885Sdim 127218885Sdimtypedef detail::packed_endian_specific_integral 128218885Sdim <uint8_t, big, unaligned> ubig8_t; 129218885Sdimtypedef detail::packed_endian_specific_integral 130218885Sdim <uint16_t, big, unaligned> ubig16_t; 131218885Sdimtypedef detail::packed_endian_specific_integral 132218885Sdim <uint32_t, big, unaligned> ubig32_t; 133218885Sdimtypedef detail::packed_endian_specific_integral 134218885Sdim <uint64_t, big, unaligned> ubig64_t; 135218885Sdim 136218885Sdimtypedef detail::packed_endian_specific_integral 137218885Sdim <int8_t, big, unaligned> big8_t; 138218885Sdimtypedef detail::packed_endian_specific_integral 139218885Sdim <int16_t, big, unaligned> big16_t; 140218885Sdimtypedef detail::packed_endian_specific_integral 141218885Sdim <int32_t, big, unaligned> big32_t; 142218885Sdimtypedef detail::packed_endian_specific_integral 143218885Sdim <int64_t, big, unaligned> big64_t; 144218885Sdim 145218885Sdimtypedef detail::packed_endian_specific_integral 146218885Sdim <uint8_t, big, aligned> aligned_ubig8_t; 147218885Sdimtypedef detail::packed_endian_specific_integral 148218885Sdim <uint16_t, big, aligned> aligned_ubig16_t; 149218885Sdimtypedef detail::packed_endian_specific_integral 150218885Sdim <uint32_t, big, aligned> aligned_ubig32_t; 151218885Sdimtypedef detail::packed_endian_specific_integral 152218885Sdim <uint64_t, big, aligned> aligned_ubig64_t; 153218885Sdim 154218885Sdimtypedef detail::packed_endian_specific_integral 155218885Sdim <int8_t, big, aligned> aligned_big8_t; 156218885Sdimtypedef detail::packed_endian_specific_integral 157218885Sdim <int16_t, big, aligned> aligned_big16_t; 158218885Sdimtypedef detail::packed_endian_specific_integral 159218885Sdim <int32_t, big, aligned> aligned_big32_t; 160218885Sdimtypedef detail::packed_endian_specific_integral 161218885Sdim <int64_t, big, aligned> aligned_big64_t; 162218885Sdim 163249423Sdimtypedef detail::packed_endian_specific_integral 164249423Sdim <uint16_t, native, unaligned> unaligned_uint16_t; 165249423Sdimtypedef detail::packed_endian_specific_integral 166249423Sdim <uint32_t, native, unaligned> unaligned_uint32_t; 167249423Sdimtypedef detail::packed_endian_specific_integral 168249423Sdim <uint64_t, native, unaligned> unaligned_uint64_t; 169249423Sdim 170249423Sdimtypedef detail::packed_endian_specific_integral 171249423Sdim <int16_t, native, unaligned> unaligned_int16_t; 172249423Sdimtypedef detail::packed_endian_specific_integral 173249423Sdim <int32_t, native, unaligned> unaligned_int32_t; 174249423Sdimtypedef detail::packed_endian_specific_integral 175249423Sdim <int64_t, native, unaligned> unaligned_int64_t; 176218885Sdim} // end namespace llvm 177218885Sdim} // end namespace support 178218885Sdim 179218885Sdim#endif 180