LLVM API Documentation

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

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 using namespace llvm;
00026 
00027 // Handle the Pass registration stuff necessary to use TargetData's.
00028 namespace {
00029   // Register the default SparcV9 implementation...
00030   RegisterPass<TargetData> X("targetdata", "Target Data Layout");
00031 }
00032 
00033 static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
00034                                uint64_t &Size, unsigned char &Alignment);
00035 
00036 //===----------------------------------------------------------------------===//
00037 // Support for StructLayout
00038 //===----------------------------------------------------------------------===//
00039 
00040 StructLayout::StructLayout(const StructType *ST, const TargetData &TD) {
00041   StructAlignment = 0;
00042   StructSize = 0;
00043 
00044   // Loop over each of the elements, placing them in memory...
00045   for (StructType::element_iterator TI = ST->element_begin(), 
00046          TE = ST->element_end(); TI != TE; ++TI) {
00047     const Type *Ty = *TI;
00048     unsigned char A;
00049     unsigned TyAlign;
00050     uint64_t TySize;
00051     getTypeInfo(Ty, &TD, TySize, A);
00052     TyAlign = A;
00053 
00054     // Add padding if necessary to make the data element aligned properly...
00055     if (StructSize % TyAlign != 0)
00056       StructSize = (StructSize/TyAlign + 1) * TyAlign;   // Add padding...
00057 
00058     // Keep track of maximum alignment constraint
00059     StructAlignment = std::max(TyAlign, StructAlignment);
00060 
00061     MemberOffsets.push_back(StructSize);
00062     StructSize += TySize;                 // Consume space for this data item
00063   }
00064 
00065   // Empty structures have alignment of 1 byte.
00066   if (StructAlignment == 0) StructAlignment = 1;
00067 
00068   // Add padding to the end of the struct so that it could be put in an array
00069   // and all array elements would be aligned correctly.
00070   if (StructSize % StructAlignment != 0)
00071     StructSize = (StructSize/StructAlignment + 1) * StructAlignment;
00072 }
00073 
00074 //===----------------------------------------------------------------------===//
00075 //                       TargetData Class Implementation
00076 //===----------------------------------------------------------------------===//
00077 
00078 TargetData::TargetData(const std::string &TargetName,
00079                        bool isLittleEndian, unsigned char PtrSize,
00080                        unsigned char PtrAl, unsigned char DoubleAl,
00081                        unsigned char FloatAl, unsigned char LongAl, 
00082                        unsigned char IntAl, unsigned char ShortAl,
00083                        unsigned char ByteAl, unsigned char BoolAl) {
00084 
00085   // If this assert triggers, a pass "required" TargetData information, but the
00086   // top level tool did not provide one for it.  We do not want to default
00087   // construct, or else we might end up using a bad endianness or pointer size!
00088   //
00089   assert(!TargetName.empty() &&
00090          "ERROR: Tool did not specify a target data to use!");
00091 
00092   LittleEndian     = isLittleEndian;
00093   PointerSize      = PtrSize;
00094   PointerAlignment = PtrAl;
00095   DoubleAlignment  = DoubleAl;
00096   FloatAlignment   = FloatAl;
00097   LongAlignment    = LongAl;
00098   IntAlignment     = IntAl;
00099   ShortAlignment   = ShortAl;
00100   ByteAlignment    = ByteAl;
00101   BoolAlignment    = BoolAl;
00102 }
00103 
00104 TargetData::TargetData(const std::string &ToolName, const Module *M) {
00105   LittleEndian     = M->getEndianness() != Module::BigEndian;
00106   PointerSize      = M->getPointerSize() != Module::Pointer64 ? 4 : 8;
00107   PointerAlignment = PointerSize;
00108   DoubleAlignment  = PointerSize;
00109   FloatAlignment   = 4;
00110   LongAlignment    = PointerSize;
00111   IntAlignment     = 4;
00112   ShortAlignment   = 2;
00113   ByteAlignment    = 1;
00114   BoolAlignment    = 1;
00115 }
00116 
00117 static std::map<std::pair<const TargetData*,const StructType*>,
00118                 StructLayout> *Layouts = 0;
00119 
00120 
00121 TargetData::~TargetData() {
00122   if (Layouts) {
00123     // Remove any layouts for this TD.
00124     std::map<std::pair<const TargetData*,
00125       const StructType*>, StructLayout>::iterator
00126       I = Layouts->lower_bound(std::make_pair(this, (const StructType*)0));
00127     while (I != Layouts->end() && I->first.first == this)
00128       Layouts->erase(I++);
00129     if (Layouts->empty()) {
00130       delete Layouts;
00131       Layouts = 0;
00132     }
00133   }
00134 }
00135 
00136 const StructLayout *TargetData::getStructLayout(const StructType *Ty) const {
00137   if (Layouts == 0)
00138     Layouts = new std::map<std::pair<const TargetData*,const StructType*>,
00139                            StructLayout>();
00140   std::map<std::pair<const TargetData*,const StructType*>,
00141                      StructLayout>::iterator
00142     I = Layouts->lower_bound(std::make_pair(this, Ty));
00143   if (I != Layouts->end() && I->first.first == this && I->first.second == Ty)
00144     return &I->second;
00145   else {
00146     return &Layouts->insert(I, std::make_pair(std::make_pair(this, Ty),
00147                                               StructLayout(Ty, *this)))->second;
00148   }
00149 }
00150 
00151 static inline void getTypeInfo(const Type *Ty, const TargetData *TD,
00152                                uint64_t &Size, unsigned char &Alignment) {
00153   assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
00154   switch (Ty->getTypeID()) {
00155   case Type::BoolTyID:   Size = 1; Alignment = TD->getBoolAlignment(); return;
00156   case Type::VoidTyID:
00157   case Type::UByteTyID:
00158   case Type::SByteTyID:  Size = 1; Alignment = TD->getByteAlignment(); return;
00159   case Type::UShortTyID:
00160   case Type::ShortTyID:  Size = 2; Alignment = TD->getShortAlignment(); return;
00161   case Type::UIntTyID:
00162   case Type::IntTyID:    Size = 4; Alignment = TD->getIntAlignment(); return;
00163   case Type::ULongTyID:
00164   case Type::LongTyID:   Size = 8; Alignment = TD->getLongAlignment(); return;
00165   case Type::FloatTyID:  Size = 4; Alignment = TD->getFloatAlignment(); return;
00166   case Type::DoubleTyID: Size = 8; Alignment = TD->getDoubleAlignment(); return;
00167   case Type::LabelTyID:
00168   case Type::PointerTyID:
00169     Size = TD->getPointerSize(); Alignment = TD->getPointerAlignment();
00170     return;
00171   case Type::ArrayTyID: {
00172     const ArrayType *ATy = cast<ArrayType>(Ty);
00173     getTypeInfo(ATy->getElementType(), TD, Size, Alignment);
00174     unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment;
00175     Size = AlignedSize*ATy->getNumElements();
00176     return;
00177   }
00178   case Type::PackedTyID: {
00179     const PackedType *PTy = cast<PackedType>(Ty);
00180     getTypeInfo(PTy->getElementType(), TD, Size, Alignment);
00181     unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment;
00182     Size = AlignedSize*PTy->getNumElements();
00183     return;
00184   }
00185   case Type::StructTyID: {
00186     // Get the layout annotation... which is lazily created on demand.
00187     const StructLayout *Layout = TD->getStructLayout(cast<StructType>(Ty));
00188     Size = Layout->StructSize; Alignment = Layout->StructAlignment;
00189     return;
00190   }
00191     
00192   default:
00193     assert(0 && "Bad type for getTypeInfo!!!");
00194     return;
00195   }
00196 }
00197 
00198 uint64_t TargetData::getTypeSize(const Type *Ty) const {
00199   uint64_t Size;
00200   unsigned char Align;
00201   getTypeInfo(Ty, this, Size, Align);
00202   return Size;
00203 }
00204 
00205 unsigned char TargetData::getTypeAlignment(const Type *Ty) const {
00206   uint64_t Size;
00207   unsigned char Align;
00208   getTypeInfo(Ty, this, Size, Align);
00209   return Align;
00210 }
00211 
00212 unsigned char TargetData::getTypeAlignmentShift(const Type *Ty) const {
00213   unsigned Align = getTypeAlignment(Ty);
00214   assert(!(Align & (Align-1)) && "Alignment is not a power of two!");
00215   return log2(Align);
00216 }
00217 
00218 /// getIntPtrType - Return an unsigned integer type that is the same size or
00219 /// greater to the host pointer size.
00220 const Type *TargetData::getIntPtrType() const {
00221   switch (getPointerSize()) {
00222   default: assert(0 && "Unknown pointer size!");
00223   case 2: return Type::UShortTy;
00224   case 4: return Type::UIntTy;
00225   case 8: return Type::ULongTy;
00226   }
00227 }
00228 
00229 
00230 uint64_t TargetData::getIndexedOffset(const Type *ptrTy,
00231                                       const std::vector<Value*> &Idx) const {
00232   const Type *Ty = ptrTy;
00233   assert(isa<PointerType>(Ty) && "Illegal argument for getIndexedOffset()");
00234   uint64_t Result = 0;
00235 
00236   generic_gep_type_iterator<std::vector<Value*>::const_iterator>
00237     TI = gep_type_begin(ptrTy, Idx.begin(), Idx.end());
00238   for (unsigned CurIDX = 0; CurIDX != Idx.size(); ++CurIDX, ++TI) {
00239     if (const StructType *STy = dyn_cast<StructType>(*TI)) {
00240       assert(Idx[CurIDX]->getType() == Type::UIntTy && "Illegal struct idx");
00241       unsigned FieldNo = cast<ConstantUInt>(Idx[CurIDX])->getValue();
00242 
00243       // Get structure layout information...
00244       const StructLayout *Layout = getStructLayout(STy);
00245 
00246       // Add in the offset, as calculated by the structure layout info...
00247       assert(FieldNo < Layout->MemberOffsets.size() &&"FieldNo out of range!");
00248       Result += Layout->MemberOffsets[FieldNo];
00249 
00250       // Update Ty to refer to current element
00251       Ty = STy->getElementType(FieldNo);
00252     } else {
00253       // Update Ty to refer to current element
00254       Ty = cast<SequentialType>(Ty)->getElementType();
00255 
00256       // Get the array index and the size of each array element.
00257       int64_t arrayIdx = cast<ConstantInt>(Idx[CurIDX])->getRawValue();
00258       Result += arrayIdx * (int64_t)getTypeSize(Ty);
00259     }
00260   }
00261 
00262   return Result;
00263 }
00264