LLVM API Documentation

TargetData.cpp

Go to the documentation of this file.
00001 //===-- TargetData.cpp - Data size & alignment routines --------------------==//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file was developed by the LLVM research group and is distributed under
00006 // the University of Illinois Open Source License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file defines target properties related to datatype size/offset/alignment
00011 // information.
00012 //
00013 // This structure should be created once, filled in if the defaults are not
00014 // correct and then passed around by const&.  None of the members functions
00015 // require modification to the object.
00016 //
00017 //===----------------------------------------------------------------------===//
00018 
00019 #include "llvm/Target/TargetData.h"
00020 #include "llvm/Module.h"
00021 #include "llvm/DerivedTypes.h"
00022 #include "llvm/Constants.h"
00023 #include "llvm/Support/GetElementPtrTypeIterator.h"
00024 #include "llvm/Support/MathExtras.h"
00025 #include "llvm/ADT/StringExtras.h"
00026 #include <algorithm>
00027 #include <cstdlib>
00028 #include <sstream>
00029 using namespace llvm;
00030 
00031 // Handle the Pass registration stuff necessary to use TargetData's.
00032 namespace {
00033   // Register the default SparcV9 implementation...
00034   RegisterPass<TargetData> X("targetdata", "Target Data Layout");
00035 }
00036 
00037 static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
00038                                uint64_t &Size, unsigned char &Alignment);
00039 
00040 //===----------------------------------------------------------------------===//
00041 // Support for StructLayout
00042 //===----------------------------------------------------------------------===//
00043 
00044 StructLayout::StructLayout(const StructType *ST, const TargetData &TD) {
00045   StructAlignment = 0;
00046   StructSize = 0;
00047 
00048   // Loop over each of the elements, placing them in memory...
00049   for (StructType::element_iterator TI = ST->element_begin(),
00050          TE = ST->element_end(); TI != TE; ++TI) {
00051     const Type *Ty = *TI;
00052     unsigned char A;
00053     unsigned TyAlign;
00054     uint64_t TySize;
00055     getTypeInfo(Ty, &TD, TySize, A);
00056     TyAlign = A;
00057 
00058     // Add padding if necessary to make the data element aligned properly...
00059     if (StructSize % TyAlign != 0)
00060       StructSize = (StructSize/TyAlign + 1) * TyAlign;   // Add padding...
00061 
00062     // Keep track of maximum alignment constraint
00063     StructAlignment = std::max(TyAlign, StructAlignment);
00064 
00065     MemberOffsets.push_back(StructSize);
00066     StructSize += TySize;                 // Consume space for this data item
00067   }
00068 
00069   // Empty structures have alignment of 1 byte.
00070   if (StructAlignment == 0) StructAlignment = 1;
00071 
00072   // Add padding to the end of the struct so that it could be put in an array
00073   // and all array elements would be aligned correctly.
00074   if (StructSize % StructAlignment != 0)
00075     StructSize = (StructSize/StructAlignment + 1) * StructAlignment;
00076 }
00077 
00078 
00079 /// getElementContainingOffset - Given a valid offset into the structure,
00080 /// return the structure index that contains it.
00081 unsigned StructLayout::getElementContainingOffset(uint64_t Offset) const {
00082   std::vector<uint64_t>::const_iterator SI =
00083     std::upper_bound(MemberOffsets.begin(), MemberOffsets.end(),
00084                      Offset);
00085   assert(SI != MemberOffsets.begin() && "Offset not in structure type!");
00086   --SI;
00087   assert(*SI <= Offset && "upper_bound didn't work");
00088   assert((SI == MemberOffsets.begin() || *(SI-1) < Offset) &&
00089          (SI+1 == MemberOffsets.end() || *(SI+1) > Offset) &&
00090          "Upper bound didn't work!");
00091   return SI-MemberOffsets.begin();
00092 }
00093 
00094 //===----------------------------------------------------------------------===//
00095 //                       TargetData Class Implementation
00096 //===----------------------------------------------------------------------===//
00097 
00098 void TargetData::init(const std::string &TargetDescription) {
00099   std::string temp = TargetDescription;
00100   
00101   LittleEndian = false;
00102   PointerSize = 8;
00103   PointerAlignment   = 8;
00104   DoubleAlignment = 8;
00105   FloatAlignment = 4;
00106   LongAlignment   = 8;
00107   IntAlignment   = 4;
00108   ShortAlignment  = 2;
00109   ByteAlignment  = 1;
00110   BoolAlignment   = 1;
00111   
00112   while (!temp.empty()) {
00113     std::string token = getToken(temp, "-");
00114     
00115     char signal = getToken(token, ":")[0];
00116     
00117     switch(signal) {
00118     case 'E':
00119       LittleEndian = false;
00120       break;
00121     case 'e':
00122       LittleEndian = true;
00123       break;
00124     case 'p':
00125       PointerSize = atoi(getToken(token,":").c_str()) / 8;
00126       PointerAlignment = atoi(getToken(token,":").c_str()) / 8;
00127       break;
00128     case 'd':
00129       DoubleAlignment = atoi(getToken(token,":").c_str()) / 8;
00130       break;
00131     case 'f':
00132       FloatAlignment = atoi(getToken(token, ":").c_str()) / 8;
00133       break;
00134     case 'l':
00135       LongAlignment = atoi(getToken(token, ":").c_str()) / 8;
00136       break;
00137     case 'i':
00138       IntAlignment = atoi(getToken(token, ":").c_str()) / 8;
00139       break;
00140     case 's':
00141       ShortAlignment = atoi(getToken(token, ":").c_str()) / 8;
00142       break;
00143     case 'b':
00144       ByteAlignment = atoi(getToken(token, ":").c_str()) / 8;
00145       break;
00146     case 'B':
00147       BoolAlignment = atoi(getToken(token, ":").c_str()) / 8;
00148       break;
00149     default:
00150       break;
00151     }
00152   }
00153 }
00154 
00155 TargetData::TargetData(const Module *M) {
00156   LittleEndian     = M->getEndianness() != Module::BigEndian;
00157   PointerSize      = M->getPointerSize() != Module::Pointer64 ? 4 : 8;
00158   PointerAlignment = PointerSize;
00159   DoubleAlignment  = PointerSize;
00160   FloatAlignment   = 4;
00161   LongAlignment    = PointerSize;
00162   IntAlignment     = 4;
00163   ShortAlignment   = 2;
00164   ByteAlignment    = 1;
00165   BoolAlignment    = 1;
00166 }
00167 
00168 /// Layouts - The lazy cache of structure layout information maintained by
00169 /// TargetData.
00170 ///
00171 static std::map<std::pair<const TargetData*,const StructType*>,
00172                 StructLayout> *Layouts = 0;
00173 
00174 
00175 TargetData::~TargetData() {
00176   if (Layouts) {
00177     // Remove any layouts for this TD.
00178     std::map<std::pair<const TargetData*,
00179       const StructType*>, StructLayout>::iterator
00180       I = Layouts->lower_bound(std::make_pair(this, (const StructType*)0));
00181     while (I != Layouts->end() && I->first.first == this)
00182       Layouts->erase(I++);
00183     if (Layouts->empty()) {
00184       delete Layouts;
00185       Layouts = 0;
00186     }
00187   }
00188 }
00189 
00190 std::string TargetData::getStringRepresentation() const {
00191   std::stringstream repr;
00192   
00193   if (LittleEndian)
00194     repr << "e";
00195   else
00196     repr << "E";
00197   
00198   repr << "-p:" << (PointerSize * 8) << ":" << (PointerAlignment * 8);
00199   repr << "-d:64:" << (DoubleAlignment * 8);
00200   repr << "-f:32:" << (FloatAlignment * 8);
00201   repr << "-l:64:" << (LongAlignment * 8);
00202   repr << "-i:32:" << (IntAlignment * 8);
00203   repr << "-s:16:" << (ShortAlignment * 8);
00204   repr << "-b:8:" << (ByteAlignment * 8);
00205   repr << "-B:8:" << (BoolAlignment * 8);
00206   
00207   return repr.str();
00208 }
00209 
00210 const StructLayout *TargetData::getStructLayout(const StructType *Ty) const {
00211   if (Layouts == 0)
00212     Layouts = new std::map<std::pair<const TargetData*,const StructType*>,
00213                            StructLayout>();
00214   std::map<std::pair<const TargetData*,const StructType*>,
00215                      StructLayout>::iterator
00216     I = Layouts->lower_bound(std::make_pair(this, Ty));
00217   if (I != Layouts->end() && I->first.first == this && I->first.second == Ty)
00218     return &I->second;
00219   else {
00220     return &Layouts->insert(I, std::make_pair(std::make_pair(this, Ty),
00221                                               StructLayout(Ty, *this)))->second;
00222   }
00223 }
00224 
00225 /// InvalidateStructLayoutInfo - TargetData speculatively caches StructLayout
00226 /// objects.  If a TargetData object is alive when types are being refined and
00227 /// removed, this method must be called whenever a StructType is removed to
00228 /// avoid a dangling pointer in this cache.
00229 void TargetData::InvalidateStructLayoutInfo(const StructType *Ty) const {
00230   if (!Layouts) return;  // No cache.
00231 
00232   std::map<std::pair<const TargetData*,const StructType*>,
00233            StructLayout>::iterator I = Layouts->find(std::make_pair(this, Ty));
00234   if (I != Layouts->end())
00235     Layouts->erase(I);
00236 }
00237 
00238 
00239 
00240 static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
00241                                uint64_t &Size, unsigned char &Alignment) {
00242   assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
00243   switch (Ty->getTypeID()) {
00244   case Type::BoolTyID:   Size = 1; Alignment = TD->getBoolAlignment(); return;
00245   case Type::VoidTyID:
00246   case Type::UByteTyID:
00247   case Type::SByteTyID:  Size = 1; Alignment = TD->getByteAlignment(); return;
00248   case Type::UShortTyID:
00249   case Type::ShortTyID:  Size = 2; Alignment = TD->getShortAlignment(); return;
00250   case Type::UIntTyID:
00251   case Type::IntTyID:    Size = 4; Alignment = TD->getIntAlignment(); return;
00252   case Type::ULongTyID:
00253   case Type::LongTyID:   Size = 8; Alignment = TD->getLongAlignment(); return;
00254   case Type::FloatTyID:  Size = 4; Alignment = TD->getFloatAlignment(); return;
00255   case Type::DoubleTyID: Size = 8; Alignment = TD->getDoubleAlignment(); return;
00256   case Type::LabelTyID:
00257   case Type::PointerTyID:
00258     Size = TD->getPointerSize(); Alignment = TD->getPointerAlignment();
00259     return;
00260   case Type::ArrayTyID: {
00261     const ArrayType *ATy = cast<ArrayType>(Ty);
00262     getTypeInfo(ATy->getElementType(), TD, Size, Alignment);
00263     unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment;
00264     Size = AlignedSize*ATy->getNumElements();
00265     return;
00266   }
00267   case Type::PackedTyID: {
00268     const PackedType *PTy = cast<PackedType>(Ty);
00269     getTypeInfo(PTy->getElementType(), TD, Size, Alignment);
00270     unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment;
00271     Size = AlignedSize*PTy->getNumElements();
00272     // FIXME: The alignments of specific packed types are target dependent.
00273     // For now, just set it to be equal to Size.
00274     Alignment = Size;
00275     return;
00276   }
00277   case Type::StructTyID: {
00278     // Get the layout annotation... which is lazily created on demand.
00279     const StructLayout *Layout = TD->getStructLayout(cast<StructType>(Ty));
00280     Size = Layout->StructSize; Alignment = Layout->StructAlignment;
00281     return;
00282   }
00283 
00284   default:
00285     assert(0 && "Bad type for getTypeInfo!!!");
00286     return;
00287   }
00288 }
00289 
00290 uint64_t TargetData::getTypeSize(const Type *Ty) const {
00291   uint64_t Size;
00292   unsigned char Align;
00293   getTypeInfo(Ty, this, Size, Align);
00294   return Size;
00295 }
00296 
00297 unsigned char TargetData::getTypeAlignment(const Type *Ty) const {
00298   uint64_t Size;
00299   unsigned char Align;
00300   getTypeInfo(Ty, this, Size, Align);
00301   return Align;
00302 }
00303 
00304 unsigned char TargetData::getTypeAlignmentShift(const Type *Ty) const {
00305   unsigned Align = getTypeAlignment(Ty);
00306   assert(!(Align & (Align-1)) && "Alignment is not a power of two!");
00307   return Log2_32(Align);
00308 }
00309 
00310 /// getIntPtrType - Return an unsigned integer type that is the same size or
00311 /// greater to the host pointer size.
00312 const Type *TargetData::getIntPtrType() const {
00313   switch (getPointerSize()) {
00314   default: assert(0 && "Unknown pointer size!");
00315   case 2: return Type::UShortTy;
00316   case 4: return Type::UIntTy;
00317   case 8: return Type::ULongTy;
00318   }
00319 }
00320 
00321 
00322 uint64_t TargetData::getIndexedOffset(const Type *ptrTy,
00323                                       const std::vector<Value*> &Idx) const {
00324   const Type *Ty = ptrTy;
00325   assert(isa<PointerType>(Ty) && "Illegal argument for getIndexedOffset()");
00326   uint64_t Result = 0;
00327 
00328   generic_gep_type_iterator<std::vector<Value*>::const_iterator>
00329     TI = gep_type_begin(ptrTy, Idx.begin(), Idx.end());
00330   for (unsigned CurIDX = 0; CurIDX != Idx.size(); ++CurIDX, ++TI) {
00331     if (const StructType *STy = dyn_cast<StructType>(*TI)) {
00332       assert(Idx[CurIDX]->getType() == Type::UIntTy && "Illegal struct idx");
00333       unsigned FieldNo = cast<ConstantUInt>(Idx[CurIDX])->getValue();
00334 
00335       // Get structure layout information...
00336       const StructLayout *Layout = getStructLayout(STy);
00337 
00338       // Add in the offset, as calculated by the structure layout info...
00339       assert(FieldNo < Layout->MemberOffsets.size() &&"FieldNo out of range!");
00340       Result += Layout->MemberOffsets[FieldNo];
00341 
00342       // Update Ty to refer to current element
00343       Ty = STy->getElementType(FieldNo);
00344     } else {
00345       // Update Ty to refer to current element
00346       Ty = cast<SequentialType>(Ty)->getElementType();
00347 
00348       // Get the array index and the size of each array element.
00349       int64_t arrayIdx = cast<ConstantInt>(Idx[CurIDX])->getRawValue();
00350       Result += arrayIdx * (int64_t)getTypeSize(Ty);
00351     }
00352   }
00353 
00354   return Result;
00355 }
00356