TargetData.cpp revision d2b0bb41f45c1d2381904221c780da8f750d2823
1//===-- TargetData.cpp - Data size & alignment routines --------------------==//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines target properties related to datatype size/offset/alignment
11// information.
12//
13// This structure should be created once, filled in if the defaults are not
14// correct and then passed around by const&.  None of the members functions
15// require modification to the object.
16//
17//===----------------------------------------------------------------------===//
18
19#include "llvm/Target/TargetData.h"
20#include "llvm/Module.h"
21#include "llvm/DerivedTypes.h"
22#include "llvm/Constants.h"
23#include "llvm/Support/GetElementPtrTypeIterator.h"
24#include "Support/MathExtras.h"
25using namespace llvm;
26
27// Handle the Pass registration stuff necessary to use TargetData's.
28namespace {
29  // Register the default SparcV9 implementation...
30  RegisterPass<TargetData> X("targetdata", "Target Data Layout");
31}
32
33static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
34                               uint64_t &Size, unsigned char &Alignment);
35
36//===----------------------------------------------------------------------===//
37// Support for StructLayout
38//===----------------------------------------------------------------------===//
39
40StructLayout::StructLayout(const StructType *ST, const TargetData &TD) {
41  StructAlignment = 0;
42  StructSize = 0;
43
44  // Loop over each of the elements, placing them in memory...
45  for (StructType::element_iterator TI = ST->element_begin(),
46         TE = ST->element_end(); TI != TE; ++TI) {
47    const Type *Ty = *TI;
48    unsigned char A;
49    unsigned TyAlign;
50    uint64_t TySize;
51    getTypeInfo(Ty, &TD, TySize, A);
52    TyAlign = A;
53
54    // Add padding if necessary to make the data element aligned properly...
55    if (StructSize % TyAlign != 0)
56      StructSize = (StructSize/TyAlign + 1) * TyAlign;   // Add padding...
57
58    // Keep track of maximum alignment constraint
59    StructAlignment = std::max(TyAlign, StructAlignment);
60
61    MemberOffsets.push_back(StructSize);
62    StructSize += TySize;                 // Consume space for this data item
63  }
64
65  // Empty structures have alignment of 1 byte.
66  if (StructAlignment == 0) StructAlignment = 1;
67
68  // Add padding to the end of the struct so that it could be put in an array
69  // and all array elements would be aligned correctly.
70  if (StructSize % StructAlignment != 0)
71    StructSize = (StructSize/StructAlignment + 1) * StructAlignment;
72}
73
74//===----------------------------------------------------------------------===//
75//                       TargetData Class Implementation
76//===----------------------------------------------------------------------===//
77
78TargetData::TargetData(const std::string &TargetName,
79                       bool isLittleEndian, unsigned char PtrSize,
80                       unsigned char PtrAl, unsigned char DoubleAl,
81                       unsigned char FloatAl, unsigned char LongAl,
82                       unsigned char IntAl, unsigned char ShortAl,
83                       unsigned char ByteAl, unsigned char BoolAl) {
84
85  // If this assert triggers, a pass "required" TargetData information, but the
86  // top level tool did not provide one for it.  We do not want to default
87  // construct, or else we might end up using a bad endianness or pointer size!
88  //
89  assert(!TargetName.empty() &&
90         "ERROR: Tool did not specify a target data to use!");
91
92  LittleEndian     = isLittleEndian;
93  PointerSize      = PtrSize;
94  PointerAlignment = PtrAl;
95  DoubleAlignment  = DoubleAl;
96  FloatAlignment   = FloatAl;
97  LongAlignment    = LongAl;
98  IntAlignment     = IntAl;
99  ShortAlignment   = ShortAl;
100  ByteAlignment    = ByteAl;
101  BoolAlignment    = BoolAl;
102}
103
104TargetData::TargetData(const std::string &ToolName, const Module *M) {
105  LittleEndian     = M->getEndianness() != Module::BigEndian;
106  PointerSize      = M->getPointerSize() != Module::Pointer64 ? 4 : 8;
107  PointerAlignment = PointerSize;
108  DoubleAlignment  = PointerSize;
109  FloatAlignment   = 4;
110  LongAlignment    = 8;
111  IntAlignment     = 4;
112  ShortAlignment   = 2;
113  ByteAlignment    = 1;
114  BoolAlignment    = 1;
115}
116
117static std::map<std::pair<const TargetData*,const StructType*>,
118                StructLayout> *Layouts = 0;
119
120
121TargetData::~TargetData() {
122  if (Layouts) {
123    // Remove any layouts for this TD.
124    std::map<std::pair<const TargetData*,
125      const StructType*>, StructLayout>::iterator
126      I = Layouts->lower_bound(std::make_pair(this, (const StructType*)0));
127    while (I != Layouts->end() && I->first.first == this)
128      Layouts->erase(I++);
129    if (Layouts->empty()) {
130      delete Layouts;
131      Layouts = 0;
132    }
133  }
134}
135
136const StructLayout *TargetData::getStructLayout(const StructType *Ty) const {
137  if (Layouts == 0)
138    Layouts = new std::map<std::pair<const TargetData*,const StructType*>,
139                           StructLayout>();
140  std::map<std::pair<const TargetData*,const StructType*>,
141                     StructLayout>::iterator
142    I = Layouts->lower_bound(std::make_pair(this, Ty));
143  if (I != Layouts->end() && I->first.first == this && I->first.second == Ty)
144    return &I->second;
145  else {
146    return &Layouts->insert(I, std::make_pair(std::make_pair(this, Ty),
147                                              StructLayout(Ty, *this)))->second;
148  }
149}
150
151static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
152                               uint64_t &Size, unsigned char &Alignment) {
153  assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
154  switch (Ty->getTypeID()) {
155  case Type::BoolTyID:   Size = 1; Alignment = TD->getBoolAlignment(); return;
156  case Type::VoidTyID:
157  case Type::UByteTyID:
158  case Type::SByteTyID:  Size = 1; Alignment = TD->getByteAlignment(); return;
159  case Type::UShortTyID:
160  case Type::ShortTyID:  Size = 2; Alignment = TD->getShortAlignment(); return;
161  case Type::UIntTyID:
162  case Type::IntTyID:    Size = 4; Alignment = TD->getIntAlignment(); return;
163  case Type::ULongTyID:
164  case Type::LongTyID:   Size = 8; Alignment = TD->getLongAlignment(); return;
165  case Type::FloatTyID:  Size = 4; Alignment = TD->getFloatAlignment(); return;
166  case Type::DoubleTyID: Size = 8; Alignment = TD->getDoubleAlignment(); return;
167  case Type::LabelTyID:
168  case Type::PointerTyID:
169    Size = TD->getPointerSize(); Alignment = TD->getPointerAlignment();
170    return;
171  case Type::ArrayTyID: {
172    const ArrayType *ATy = cast<ArrayType>(Ty);
173    getTypeInfo(ATy->getElementType(), TD, Size, Alignment);
174    unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment;
175    Size = AlignedSize*ATy->getNumElements();
176    return;
177  }
178  case Type::StructTyID: {
179    // Get the layout annotation... which is lazily created on demand.
180    const StructLayout *Layout = TD->getStructLayout(cast<StructType>(Ty));
181    Size = Layout->StructSize; Alignment = Layout->StructAlignment;
182    return;
183  }
184
185  default:
186    assert(0 && "Bad type for getTypeInfo!!!");
187    return;
188  }
189}
190
191uint64_t TargetData::getTypeSize(const Type *Ty) const {
192  uint64_t Size;
193  unsigned char Align;
194  getTypeInfo(Ty, this, Size, Align);
195  return Size;
196}
197
198unsigned char TargetData::getTypeAlignment(const Type *Ty) const {
199  uint64_t Size;
200  unsigned char Align;
201  getTypeInfo(Ty, this, Size, Align);
202  return Align;
203}
204
205unsigned char TargetData::getTypeAlignmentShift(const Type *Ty) const {
206  unsigned Align = getTypeAlignment(Ty);
207  assert(!(Align & (Align-1)) && "Alignment is not a power of two!");
208  return log2(Align);
209}
210
211/// getIntPtrType - Return an unsigned integer type that is the same size or
212/// greater to the host pointer size.
213const Type *TargetData::getIntPtrType() const {
214  switch (getPointerSize()) {
215  default: assert(0 && "Unknown pointer size!");
216  case 2: return Type::UShortTy;
217  case 4: return Type::UIntTy;
218  case 8: return Type::ULongTy;
219  }
220}
221
222
223uint64_t TargetData::getIndexedOffset(const Type *ptrTy,
224                                      const std::vector<Value*> &Idx) const {
225  const Type *Ty = ptrTy;
226  assert(isa<PointerType>(Ty) && "Illegal argument for getIndexedOffset()");
227  uint64_t Result = 0;
228
229  generic_gep_type_iterator<std::vector<Value*>::const_iterator>
230    TI = gep_type_begin(ptrTy, Idx.begin(), Idx.end());
231  for (unsigned CurIDX = 0; CurIDX != Idx.size(); ++CurIDX, ++TI) {
232    if (const StructType *STy = dyn_cast<StructType>(*TI)) {
233      assert(Idx[CurIDX]->getType() == Type::UIntTy && "Illegal struct idx");
234      unsigned FieldNo = cast<ConstantUInt>(Idx[CurIDX])->getValue();
235
236      // Get structure layout information...
237      const StructLayout *Layout = getStructLayout(STy);
238
239      // Add in the offset, as calculated by the structure layout info...
240      assert(FieldNo < Layout->MemberOffsets.size() &&"FieldNo out of range!");
241      Result += Layout->MemberOffsets[FieldNo];
242
243      // Update Ty to refer to current element
244      Ty = STy->getElementType(FieldNo);
245    } else {
246      // Update Ty to refer to current element
247      Ty = cast<SequentialType>(Ty)->getElementType();
248
249      // Get the array index and the size of each array element.
250      int64_t arrayIdx = cast<ConstantInt>(Idx[CurIDX])->getRawValue();
251      Result += arrayIdx * (int64_t)getTypeSize(Ty);
252    }
253  }
254
255  return Result;
256}
257
258