diff options
Diffstat (limited to 'lib/IR/DataLayout.cpp')
-rw-r--r-- | lib/IR/DataLayout.cpp | 163 |
1 files changed, 83 insertions, 80 deletions
diff --git a/lib/IR/DataLayout.cpp b/lib/IR/DataLayout.cpp index 6e0ebbd4a730..5fe7a2e94b6a 100644 --- a/lib/IR/DataLayout.cpp +++ b/lib/IR/DataLayout.cpp @@ -29,6 +29,7 @@ #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> @@ -44,7 +45,6 @@ using namespace llvm; 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(); @@ -52,10 +52,10 @@ StructLayout::StructLayout(StructType *ST, const DataLayout &DL) { // Loop over each of the elements, placing them in memory. for (unsigned i = 0, e = NumElements; i != e; ++i) { Type *Ty = ST->getElementType(i); - unsigned TyAlign = ST->isPacked() ? 1 : DL.getABITypeAlignment(Ty); + const Align TyAlign(ST->isPacked() ? 1 : DL.getABITypeAlignment(Ty)); // Add padding if necessary to align the data element properly. - if ((StructSize & (TyAlign-1)) != 0) { + if (!isAligned(TyAlign, StructSize)) { IsPadded = true; StructSize = alignTo(StructSize, TyAlign); } @@ -67,12 +67,9 @@ StructLayout::StructLayout(StructType *ST, const DataLayout &DL) { StructSize += DL.getTypeAllocSize(Ty); // Consume space for this data item } - // Empty structures have alignment of 1 byte. - if (StructAlignment == 0) StructAlignment = 1; - // 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) { + if (!isAligned(StructAlignment, StructSize)) { IsPadded = true; StructSize = alignTo(StructSize, StructAlignment); } @@ -102,9 +99,8 @@ unsigned StructLayout::getElementContainingOffset(uint64_t Offset) const { // LayoutAlignElem, LayoutAlign support //===----------------------------------------------------------------------===// -LayoutAlignElem -LayoutAlignElem::get(AlignTypeEnum align_type, unsigned abi_align, - unsigned pref_align, uint32_t bit_width) { +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; @@ -126,10 +122,9 @@ LayoutAlignElem::operator==(const LayoutAlignElem &rhs) const { // PointerAlignElem, PointerAlign support //===----------------------------------------------------------------------===// -PointerAlignElem -PointerAlignElem::get(uint32_t AddressSpace, unsigned ABIAlign, - unsigned PrefAlign, uint32_t TypeByteWidth, - uint32_t IndexWidth) { +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; @@ -162,18 +157,18 @@ const char *DataLayout::getManglingComponent(const Triple &T) { } static const LayoutAlignElem DefaultAlignments[] = { - { INTEGER_ALIGN, 1, 1, 1 }, // i1 - { INTEGER_ALIGN, 8, 1, 1 }, // i8 - { INTEGER_ALIGN, 16, 2, 2 }, // i16 - { INTEGER_ALIGN, 32, 4, 4 }, // i32 - { INTEGER_ALIGN, 64, 4, 8 }, // i64 - { FLOAT_ALIGN, 16, 2, 2 }, // half - { FLOAT_ALIGN, 32, 4, 4 }, // float - { FLOAT_ALIGN, 64, 8, 8 }, // double - { FLOAT_ALIGN, 128, 16, 16 }, // ppcf128, quad, ... - { VECTOR_ALIGN, 64, 8, 8 }, // v2i32, v1i64, ... - { VECTOR_ALIGN, 128, 16, 16 }, // v16i8, v8i16, v4i32, ... - { AGGREGATE_ALIGN, 0, 0, 8 } // struct + {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) { @@ -182,9 +177,9 @@ void DataLayout::reset(StringRef Desc) { LayoutMap = nullptr; BigEndian = false; AllocaAddrSpace = 0; - StackNaturalAlign = 0; + StackNaturalAlign.reset(); ProgramAddrSpace = 0; - FunctionPtrAlign = 0; + FunctionPtrAlign.reset(); TheFunctionPtrAlignType = FunctionPtrAlignType::Independent; ManglingMode = MM_None; NonIntegralAddressSpaces.clear(); @@ -194,7 +189,7 @@ void DataLayout::reset(StringRef Desc) { setAlignment((AlignTypeEnum)E.AlignType, E.ABIAlign, E.PrefAlign, E.TypeBitWidth); } - setPointerAlignment(0, 8, 8, 8, 8); + setPointerAlignment(0, Align(8), Align(8), 8, 8); parseSpecifier(Desc); } @@ -320,8 +315,9 @@ void DataLayout::parseSpecifier(StringRef Desc) { report_fatal_error("Invalid index size of 0 bytes"); } } - setPointerAlignment(AddrSpace, PointerABIAlign, PointerPrefAlign, - PointerMemSize, IndexSize); + setPointerAlignment(AddrSpace, assumeAligned(PointerABIAlign), + assumeAligned(PointerPrefAlign), PointerMemSize, + IndexSize); break; } case 'i': @@ -349,11 +345,16 @@ void DataLayout::parseSpecifier(StringRef Desc) { report_fatal_error( "Missing alignment specification in datalayout string"); Split = split(Rest, ':'); - unsigned ABIAlign = inBytes(getInt(Tok)); + 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()) { @@ -361,7 +362,14 @@ void DataLayout::parseSpecifier(StringRef Desc) { PrefAlign = inBytes(getInt(Tok)); } - setAlignment(AlignType, ABIAlign, PrefAlign, Size); + 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; } @@ -378,7 +386,10 @@ void DataLayout::parseSpecifier(StringRef Desc) { } break; case 'S': { // Stack natural alignment. - StackNaturalAlign = inBytes(getInt(Tok)); + 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': { @@ -394,7 +405,10 @@ void DataLayout::parseSpecifier(StringRef Desc) { "datalayout string"); } Tok = Tok.substr(1); - FunctionPtrAlign = inBytes(getInt(Tok)); + 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. @@ -468,20 +482,15 @@ DataLayout::findAlignmentLowerBound(AlignTypeEnum AlignType, }); } -void -DataLayout::setAlignment(AlignTypeEnum align_type, unsigned abi_align, - unsigned pref_align, uint32_t bit_width) { +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 (!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"); @@ -507,8 +516,8 @@ DataLayout::findPointerLowerBound(uint32_t AddressSpace) { }); } -void DataLayout::setPointerAlignment(uint32_t AddrSpace, unsigned ABIAlign, - unsigned PrefAlign, uint32_t TypeByteWidth, +void DataLayout::setPointerAlignment(uint32_t AddrSpace, Align ABIAlign, + Align PrefAlign, uint32_t TypeByteWidth, uint32_t IndexWidth) { if (PrefAlign < ABIAlign) report_fatal_error( @@ -528,9 +537,8 @@ void DataLayout::setPointerAlignment(uint32_t AddrSpace, unsigned ABIAlign, /// getAlignmentInfo - Return the alignment (either ABI if ABIInfo = true or /// preferred if ABIInfo = false) the layout wants for the specified datatype. -unsigned DataLayout::getAlignmentInfo(AlignTypeEnum AlignType, - uint32_t BitWidth, bool ABIInfo, - Type *Ty) const { +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 @@ -549,10 +557,11 @@ unsigned DataLayout::getAlignmentInfo(AlignTypeEnum AlignType, } 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<VectorType>(Ty)->getElementType()); - Align *= cast<VectorType>(Ty)->getNumElements(); - Align = PowerOf2Ceil(Align); - return Align; + 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 @@ -561,9 +570,9 @@ unsigned DataLayout::getAlignmentInfo(AlignTypeEnum AlignType, // approximation of reality, and if the user wanted something less // less conservative, they should have specified it explicitly in the data // layout. - unsigned Align = getTypeStoreSize(Ty); - Align = PowerOf2Ceil(Align); - return Align; + unsigned Alignment = getTypeStoreSize(Ty); + Alignment = PowerOf2Ceil(Alignment); + return Align(Alignment); } namespace { @@ -624,7 +633,7 @@ const StructLayout *DataLayout::getStructLayout(StructType *Ty) const { return L; } -unsigned DataLayout::getPointerABIAlignment(unsigned AS) const { +Align DataLayout::getPointerABIAlignment(unsigned AS) const { PointersTy::const_iterator I = findPointerLowerBound(AS); if (I == Pointers.end() || I->AddressSpace != AS) { I = findPointerLowerBound(0); @@ -633,7 +642,7 @@ unsigned DataLayout::getPointerABIAlignment(unsigned AS) const { return I->ABIAlign; } -unsigned DataLayout::getPointerPrefAlignment(unsigned AS) const { +Align DataLayout::getPointerPrefAlignment(unsigned AS) const { PointersTy::const_iterator I = findPointerLowerBound(AS); if (I == Pointers.end() || I->AddressSpace != AS) { I = findPointerLowerBound(0); @@ -690,21 +699,18 @@ unsigned DataLayout::getIndexTypeSizeInBits(Type *Ty) const { Get the ABI (\a abi_or_pref == true) or preferred alignment (\a abi_or_pref == false) for the requested type \a Ty. */ -unsigned DataLayout::getAlignment(Type *Ty, bool abi_or_pref) const { +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)); + 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)); + return abi_or_pref ? getPointerABIAlignment(AS) + : getPointerPrefAlignment(AS); } case Type::ArrayTyID: return getAlignment(cast<ArrayType>(Ty)->getElementType(), abi_or_pref); @@ -712,11 +718,11 @@ unsigned DataLayout::getAlignment(Type *Ty, bool abi_or_pref) const { case Type::StructTyID: { // Packed structure types always have an ABI alignment of one. if (cast<StructType>(Ty)->isPacked() && abi_or_pref) - return 1; + return Align::None(); // Get the layout annotation... which is lazily created on demand. const StructLayout *Layout = getStructLayout(cast<StructType>(Ty)); - unsigned Align = getAlignmentInfo(AGGREGATE_ALIGN, 0, abi_or_pref, Ty); + const Align Align = getAlignmentInfo(AGGREGATE_ALIGN, 0, abi_or_pref, Ty); return std::max(Align, Layout->getAlignment()); } case Type::IntegerTyID: @@ -740,27 +746,24 @@ unsigned DataLayout::getAlignment(Type *Ty, bool abi_or_pref) const { llvm_unreachable("Bad type for getAlignment!!!"); } - return getAlignmentInfo(AlignType, getTypeSizeInBits(Ty), abi_or_pref, Ty); + // 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); + return getAlignment(Ty, true).value(); } /// getABIIntegerTypeAlignment - Return the minimum ABI-required alignment for /// an integer type of the specified bitwidth. -unsigned DataLayout::getABIIntegerTypeAlignment(unsigned BitWidth) const { +Align DataLayout::getABIIntegerTypeAlignment(unsigned BitWidth) const { return getAlignmentInfo(INTEGER_ALIGN, BitWidth, true, nullptr); } unsigned DataLayout::getPrefTypeAlignment(Type *Ty) const { - return getAlignment(Ty, false); -} - -unsigned DataLayout::getPreferredTypeAlignmentShift(Type *Ty) const { - unsigned Align = getPrefTypeAlignment(Ty); - assert(!(Align & (Align-1)) && "Alignment is not a power of two!"); - return Log2_32(Align); + return getAlignment(Ty, false).value(); } IntegerType *DataLayout::getIntPtrType(LLVMContext &C, |