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