1//===- SizeTraits.h -------------------------------------------------------===//
2//
3//                     The MCLinker Project
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#ifndef MCLD_ADT_SIZETRAITS_H_
10#define MCLD_ADT_SIZETRAITS_H_
11
12#include <llvm/Support/DataTypes.h>
13#include <llvm/Support/ELF.h>
14
15namespace mcld {
16
17template <size_t SIZE>
18class SizeTraits;
19
20template <>
21class SizeTraits<32> {
22 public:
23  typedef uint32_t Address;
24  typedef uint32_t Offset;
25  typedef uint32_t Word;
26  typedef int32_t SWord;
27};
28
29template <>
30class SizeTraits<64> {
31 public:
32  typedef uint64_t Address;
33  typedef uint64_t Offset;
34  typedef uint64_t Word;
35  typedef int64_t SWord;
36};
37
38// FIXME: move this to mcld internal ELF header file?
39template <size_t SIZE>
40class ELFSizeTraits;
41
42template <>
43class ELFSizeTraits<32> {
44 public:
45  typedef llvm::ELF::Elf32_Addr Addr;  // Program address
46  typedef llvm::ELF::Elf32_Off Off;    // File offset
47  typedef llvm::ELF::Elf32_Half Half;
48  typedef llvm::ELF::Elf32_Word Word;
49  typedef llvm::ELF::Elf32_Sword Sword;
50
51  typedef llvm::ELF::Elf32_Ehdr Ehdr;
52  typedef llvm::ELF::Elf32_Shdr Shdr;
53  typedef llvm::ELF::Elf32_Sym Sym;
54  typedef llvm::ELF::Elf32_Rel Rel;
55  typedef llvm::ELF::Elf32_Rela Rela;
56  typedef llvm::ELF::Elf32_Phdr Phdr;
57  typedef llvm::ELF::Elf32_Dyn Dyn;
58};
59
60template <>
61class ELFSizeTraits<64> {
62 public:
63  typedef llvm::ELF::Elf64_Addr Addr;
64  typedef llvm::ELF::Elf64_Off Off;
65  typedef llvm::ELF::Elf64_Half Half;
66  typedef llvm::ELF::Elf64_Word Word;
67  typedef llvm::ELF::Elf64_Sword Sword;
68  typedef llvm::ELF::Elf64_Xword Xword;
69  typedef llvm::ELF::Elf64_Sxword Sxword;
70
71  typedef llvm::ELF::Elf64_Ehdr Ehdr;
72  typedef llvm::ELF::Elf64_Shdr Shdr;
73  typedef llvm::ELF::Elf64_Sym Sym;
74  typedef llvm::ELF::Elf64_Rel Rel;
75  typedef llvm::ELF::Elf64_Rela Rela;
76  typedef llvm::ELF::Elf64_Phdr Phdr;
77  typedef llvm::ELF::Elf64_Dyn Dyn;
78};
79
80/// alignAddress - helper function to align an address with given alignment
81/// constraint
82///
83/// @param pAddr - the address to be aligned
84/// @param pAlignConstraint - the alignment used to align the given address
85inline void alignAddress(uint64_t& pAddr, uint64_t pAlignConstraint) {
86  if (pAlignConstraint != 0)
87    pAddr = (pAddr + pAlignConstraint - 1) & ~(pAlignConstraint - 1);
88}
89
90template <size_t Constraint>
91uint64_t Align(uint64_t pAddress);
92
93template <>
94inline uint64_t Align<32>(uint64_t pAddress) {
95  return (pAddress + 0x1F) & (~0x1F);
96}
97
98template <>
99inline uint64_t Align<64>(uint64_t pAddress) {
100  return (pAddress + 0x3F) & (~0x3F);
101}
102
103#ifdef bswap16
104#undef bswap16
105#endif
106#ifdef bswap32
107#undef bswap32
108#endif
109#ifdef bswap64
110#undef bswap64
111#endif
112
113/// bswap16 - byte swap 16-bit version
114/// @ref binary utilities - elfcpp_swap
115inline uint16_t bswap16(uint16_t pData) {
116  return ((pData >> 8) & 0xFF) | ((pData & 0xFF) << 8);
117}
118
119/// bswap32 - byte swap 32-bit version
120/// @ref elfcpp_swap
121inline uint32_t bswap32(uint32_t pData) {
122  return (((pData & 0xFF000000) >> 24) | ((pData & 0x00FF0000) >> 8) |
123          ((pData & 0x0000FF00) << 8) | ((pData & 0x000000FF) << 24));
124}
125
126/// bswap64 - byte swap 64-bit version
127/// @ref binary utilities - elfcpp_swap
128inline uint64_t bswap64(uint64_t pData) {
129  return (((pData & 0xFF00000000000000ULL) >> 56) |
130          ((pData & 0x00FF000000000000ULL) >> 40) |
131          ((pData & 0x0000FF0000000000ULL) >> 24) |
132          ((pData & 0x000000FF00000000ULL) >> 8) |
133          ((pData & 0x00000000FF000000ULL) << 8) |
134          ((pData & 0x0000000000FF0000ULL) << 24) |
135          ((pData & 0x000000000000FF00ULL) << 40) |
136          ((pData & 0x00000000000000FFULL) << 56));
137}
138
139template <size_t SIZE>
140typename SizeTraits<SIZE>::Word bswap(typename SizeTraits<SIZE>::Word pData);
141
142template <>
143inline SizeTraits<32>::Word bswap<32>(SizeTraits<32>::Word pData) {
144  return bswap32(pData);
145}
146
147template <>
148inline SizeTraits<64>::Word bswap<64>(SizeTraits<64>::Word pData) {
149  return bswap64(pData);
150}
151
152template <size_t WIDTH>
153inline uint64_t signExtend(uint64_t pVal) {
154  uint64_t mask = (~((uint64_t)0)) >> (64 - WIDTH);
155  uint64_t sign_bit = 1 << (WIDTH - 1);
156
157  return ((pVal & mask) ^ sign_bit) - sign_bit;
158}
159
160template <>
161inline uint64_t signExtend<64>(uint64_t pVal) {
162  return pVal;
163}
164
165template <size_t SizeOfStr, typename FieldType>
166class StringSizerHelper {
167 private:
168  char FIELD_TOO_SMALL[SizeOfStr <= FieldType(~0U) ? 1 : -1];
169
170 public:
171  enum { Size = SizeOfStr };
172};
173
174#define STR_SIZE(str, fieldTy) StringSizerHelper<sizeof(str) - 1, fieldTy>::Size
175
176}  // namespace mcld
177
178#endif  // MCLD_ADT_SIZETRAITS_H_
179