X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FIR%2FDataLayout.cpp;h=5468f47bbfe62a3d8807d55265264858d0f05013;hp=7df867279b229f53c0a59337ff8541557a537811;hb=70b36591bc9e9f0772c62794bf1a202b1884aaf6;hpb=a9ad60c412327bc124258d4b9926436087e68ac4 diff --git a/lib/IR/DataLayout.cpp b/lib/IR/DataLayout.cpp index 7df867279b2..5468f47bbfe 100644 --- a/lib/IR/DataLayout.cpp +++ b/lib/IR/DataLayout.cpp @@ -22,9 +22,9 @@ #include "llvm/ADT/Triple.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/Module.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/GetElementPtrTypeIterator.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Mutex.h" @@ -33,12 +33,6 @@ #include using namespace llvm; -// Handle the Pass registration stuff necessary to use DataLayout's. - -// Register the default SparcV9 implementation... -INITIALIZE_PASS(DataLayout, "datalayout", "Data Layout", false, true) -char DataLayout::ID = 0; - //===----------------------------------------------------------------------===// // Support for StructLayout //===----------------------------------------------------------------------===// @@ -47,6 +41,7 @@ StructLayout::StructLayout(StructType *ST, const DataLayout &DL) { assert(!ST->isOpaque() && "Cannot get layout of opaque structs"); StructAlignment = 0; StructSize = 0; + IsPadded = false; NumElements = ST->getNumElements(); // Loop over each of the elements, placing them in memory. @@ -55,8 +50,10 @@ StructLayout::StructLayout(StructType *ST, const DataLayout &DL) { unsigned TyAlign = ST->isPacked() ? 1 : DL.getABITypeAlignment(Ty); // Add padding if necessary to align the data element properly. - if ((StructSize & (TyAlign-1)) != 0) - StructSize = DataLayout::RoundUpAlignment(StructSize, TyAlign); + if ((StructSize & (TyAlign-1)) != 0) { + IsPadded = true; + StructSize = RoundUpToAlignment(StructSize, TyAlign); + } // Keep track of maximum alignment constraint. StructAlignment = std::max(TyAlign, StructAlignment); @@ -70,8 +67,10 @@ StructLayout::StructLayout(StructType *ST, const DataLayout &DL) { // 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 ((StructSize & (StructAlignment-1)) != 0) - StructSize = DataLayout::RoundUpAlignment(StructSize, StructAlignment); + if ((StructSize & (StructAlignment-1)) != 0) { + IsPadded = true; + StructSize = RoundUpToAlignment(StructSize, StructAlignment); + } } @@ -156,10 +155,9 @@ DataLayout::InvalidPointerElem = { 0U, 0U, 0U, ~0U }; const char *DataLayout::getManglingComponent(const Triple &T) { if (T.isOSBinFormatMachO()) return "-m:o"; - if (T.isOSBinFormatELF() || T.isArch64Bit()) - return "-m:e"; - assert(T.isOSBinFormatCOFF()); - return "-m:w"; + if (T.isOSWindows() && T.isOSBinFormatCOFF()) + return T.getArch() == Triple::x86 ? "-m:x" : "-m:w"; + return "-m:e"; } static const LayoutAlignElem DefaultAlignments[] = { @@ -177,17 +175,16 @@ static const LayoutAlignElem DefaultAlignments[] = { { AGGREGATE_ALIGN, 0, 0, 8 } // struct }; -void DataLayout::init(StringRef Desc) { - initializeDataLayoutPass(*PassRegistry::getPassRegistry()); +void DataLayout::reset(StringRef Desc) { + clear(); - LayoutMap = 0; - LittleEndian = false; + LayoutMap = nullptr; + BigEndian = false; StackNaturalAlign = 0; ManglingMode = MM_None; // Default alignments - for (int I = 0, N = array_lengthof(DefaultAlignments); I < N; ++I) { - const LayoutAlignElem &E = DefaultAlignments[I]; + for (const LayoutAlignElem &E : DefaultAlignments) { setAlignment((AlignTypeEnum)E.AlignType, E.ABIAlign, E.PrefAlign, E.TypeBitWidth); } @@ -200,26 +197,31 @@ void DataLayout::init(StringRef Desc) { static std::pair split(StringRef Str, char Separator) { assert(!Str.empty() && "parse error, string can't be empty here"); std::pair Split = Str.split(Separator); - assert((!Split.second.empty() || Split.first == Str) && - "a trailing separator is not allowed"); + 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 = 0; + unsigned Result; bool error = R.getAsInteger(10, Result); (void)error; - assert(!error && "not a number, or does not fit in an unsigned int"); + 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) { - assert(Bits % 8 == 0 && "number of bits must be a byte width multiple"); + if (Bits % 8) + report_fatal_error("number of bits must be a byte width multiple"); return Bits / 8; } void DataLayout::parseSpecifier(StringRef Desc) { + StringRepresentation = Desc; while (!Desc.empty()) { // Split at '-'. std::pair Split = split(Desc, '-'); @@ -241,30 +243,44 @@ void DataLayout::parseSpecifier(StringRef Desc) { // FIXME: remove this on LLVM 4.0. break; case 'E': - LittleEndian = false; + BigEndian = true; break; case 'e': - LittleEndian = true; + BigEndian = false; break; case 'p': { // Address space. unsigned AddrSpace = Tok.empty() ? 0 : getInt(Tok); - assert(AddrSpace < 1 << 24 && - "Invalid address space, must be a 24bit integer"); + 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"); // 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"); } setPointerAlignment(AddrSpace, PointerABIAlign, PointerPrefAlign, @@ -287,12 +303,19 @@ void DataLayout::parseSpecifier(StringRef Desc) { // Bit size. unsigned Size = Tok.empty() ? 0 : getInt(Tok); - assert((AlignType != AGGREGATE_ALIGN || Size == 0) && - "These specifications don't have a size"); + 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, ':'); unsigned ABIAlign = inBytes(getInt(Tok)); + if (AlignType != AGGREGATE_ALIGN && !ABIAlign) + report_fatal_error( + "ABI alignment specification must be >0 for non-aggregate types"); // Preferred alignment. unsigned PrefAlign = ABIAlign; @@ -308,7 +331,9 @@ void DataLayout::parseSpecifier(StringRef Desc) { case 'n': // Native integer types. for (;;) { unsigned Width = getInt(Tok); - assert(Width != 0 && "width must be non-zero"); + if (Width == 0) + report_fatal_error( + "Zero width native integer type in datalayout string"); LegalIntWidths.push_back(Width); if (Rest.empty()) break; @@ -320,11 +345,15 @@ void DataLayout::parseSpecifier(StringRef Desc) { break; } case 'm': - assert(Tok.empty()); - assert(Rest.size() == 1); + 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: - llvm_unreachable("Unknown mangling in datalayout string"); + report_fatal_error("Unknown mangling in datalayout string"); case 'e': ManglingMode = MM_ELF; break; @@ -335,43 +364,60 @@ void DataLayout::parseSpecifier(StringRef Desc) { ManglingMode = MM_Mips; break; case 'w': - ManglingMode = MM_WINCOFF; + ManglingMode = MM_WinCOFF; + break; + case 'x': + ManglingMode = MM_WinCOFFX86; break; } break; default: - llvm_unreachable("Unknown specifier in datalayout string"); + report_fatal_error("Unknown specifier in datalayout string"); break; } } } -/// Default ctor. -/// -/// @note This has to exist, because this is a pass, but it should never be -/// used. -DataLayout::DataLayout() : ImmutablePass(ID) { - report_fatal_error("Bad DataLayout ctor used. " - "Tool did not specify a DataLayout to use?"); +DataLayout::DataLayout(const Module *M) : LayoutMap(nullptr) { + init(M); } -DataLayout::DataLayout(const Module *M) - : ImmutablePass(ID) { - init(M->getDataLayout()); +void DataLayout::init(const Module *M) { *this = M->getDataLayout(); } + +bool DataLayout::operator==(const DataLayout &Other) const { + bool Ret = BigEndian == Other.BigEndian && + StackNaturalAlign == Other.StackNaturalAlign && + ManglingMode == Other.ManglingMode && + LegalIntWidths == Other.LegalIntWidths && + Alignments == Other.Alignments && Pointers == Other.Pointers; + // Note: getStringRepresentation() might differs, it is not canonicalized + return Ret; } void DataLayout::setAlignment(AlignTypeEnum align_type, unsigned abi_align, unsigned pref_align, uint32_t bit_width) { - assert(abi_align <= pref_align && "Preferred alignment worse than ABI!"); - assert(pref_align < (1 << 16) && "Alignment doesn't fit in bitfield"); - assert(bit_width < (1 << 24) && "Bit width doesn't fit in bitfield"); - for (unsigned i = 0, e = Alignments.size(); i != e; ++i) { - if (Alignments[i].AlignType == (unsigned)align_type && - Alignments[i].TypeBitWidth == bit_width) { + if (!isUInt<24>(bit_width)) + report_fatal_error("Invalid bit width, must be a 24bit integer"); + if (!isUInt<16>(abi_align)) + report_fatal_error("Invalid ABI alignment, must be a 16bit integer"); + if (!isUInt<16>(pref_align)) + report_fatal_error("Invalid preferred alignment, must be a 16bit integer"); + if (abi_align != 0 && !isPowerOf2_64(abi_align)) + report_fatal_error("Invalid ABI alignment, must be a power of 2"); + if (pref_align != 0 && !isPowerOf2_64(pref_align)) + report_fatal_error("Invalid preferred alignment, must be a power of 2"); + + if (pref_align < abi_align) + report_fatal_error( + "Preferred alignment cannot be less than the ABI alignment"); + + for (LayoutAlignElem &Elem : Alignments) { + if (Elem.AlignType == (unsigned)align_type && + Elem.TypeBitWidth == bit_width) { // Update the abi, preferred alignments. - Alignments[i].ABIAlign = abi_align; - Alignments[i].PrefAlign = pref_align; + Elem.ABIAlign = abi_align; + Elem.PrefAlign = pref_align; return; } } @@ -380,18 +426,29 @@ DataLayout::setAlignment(AlignTypeEnum align_type, unsigned 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, unsigned ABIAlign, unsigned PrefAlign, uint32_t TypeByteWidth) { - assert(ABIAlign <= PrefAlign && "Preferred alignment worse than ABI!"); - DenseMap::iterator val = Pointers.find(AddrSpace); - if (val == Pointers.end()) { - Pointers[AddrSpace] = - PointerAlignElem::get(AddrSpace, ABIAlign, PrefAlign, TypeByteWidth); + 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)); } else { - val->second.ABIAlign = ABIAlign; - val->second.PrefAlign = PrefAlign; - val->second.TypeByteWidth = TypeByteWidth; + I->ABIAlign = ABIAlign; + I->PrefAlign = PrefAlign; + I->TypeByteWidth = TypeByteWidth; } } @@ -409,8 +466,8 @@ unsigned DataLayout::getAlignmentInfo(AlignTypeEnum AlignType, return ABIInfo ? Alignments[i].ABIAlign : Alignments[i].PrefAlign; // The best match so far depends on what we're looking for. - if (AlignType == INTEGER_ALIGN && - Alignments[i].AlignType == INTEGER_ALIGN) { + if (AlignType == INTEGER_ALIGN && + Alignments[i].AlignType == INTEGER_ALIGN) { // The "best match" for integers is the smallest size that is larger than // the BitWidth requested. if (Alignments[i].TypeBitWidth > BitWidth && (BestMatchIdx == -1 || @@ -430,9 +487,7 @@ unsigned DataLayout::getAlignmentInfo(AlignTypeEnum AlignType, // If we didn't find an integer alignment, fall back on most conservative. if (AlignType == INTEGER_ALIGN) { BestMatchIdx = LargestInt; - } else { - assert(AlignType == VECTOR_ALIGN && "Unknown alignment type!"); - + } else if (AlignType == VECTOR_ALIGN) { // By default, use natural alignment for vector types. This is consistent // with what clang and llvm-gcc do. unsigned Align = getTypeAllocSize(cast(Ty)->getElementType()); @@ -445,6 +500,19 @@ unsigned DataLayout::getAlignmentInfo(AlignTypeEnum AlignType, } } + // 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. + if (BestMatchIdx == -1) { + unsigned Align = getTypeStoreSize(Ty); + if (Align & (Align-1)) + Align = NextPowerOf2(Align); + return Align; + } + // Since we got a "best match" index, just return it. return ABIInfo ? Alignments[BestMatchIdx].ABIAlign : Alignments[BestMatchIdx].PrefAlign; @@ -457,11 +525,10 @@ class StructLayoutMap { LayoutInfoTy LayoutInfo; public: - virtual ~StructLayoutMap() { + ~StructLayoutMap() { // Remove any layouts. - for (LayoutInfoTy::iterator I = LayoutInfo.begin(), E = LayoutInfo.end(); - I != E; ++I) { - StructLayout *Value = I->second; + for (const auto &I : LayoutInfo) { + StructLayout *Value = I.second; Value->~StructLayout(); free(Value); } @@ -470,21 +537,20 @@ public: StructLayout *&operator[](StructType *STy) { return LayoutInfo[STy]; } - - // for debugging... - virtual void dump() const {} }; } // end anonymous namespace -DataLayout::~DataLayout() { - delete static_cast(LayoutMap); +void DataLayout::clear() { + LegalIntWidths.clear(); + Alignments.clear(); + Pointers.clear(); + delete static_cast(LayoutMap); + LayoutMap = nullptr; } -bool DataLayout::doFinalization(Module &M) { - delete static_cast(LayoutMap); - LayoutMap = 0; - return false; +DataLayout::~DataLayout() { + clear(); } const StructLayout *DataLayout::getStructLayout(StructType *Ty) const { @@ -510,83 +576,32 @@ const StructLayout *DataLayout::getStructLayout(StructType *Ty) const { return L; } -std::string DataLayout::getStringRepresentation() const { - std::string Result; - raw_string_ostream OS(Result); - - OS << (LittleEndian ? "e" : "E"); - - switch (ManglingMode) { - case MM_None: - break; - case MM_ELF: - OS << "-m:e"; - break; - case MM_MachO: - OS << "-m:o"; - break; - case MM_WINCOFF: - OS << "-m:w"; - break; - case MM_Mips: - OS << "-m:m"; - break; - } - SmallVector addrSpaces; - // Lets get all of the known address spaces and sort them - // into increasing order so that we can emit the string - // in a cleaner format. - for (DenseMap::const_iterator - pib = Pointers.begin(), pie = Pointers.end(); - pib != pie; ++pib) { - addrSpaces.push_back(pib->first); - } - std::sort(addrSpaces.begin(), addrSpaces.end()); - for (SmallVectorImpl::iterator asb = addrSpaces.begin(), - ase = addrSpaces.end(); asb != ase; ++asb) { - const PointerAlignElem &PI = Pointers.find(*asb)->second; - - // Skip default. - if (PI.AddressSpace == 0 && PI.ABIAlign == 8 && PI.PrefAlign == 8 && - PI.TypeByteWidth == 8) - continue; - - OS << "-p"; - if (PI.AddressSpace) { - OS << PI.AddressSpace; - } - OS << ":" << PI.TypeByteWidth*8 << ':' << PI.ABIAlign*8; - if (PI.PrefAlign != PI.ABIAlign) - OS << ':' << PI.PrefAlign*8; +unsigned 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; +} - const LayoutAlignElem *DefaultStart = DefaultAlignments; - const LayoutAlignElem *DefaultEnd = - DefaultStart + array_lengthof(DefaultAlignments); - for (unsigned i = 0, e = Alignments.size(); i != e; ++i) { - const LayoutAlignElem &AI = Alignments[i]; - if (std::find(DefaultStart, DefaultEnd, AI) != DefaultEnd) - continue; - OS << '-' << (char)AI.AlignType; - if (AI.TypeBitWidth) - OS << AI.TypeBitWidth; - OS << ':' << AI.ABIAlign*8; - if (AI.ABIAlign != AI.PrefAlign) - OS << ':' << AI.PrefAlign*8; +unsigned 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; +} - if (!LegalIntWidths.empty()) { - OS << "-n" << (unsigned)LegalIntWidths[0]; - - for (unsigned i = 1, e = LegalIntWidths.size(); i != e; ++i) - OS << ':' << (unsigned)LegalIntWidths[i]; +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); } - - if (StackNaturalAlign) - OS << "-S" << StackNaturalAlign*8; - - return OS.str(); + return I->TypeByteWidth; } unsigned DataLayout::getPointerTypeSizeInBits(Type *Ty) const { @@ -618,7 +633,7 @@ unsigned DataLayout::getAlignment(Type *Ty, bool abi_or_pref) const { ? getPointerABIAlignment(0) : getPointerPrefAlignment(0)); case Type::PointerTyID: { - unsigned AS = dyn_cast(Ty)->getAddressSpace(); + unsigned AS = cast(Ty)->getAddressSpace(); return (abi_or_pref ? getPointerABIAlignment(AS) : getPointerPrefAlignment(AS)); @@ -668,7 +683,7 @@ unsigned DataLayout::getABITypeAlignment(Type *Ty) const { /// getABIIntegerTypeAlignment - Return the minimum ABI-required alignment for /// an integer type of the specified bitwidth. unsigned DataLayout::getABIIntegerTypeAlignment(unsigned BitWidth) const { - return getAlignmentInfo(INTEGER_ALIGN, BitWidth, true, 0); + return getAlignmentInfo(INTEGER_ALIGN, BitWidth, true, nullptr); } unsigned DataLayout::getPrefTypeAlignment(Type *Ty) const { @@ -689,7 +704,7 @@ IntegerType *DataLayout::getIntPtrType(LLVMContext &C, Type *DataLayout::getIntPtrType(Type *Ty) const { assert(Ty->isPtrOrPtrVectorTy() && "Expected a pointer or pointer vector type."); - unsigned NumBits = getTypeSizeInBits(Ty->getScalarType()); + unsigned NumBits = getPointerTypeSizeInBits(Ty); IntegerType *IntTy = IntegerType::get(Ty->getContext(), NumBits); if (VectorType *VecTy = dyn_cast(Ty)) return VectorType::get(IntTy, VecTy->getNumElements()); @@ -697,17 +712,15 @@ Type *DataLayout::getIntPtrType(Type *Ty) const { } Type *DataLayout::getSmallestLegalIntType(LLVMContext &C, unsigned Width) const { - for (unsigned i = 0, e = (unsigned)LegalIntWidths.size(); i != e; ++i) - if (Width <= LegalIntWidths[i]) - return Type::getIntNTy(C, LegalIntWidths[i]); - return 0; + for (unsigned LegalIntWidth : LegalIntWidths) + if (Width <= LegalIntWidth) + return Type::getIntNTy(C, LegalIntWidth); + return nullptr; } unsigned DataLayout::getLargestLegalIntTypeSize() const { - unsigned MaxWidth = 0; - for (unsigned i = 0, e = (unsigned)LegalIntWidths.size(); i != e; ++i) - MaxWidth = std::max(MaxWidth, LegalIntWidths[i]); - return MaxWidth; + auto Max = std::max_element(LegalIntWidths.begin(), LegalIntWidths.end()); + return Max != LegalIntWidths.end() ? *Max : 0; } uint64_t DataLayout::getIndexedOffset(Type *ptrTy, @@ -777,3 +790,4 @@ unsigned DataLayout::getPreferredAlignment(const GlobalVariable *GV) const { unsigned DataLayout::getPreferredAlignmentLog(const GlobalVariable *GV) const { return Log2_32(getPreferredAlignment(GV)); } +