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