diff options
Diffstat (limited to 'llvm/lib/IR/DataLayout.cpp')
-rw-r--r-- | llvm/lib/IR/DataLayout.cpp | 877 |
1 files changed, 877 insertions, 0 deletions
diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp new file mode 100644 index 000000000000..5fe7a2e94b6a --- /dev/null +++ b/llvm/lib/IR/DataLayout.cpp @@ -0,0 +1,877 @@ +//===- DataLayout.cpp - Data size & alignment routines ---------------------==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines layout properties related to datatype size/offset/alignment +// information. +// +// This structure should be created once, filled in if the defaults are not +// correct and then passed around by const&. None of the members functions +// require modification to the object. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/DataLayout.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Value.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/TypeSize.h" +#include <algorithm> +#include <cassert> +#include <cstdint> +#include <cstdlib> +#include <tuple> +#include <utility> + +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Support for StructLayout +//===----------------------------------------------------------------------===// + +StructLayout::StructLayout(StructType *ST, const DataLayout &DL) { + assert(!ST->isOpaque() && "Cannot get layout of opaque structs"); + StructSize = 0; + IsPadded = false; + NumElements = ST->getNumElements(); + + // Loop over each of the elements, placing them in memory. + for (unsigned i = 0, e = NumElements; i != e; ++i) { + Type *Ty = ST->getElementType(i); + const Align TyAlign(ST->isPacked() ? 1 : DL.getABITypeAlignment(Ty)); + + // Add padding if necessary to align the data element properly. + if (!isAligned(TyAlign, StructSize)) { + IsPadded = true; + StructSize = alignTo(StructSize, TyAlign); + } + + // Keep track of maximum alignment constraint. + StructAlignment = std::max(TyAlign, StructAlignment); + + MemberOffsets[i] = StructSize; + StructSize += DL.getTypeAllocSize(Ty); // Consume space for this data item + } + + // Add padding to the end of the struct so that it could be put in an array + // and all array elements would be aligned correctly. + if (!isAligned(StructAlignment, StructSize)) { + IsPadded = true; + StructSize = alignTo(StructSize, StructAlignment); + } +} + +/// getElementContainingOffset - Given a valid offset into the structure, +/// return the structure index that contains it. +unsigned StructLayout::getElementContainingOffset(uint64_t Offset) const { + const uint64_t *SI = + std::upper_bound(&MemberOffsets[0], &MemberOffsets[NumElements], Offset); + assert(SI != &MemberOffsets[0] && "Offset not in structure type!"); + --SI; + assert(*SI <= Offset && "upper_bound didn't work"); + assert((SI == &MemberOffsets[0] || *(SI-1) <= Offset) && + (SI+1 == &MemberOffsets[NumElements] || *(SI+1) > Offset) && + "Upper bound didn't work!"); + + // Multiple fields can have the same offset if any of them are zero sized. + // For example, in { i32, [0 x i32], i32 }, searching for offset 4 will stop + // at the i32 element, because it is the last element at that offset. This is + // the right one to return, because anything after it will have a higher + // offset, implying that this element is non-empty. + return SI-&MemberOffsets[0]; +} + +//===----------------------------------------------------------------------===// +// LayoutAlignElem, LayoutAlign support +//===----------------------------------------------------------------------===// + +LayoutAlignElem LayoutAlignElem::get(AlignTypeEnum align_type, Align abi_align, + Align pref_align, uint32_t bit_width) { + assert(abi_align <= pref_align && "Preferred alignment worse than ABI!"); + LayoutAlignElem retval; + retval.AlignType = align_type; + retval.ABIAlign = abi_align; + retval.PrefAlign = pref_align; + retval.TypeBitWidth = bit_width; + return retval; +} + +bool +LayoutAlignElem::operator==(const LayoutAlignElem &rhs) const { + return (AlignType == rhs.AlignType + && ABIAlign == rhs.ABIAlign + && PrefAlign == rhs.PrefAlign + && TypeBitWidth == rhs.TypeBitWidth); +} + +//===----------------------------------------------------------------------===// +// PointerAlignElem, PointerAlign support +//===----------------------------------------------------------------------===// + +PointerAlignElem PointerAlignElem::get(uint32_t AddressSpace, Align ABIAlign, + Align PrefAlign, uint32_t TypeByteWidth, + uint32_t IndexWidth) { + assert(ABIAlign <= PrefAlign && "Preferred alignment worse than ABI!"); + PointerAlignElem retval; + retval.AddressSpace = AddressSpace; + retval.ABIAlign = ABIAlign; + retval.PrefAlign = PrefAlign; + retval.TypeByteWidth = TypeByteWidth; + retval.IndexWidth = IndexWidth; + return retval; +} + +bool +PointerAlignElem::operator==(const PointerAlignElem &rhs) const { + return (ABIAlign == rhs.ABIAlign + && AddressSpace == rhs.AddressSpace + && PrefAlign == rhs.PrefAlign + && TypeByteWidth == rhs.TypeByteWidth + && IndexWidth == rhs.IndexWidth); +} + +//===----------------------------------------------------------------------===// +// DataLayout Class Implementation +//===----------------------------------------------------------------------===// + +const char *DataLayout::getManglingComponent(const Triple &T) { + if (T.isOSBinFormatMachO()) + return "-m:o"; + if (T.isOSWindows() && T.isOSBinFormatCOFF()) + return T.getArch() == Triple::x86 ? "-m:x" : "-m:w"; + return "-m:e"; +} + +static const LayoutAlignElem DefaultAlignments[] = { + {INTEGER_ALIGN, 1, Align(1), Align(1)}, // i1 + {INTEGER_ALIGN, 8, Align(1), Align(1)}, // i8 + {INTEGER_ALIGN, 16, Align(2), Align(2)}, // i16 + {INTEGER_ALIGN, 32, Align(4), Align(4)}, // i32 + {INTEGER_ALIGN, 64, Align(4), Align(8)}, // i64 + {FLOAT_ALIGN, 16, Align(2), Align(2)}, // half + {FLOAT_ALIGN, 32, Align(4), Align(4)}, // float + {FLOAT_ALIGN, 64, Align(8), Align(8)}, // double + {FLOAT_ALIGN, 128, Align(16), Align(16)}, // ppcf128, quad, ... + {VECTOR_ALIGN, 64, Align(8), Align(8)}, // v2i32, v1i64, ... + {VECTOR_ALIGN, 128, Align(16), Align(16)}, // v16i8, v8i16, v4i32, ... + {AGGREGATE_ALIGN, 0, Align(1), Align(8)} // struct +}; + +void DataLayout::reset(StringRef Desc) { + clear(); + + LayoutMap = nullptr; + BigEndian = false; + AllocaAddrSpace = 0; + StackNaturalAlign.reset(); + ProgramAddrSpace = 0; + FunctionPtrAlign.reset(); + TheFunctionPtrAlignType = FunctionPtrAlignType::Independent; + ManglingMode = MM_None; + NonIntegralAddressSpaces.clear(); + + // Default alignments + for (const LayoutAlignElem &E : DefaultAlignments) { + setAlignment((AlignTypeEnum)E.AlignType, E.ABIAlign, E.PrefAlign, + E.TypeBitWidth); + } + setPointerAlignment(0, Align(8), Align(8), 8, 8); + + parseSpecifier(Desc); +} + +/// Checked version of split, to ensure mandatory subparts. +static std::pair<StringRef, StringRef> split(StringRef Str, char Separator) { + assert(!Str.empty() && "parse error, string can't be empty here"); + std::pair<StringRef, StringRef> Split = Str.split(Separator); + if (Split.second.empty() && Split.first != Str) + report_fatal_error("Trailing separator in datalayout string"); + if (!Split.second.empty() && Split.first.empty()) + report_fatal_error("Expected token before separator in datalayout string"); + return Split; +} + +/// Get an unsigned integer, including error checks. +static unsigned getInt(StringRef R) { + unsigned Result; + bool error = R.getAsInteger(10, Result); (void)error; + if (error) + report_fatal_error("not a number, or does not fit in an unsigned int"); + return Result; +} + +/// Convert bits into bytes. Assert if not a byte width multiple. +static unsigned inBytes(unsigned Bits) { + if (Bits % 8) + report_fatal_error("number of bits must be a byte width multiple"); + return Bits / 8; +} + +static unsigned getAddrSpace(StringRef R) { + unsigned AddrSpace = getInt(R); + if (!isUInt<24>(AddrSpace)) + report_fatal_error("Invalid address space, must be a 24-bit integer"); + return AddrSpace; +} + +void DataLayout::parseSpecifier(StringRef Desc) { + StringRepresentation = Desc; + while (!Desc.empty()) { + // Split at '-'. + std::pair<StringRef, StringRef> Split = split(Desc, '-'); + Desc = Split.second; + + // Split at ':'. + Split = split(Split.first, ':'); + + // Aliases used below. + StringRef &Tok = Split.first; // Current token. + StringRef &Rest = Split.second; // The rest of the string. + + if (Tok == "ni") { + do { + Split = split(Rest, ':'); + Rest = Split.second; + unsigned AS = getInt(Split.first); + if (AS == 0) + report_fatal_error("Address space 0 can never be non-integral"); + NonIntegralAddressSpaces.push_back(AS); + } while (!Rest.empty()); + + continue; + } + + char Specifier = Tok.front(); + Tok = Tok.substr(1); + + switch (Specifier) { + case 's': + // Ignored for backward compatibility. + // FIXME: remove this on LLVM 4.0. + break; + case 'E': + BigEndian = true; + break; + case 'e': + BigEndian = false; + break; + case 'p': { + // Address space. + unsigned AddrSpace = Tok.empty() ? 0 : getInt(Tok); + if (!isUInt<24>(AddrSpace)) + report_fatal_error("Invalid address space, must be a 24bit integer"); + + // Size. + if (Rest.empty()) + report_fatal_error( + "Missing size specification for pointer in datalayout string"); + Split = split(Rest, ':'); + unsigned PointerMemSize = inBytes(getInt(Tok)); + if (!PointerMemSize) + report_fatal_error("Invalid pointer size of 0 bytes"); + + // ABI alignment. + if (Rest.empty()) + report_fatal_error( + "Missing alignment specification for pointer in datalayout string"); + Split = split(Rest, ':'); + unsigned PointerABIAlign = inBytes(getInt(Tok)); + if (!isPowerOf2_64(PointerABIAlign)) + report_fatal_error( + "Pointer ABI alignment must be a power of 2"); + + // Size of index used in GEP for address calculation. + // The parameter is optional. By default it is equal to size of pointer. + unsigned IndexSize = PointerMemSize; + + // Preferred alignment. + unsigned PointerPrefAlign = PointerABIAlign; + if (!Rest.empty()) { + Split = split(Rest, ':'); + PointerPrefAlign = inBytes(getInt(Tok)); + if (!isPowerOf2_64(PointerPrefAlign)) + report_fatal_error( + "Pointer preferred alignment must be a power of 2"); + + // Now read the index. It is the second optional parameter here. + if (!Rest.empty()) { + Split = split(Rest, ':'); + IndexSize = inBytes(getInt(Tok)); + if (!IndexSize) + report_fatal_error("Invalid index size of 0 bytes"); + } + } + setPointerAlignment(AddrSpace, assumeAligned(PointerABIAlign), + assumeAligned(PointerPrefAlign), PointerMemSize, + IndexSize); + break; + } + case 'i': + case 'v': + case 'f': + case 'a': { + AlignTypeEnum AlignType; + switch (Specifier) { + default: llvm_unreachable("Unexpected specifier!"); + case 'i': AlignType = INTEGER_ALIGN; break; + case 'v': AlignType = VECTOR_ALIGN; break; + case 'f': AlignType = FLOAT_ALIGN; break; + case 'a': AlignType = AGGREGATE_ALIGN; break; + } + + // Bit size. + unsigned Size = Tok.empty() ? 0 : getInt(Tok); + + if (AlignType == AGGREGATE_ALIGN && Size != 0) + report_fatal_error( + "Sized aggregate specification in datalayout string"); + + // ABI alignment. + if (Rest.empty()) + report_fatal_error( + "Missing alignment specification in datalayout string"); + Split = split(Rest, ':'); + const unsigned ABIAlign = inBytes(getInt(Tok)); + if (AlignType != AGGREGATE_ALIGN && !ABIAlign) + report_fatal_error( + "ABI alignment specification must be >0 for non-aggregate types"); + + if (!isUInt<16>(ABIAlign)) + report_fatal_error("Invalid ABI alignment, must be a 16bit integer"); + if (ABIAlign != 0 && !isPowerOf2_64(ABIAlign)) + report_fatal_error("Invalid ABI alignment, must be a power of 2"); + + // Preferred alignment. + unsigned PrefAlign = ABIAlign; + if (!Rest.empty()) { + Split = split(Rest, ':'); + PrefAlign = inBytes(getInt(Tok)); + } + + if (!isUInt<16>(PrefAlign)) + report_fatal_error( + "Invalid preferred alignment, must be a 16bit integer"); + if (PrefAlign != 0 && !isPowerOf2_64(PrefAlign)) + report_fatal_error("Invalid preferred alignment, must be a power of 2"); + + setAlignment(AlignType, assumeAligned(ABIAlign), assumeAligned(PrefAlign), + Size); + + break; + } + case 'n': // Native integer types. + while (true) { + unsigned Width = getInt(Tok); + if (Width == 0) + report_fatal_error( + "Zero width native integer type in datalayout string"); + LegalIntWidths.push_back(Width); + if (Rest.empty()) + break; + Split = split(Rest, ':'); + } + break; + case 'S': { // Stack natural alignment. + uint64_t Alignment = inBytes(getInt(Tok)); + if (Alignment != 0 && !llvm::isPowerOf2_64(Alignment)) + report_fatal_error("Alignment is neither 0 nor a power of 2"); + StackNaturalAlign = MaybeAlign(Alignment); + break; + } + case 'F': { + switch (Tok.front()) { + case 'i': + TheFunctionPtrAlignType = FunctionPtrAlignType::Independent; + break; + case 'n': + TheFunctionPtrAlignType = FunctionPtrAlignType::MultipleOfFunctionAlign; + break; + default: + report_fatal_error("Unknown function pointer alignment type in " + "datalayout string"); + } + Tok = Tok.substr(1); + uint64_t Alignment = inBytes(getInt(Tok)); + if (Alignment != 0 && !llvm::isPowerOf2_64(Alignment)) + report_fatal_error("Alignment is neither 0 nor a power of 2"); + FunctionPtrAlign = MaybeAlign(Alignment); + break; + } + case 'P': { // Function address space. + ProgramAddrSpace = getAddrSpace(Tok); + break; + } + case 'A': { // Default stack/alloca address space. + AllocaAddrSpace = getAddrSpace(Tok); + break; + } + case 'm': + if (!Tok.empty()) + report_fatal_error("Unexpected trailing characters after mangling specifier in datalayout string"); + if (Rest.empty()) + report_fatal_error("Expected mangling specifier in datalayout string"); + if (Rest.size() > 1) + report_fatal_error("Unknown mangling specifier in datalayout string"); + switch(Rest[0]) { + default: + report_fatal_error("Unknown mangling in datalayout string"); + case 'e': + ManglingMode = MM_ELF; + break; + case 'o': + ManglingMode = MM_MachO; + break; + case 'm': + ManglingMode = MM_Mips; + break; + case 'w': + ManglingMode = MM_WinCOFF; + break; + case 'x': + ManglingMode = MM_WinCOFFX86; + break; + } + break; + default: + report_fatal_error("Unknown specifier in datalayout string"); + break; + } + } +} + +DataLayout::DataLayout(const Module *M) { + init(M); +} + +void DataLayout::init(const Module *M) { *this = M->getDataLayout(); } + +bool DataLayout::operator==(const DataLayout &Other) const { + bool Ret = BigEndian == Other.BigEndian && + AllocaAddrSpace == Other.AllocaAddrSpace && + StackNaturalAlign == Other.StackNaturalAlign && + ProgramAddrSpace == Other.ProgramAddrSpace && + FunctionPtrAlign == Other.FunctionPtrAlign && + TheFunctionPtrAlignType == Other.TheFunctionPtrAlignType && + ManglingMode == Other.ManglingMode && + LegalIntWidths == Other.LegalIntWidths && + Alignments == Other.Alignments && Pointers == Other.Pointers; + // Note: getStringRepresentation() might differs, it is not canonicalized + return Ret; +} + +DataLayout::AlignmentsTy::iterator +DataLayout::findAlignmentLowerBound(AlignTypeEnum AlignType, + uint32_t BitWidth) { + auto Pair = std::make_pair((unsigned)AlignType, BitWidth); + return partition_point(Alignments, [=](const LayoutAlignElem &E) { + return std::make_pair(E.AlignType, E.TypeBitWidth) < Pair; + }); +} + +void DataLayout::setAlignment(AlignTypeEnum align_type, Align abi_align, + Align pref_align, uint32_t bit_width) { + // AlignmentsTy::ABIAlign and AlignmentsTy::PrefAlign were once stored as + // uint16_t, it is unclear if there are requirements for alignment to be less + // than 2^16 other than storage. In the meantime we leave the restriction as + // an assert. See D67400 for context. + assert(Log2(abi_align) < 16 && Log2(pref_align) < 16 && "Alignment too big"); + if (!isUInt<24>(bit_width)) + report_fatal_error("Invalid bit width, must be a 24bit integer"); + if (pref_align < abi_align) + report_fatal_error( + "Preferred alignment cannot be less than the ABI alignment"); + + AlignmentsTy::iterator I = findAlignmentLowerBound(align_type, bit_width); + if (I != Alignments.end() && + I->AlignType == (unsigned)align_type && I->TypeBitWidth == bit_width) { + // Update the abi, preferred alignments. + I->ABIAlign = abi_align; + I->PrefAlign = pref_align; + } else { + // Insert before I to keep the vector sorted. + Alignments.insert(I, LayoutAlignElem::get(align_type, abi_align, + pref_align, bit_width)); + } +} + +DataLayout::PointersTy::iterator +DataLayout::findPointerLowerBound(uint32_t AddressSpace) { + return std::lower_bound(Pointers.begin(), Pointers.end(), AddressSpace, + [](const PointerAlignElem &A, uint32_t AddressSpace) { + return A.AddressSpace < AddressSpace; + }); +} + +void DataLayout::setPointerAlignment(uint32_t AddrSpace, Align ABIAlign, + Align PrefAlign, uint32_t TypeByteWidth, + uint32_t IndexWidth) { + if (PrefAlign < ABIAlign) + report_fatal_error( + "Preferred alignment cannot be less than the ABI alignment"); + + PointersTy::iterator I = findPointerLowerBound(AddrSpace); + if (I == Pointers.end() || I->AddressSpace != AddrSpace) { + Pointers.insert(I, PointerAlignElem::get(AddrSpace, ABIAlign, PrefAlign, + TypeByteWidth, IndexWidth)); + } else { + I->ABIAlign = ABIAlign; + I->PrefAlign = PrefAlign; + I->TypeByteWidth = TypeByteWidth; + I->IndexWidth = IndexWidth; + } +} + +/// getAlignmentInfo - Return the alignment (either ABI if ABIInfo = true or +/// preferred if ABIInfo = false) the layout wants for the specified datatype. +Align DataLayout::getAlignmentInfo(AlignTypeEnum AlignType, uint32_t BitWidth, + bool ABIInfo, Type *Ty) const { + AlignmentsTy::const_iterator I = findAlignmentLowerBound(AlignType, BitWidth); + // See if we found an exact match. Of if we are looking for an integer type, + // but don't have an exact match take the next largest integer. This is where + // the lower_bound will point to when it fails an exact match. + if (I != Alignments.end() && I->AlignType == (unsigned)AlignType && + (I->TypeBitWidth == BitWidth || AlignType == INTEGER_ALIGN)) + return ABIInfo ? I->ABIAlign : I->PrefAlign; + + if (AlignType == INTEGER_ALIGN) { + // If we didn't have a larger value try the largest value we have. + if (I != Alignments.begin()) { + --I; // Go to the previous entry and see if its an integer. + if (I->AlignType == INTEGER_ALIGN) + return ABIInfo ? I->ABIAlign : I->PrefAlign; + } + } else if (AlignType == VECTOR_ALIGN) { + // By default, use natural alignment for vector types. This is consistent + // with what clang and llvm-gcc do. + unsigned Alignment = + getTypeAllocSize(cast<VectorType>(Ty)->getElementType()); + Alignment *= cast<VectorType>(Ty)->getNumElements(); + Alignment = PowerOf2Ceil(Alignment); + return Align(Alignment); + } + + // If we still couldn't find a reasonable default alignment, fall back + // to a simple heuristic that the alignment is the first power of two + // greater-or-equal to the store size of the type. This is a reasonable + // approximation of reality, and if the user wanted something less + // less conservative, they should have specified it explicitly in the data + // layout. + unsigned Alignment = getTypeStoreSize(Ty); + Alignment = PowerOf2Ceil(Alignment); + return Align(Alignment); +} + +namespace { + +class StructLayoutMap { + using LayoutInfoTy = DenseMap<StructType*, StructLayout*>; + LayoutInfoTy LayoutInfo; + +public: + ~StructLayoutMap() { + // Remove any layouts. + for (const auto &I : LayoutInfo) { + StructLayout *Value = I.second; + Value->~StructLayout(); + free(Value); + } + } + + StructLayout *&operator[](StructType *STy) { + return LayoutInfo[STy]; + } +}; + +} // end anonymous namespace + +void DataLayout::clear() { + LegalIntWidths.clear(); + Alignments.clear(); + Pointers.clear(); + delete static_cast<StructLayoutMap *>(LayoutMap); + LayoutMap = nullptr; +} + +DataLayout::~DataLayout() { + clear(); +} + +const StructLayout *DataLayout::getStructLayout(StructType *Ty) const { + if (!LayoutMap) + LayoutMap = new StructLayoutMap(); + + StructLayoutMap *STM = static_cast<StructLayoutMap*>(LayoutMap); + StructLayout *&SL = (*STM)[Ty]; + if (SL) return SL; + + // Otherwise, create the struct layout. Because it is variable length, we + // malloc it, then use placement new. + int NumElts = Ty->getNumElements(); + StructLayout *L = (StructLayout *) + safe_malloc(sizeof(StructLayout)+(NumElts-1) * sizeof(uint64_t)); + + // Set SL before calling StructLayout's ctor. The ctor could cause other + // entries to be added to TheMap, invalidating our reference. + SL = L; + + new (L) StructLayout(Ty, *this); + + return L; +} + +Align DataLayout::getPointerABIAlignment(unsigned AS) const { + PointersTy::const_iterator I = findPointerLowerBound(AS); + if (I == Pointers.end() || I->AddressSpace != AS) { + I = findPointerLowerBound(0); + assert(I->AddressSpace == 0); + } + return I->ABIAlign; +} + +Align DataLayout::getPointerPrefAlignment(unsigned AS) const { + PointersTy::const_iterator I = findPointerLowerBound(AS); + if (I == Pointers.end() || I->AddressSpace != AS) { + I = findPointerLowerBound(0); + assert(I->AddressSpace == 0); + } + return I->PrefAlign; +} + +unsigned DataLayout::getPointerSize(unsigned AS) const { + PointersTy::const_iterator I = findPointerLowerBound(AS); + if (I == Pointers.end() || I->AddressSpace != AS) { + I = findPointerLowerBound(0); + assert(I->AddressSpace == 0); + } + return I->TypeByteWidth; +} + +unsigned DataLayout::getMaxPointerSize() const { + unsigned MaxPointerSize = 0; + for (auto &P : Pointers) + MaxPointerSize = std::max(MaxPointerSize, P.TypeByteWidth); + + return MaxPointerSize; +} + +unsigned DataLayout::getPointerTypeSizeInBits(Type *Ty) const { + assert(Ty->isPtrOrPtrVectorTy() && + "This should only be called with a pointer or pointer vector type"); + Ty = Ty->getScalarType(); + return getPointerSizeInBits(cast<PointerType>(Ty)->getAddressSpace()); +} + +unsigned DataLayout::getIndexSize(unsigned AS) const { + PointersTy::const_iterator I = findPointerLowerBound(AS); + if (I == Pointers.end() || I->AddressSpace != AS) { + I = findPointerLowerBound(0); + assert(I->AddressSpace == 0); + } + return I->IndexWidth; +} + +unsigned DataLayout::getIndexTypeSizeInBits(Type *Ty) const { + assert(Ty->isPtrOrPtrVectorTy() && + "This should only be called with a pointer or pointer vector type"); + Ty = Ty->getScalarType(); + return getIndexSizeInBits(cast<PointerType>(Ty)->getAddressSpace()); +} + +/*! + \param abi_or_pref Flag that determines which alignment is returned. true + returns the ABI alignment, false returns the preferred alignment. + \param Ty The underlying type for which alignment is determined. + + Get the ABI (\a abi_or_pref == true) or preferred alignment (\a abi_or_pref + == false) for the requested type \a Ty. + */ +Align DataLayout::getAlignment(Type *Ty, bool abi_or_pref) const { + AlignTypeEnum AlignType; + + assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!"); + switch (Ty->getTypeID()) { + // Early escape for the non-numeric types. + case Type::LabelTyID: + return abi_or_pref ? getPointerABIAlignment(0) : getPointerPrefAlignment(0); + case Type::PointerTyID: { + unsigned AS = cast<PointerType>(Ty)->getAddressSpace(); + return abi_or_pref ? getPointerABIAlignment(AS) + : getPointerPrefAlignment(AS); + } + case Type::ArrayTyID: + return getAlignment(cast<ArrayType>(Ty)->getElementType(), abi_or_pref); + + case Type::StructTyID: { + // Packed structure types always have an ABI alignment of one. + if (cast<StructType>(Ty)->isPacked() && abi_or_pref) + return Align::None(); + + // Get the layout annotation... which is lazily created on demand. + const StructLayout *Layout = getStructLayout(cast<StructType>(Ty)); + const Align Align = getAlignmentInfo(AGGREGATE_ALIGN, 0, abi_or_pref, Ty); + return std::max(Align, Layout->getAlignment()); + } + case Type::IntegerTyID: + AlignType = INTEGER_ALIGN; + break; + case Type::HalfTyID: + case Type::FloatTyID: + case Type::DoubleTyID: + // PPC_FP128TyID and FP128TyID have different data contents, but the + // same size and alignment, so they look the same here. + case Type::PPC_FP128TyID: + case Type::FP128TyID: + case Type::X86_FP80TyID: + AlignType = FLOAT_ALIGN; + break; + case Type::X86_MMXTyID: + case Type::VectorTyID: + AlignType = VECTOR_ALIGN; + break; + default: + llvm_unreachable("Bad type for getAlignment!!!"); + } + + // If we're dealing with a scalable vector, we just need the known minimum + // size for determining alignment. If not, we'll get the exact size. + return getAlignmentInfo(AlignType, getTypeSizeInBits(Ty).getKnownMinSize(), + abi_or_pref, Ty); +} + +unsigned DataLayout::getABITypeAlignment(Type *Ty) const { + return getAlignment(Ty, true).value(); +} + +/// getABIIntegerTypeAlignment - Return the minimum ABI-required alignment for +/// an integer type of the specified bitwidth. +Align DataLayout::getABIIntegerTypeAlignment(unsigned BitWidth) const { + return getAlignmentInfo(INTEGER_ALIGN, BitWidth, true, nullptr); +} + +unsigned DataLayout::getPrefTypeAlignment(Type *Ty) const { + return getAlignment(Ty, false).value(); +} + +IntegerType *DataLayout::getIntPtrType(LLVMContext &C, + unsigned AddressSpace) const { + return IntegerType::get(C, getIndexSizeInBits(AddressSpace)); +} + +Type *DataLayout::getIntPtrType(Type *Ty) const { + assert(Ty->isPtrOrPtrVectorTy() && + "Expected a pointer or pointer vector type."); + unsigned NumBits = getIndexTypeSizeInBits(Ty); + IntegerType *IntTy = IntegerType::get(Ty->getContext(), NumBits); + if (VectorType *VecTy = dyn_cast<VectorType>(Ty)) + return VectorType::get(IntTy, VecTy->getNumElements()); + return IntTy; +} + +Type *DataLayout::getSmallestLegalIntType(LLVMContext &C, unsigned Width) const { + for (unsigned LegalIntWidth : LegalIntWidths) + if (Width <= LegalIntWidth) + return Type::getIntNTy(C, LegalIntWidth); + return nullptr; +} + +unsigned DataLayout::getLargestLegalIntTypeSizeInBits() const { + auto Max = std::max_element(LegalIntWidths.begin(), LegalIntWidths.end()); + return Max != LegalIntWidths.end() ? *Max : 0; +} + +Type *DataLayout::getIndexType(Type *Ty) const { + assert(Ty->isPtrOrPtrVectorTy() && + "Expected a pointer or pointer vector type."); + unsigned NumBits = getIndexTypeSizeInBits(Ty); + IntegerType *IntTy = IntegerType::get(Ty->getContext(), NumBits); + if (VectorType *VecTy = dyn_cast<VectorType>(Ty)) + return VectorType::get(IntTy, VecTy->getNumElements()); + return IntTy; +} + +int64_t DataLayout::getIndexedOffsetInType(Type *ElemTy, + ArrayRef<Value *> Indices) const { + int64_t Result = 0; + + generic_gep_type_iterator<Value* const*> + GTI = gep_type_begin(ElemTy, Indices), + GTE = gep_type_end(ElemTy, Indices); + for (; GTI != GTE; ++GTI) { + Value *Idx = GTI.getOperand(); + if (StructType *STy = GTI.getStructTypeOrNull()) { + assert(Idx->getType()->isIntegerTy(32) && "Illegal struct idx"); + unsigned FieldNo = cast<ConstantInt>(Idx)->getZExtValue(); + + // Get structure layout information... + const StructLayout *Layout = getStructLayout(STy); + + // Add in the offset, as calculated by the structure layout info... + Result += Layout->getElementOffset(FieldNo); + } else { + // Get the array index and the size of each array element. + if (int64_t arrayIdx = cast<ConstantInt>(Idx)->getSExtValue()) + Result += arrayIdx * getTypeAllocSize(GTI.getIndexedType()); + } + } + + return Result; +} + +/// getPreferredAlignment - Return the preferred alignment of the specified +/// global. This includes an explicitly requested alignment (if the global +/// has one). +unsigned DataLayout::getPreferredAlignment(const GlobalVariable *GV) const { + unsigned GVAlignment = GV->getAlignment(); + // If a section is specified, always precisely honor explicit alignment, + // so we don't insert padding into a section we don't control. + if (GVAlignment && GV->hasSection()) + return GVAlignment; + + // If no explicit alignment is specified, compute the alignment based on + // the IR type. If an alignment is specified, increase it to match the ABI + // alignment of the IR type. + // + // FIXME: Not sure it makes sense to use the alignment of the type if + // there's already an explicit alignment specification. + Type *ElemType = GV->getValueType(); + unsigned Alignment = getPrefTypeAlignment(ElemType); + if (GVAlignment >= Alignment) { + Alignment = GVAlignment; + } else if (GVAlignment != 0) { + Alignment = std::max(GVAlignment, getABITypeAlignment(ElemType)); + } + + // If no explicit alignment is specified, and the global is large, increase + // the alignment to 16. + // FIXME: Why 16, specifically? + if (GV->hasInitializer() && GVAlignment == 0) { + if (Alignment < 16) { + // If the global is not external, see if it is large. If so, give it a + // larger alignment. + if (getTypeSizeInBits(ElemType) > 128) + Alignment = 16; // 16-byte alignment. + } + } + return Alignment; +} + +/// getPreferredAlignmentLog - Return the preferred alignment of the +/// specified global, returned in log form. This includes an explicitly +/// requested alignment (if the global has one). +unsigned DataLayout::getPreferredAlignmentLog(const GlobalVariable *GV) const { + return Log2_32(getPreferredAlignment(GV)); +} |