diff --git a/llvm/include/llvm/IR/DataLayout.h b/llvm/include/llvm/IR/DataLayout.h --- a/llvm/include/llvm/IR/DataLayout.h +++ b/llvm/include/llvm/IR/DataLayout.h @@ -29,6 +29,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Alignment.h" +#include "llvm/Support/TrailingObjects.h" #include "llvm/Support/TypeSize.h" #include #include @@ -619,12 +620,11 @@ /// Used to lazily calculate structure layout information for a target machine, /// based on the DataLayout structure. -class StructLayout { +class StructLayout final : public TrailingObjects { uint64_t StructSize; Align StructAlignment; unsigned IsPadded : 1; unsigned NumElements : 31; - uint64_t MemberOffsets[1]; // variable sized array! public: uint64_t getSizeInBytes() const { return StructSize; } @@ -641,9 +641,18 @@ /// index that contains it. unsigned getElementContainingOffset(uint64_t Offset) const; + MutableArrayRef getMemberOffsets() { + return llvm::makeMutableArrayRef(getTrailingObjects(), + NumElements); + } + + ArrayRef getMemberOffsets() const { + return llvm::makeArrayRef(getTrailingObjects(), NumElements); + } + uint64_t getElementOffset(unsigned Idx) const { assert(Idx < NumElements && "Invalid element idx!"); - return MemberOffsets[Idx]; + return getMemberOffsets()[Idx]; } uint64_t getElementOffsetInBits(unsigned Idx) const { @@ -654,6 +663,10 @@ friend class DataLayout; // Only DataLayout can create this class StructLayout(StructType *ST, const DataLayout &DL); + + size_t numTrailingObjects(OverloadToken) const { + return NumElements; + } }; // The implementation of this method is provided inline as it is particularly diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp --- a/llvm/lib/IR/DataLayout.cpp +++ b/llvm/lib/IR/DataLayout.cpp @@ -64,7 +64,7 @@ // Keep track of maximum alignment constraint. StructAlignment = std::max(TyAlign, StructAlignment); - MemberOffsets[i] = StructSize; + getMemberOffsets()[i] = StructSize; // Consume space for this data item StructSize += DL.getTypeAllocSize(Ty).getFixedValue(); } @@ -80,13 +80,13 @@ /// 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!"); + ArrayRef MemberOffsets = getMemberOffsets(); + auto SI = llvm::upper_bound(MemberOffsets, Offset); + assert(SI != MemberOffsets.begin() && "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) && + assert((SI == MemberOffsets.begin() || *(SI - 1) <= Offset) && + (SI + 1 == MemberOffsets.end() || *(SI + 1) > Offset) && "Upper bound didn't work!"); // Multiple fields can have the same offset if any of them are zero sized. @@ -94,7 +94,7 @@ // 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]; + return SI - MemberOffsets.begin(); } //===----------------------------------------------------------------------===// @@ -678,9 +678,8 @@ // 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)); + StructLayout *L = (StructLayout *)safe_malloc( + StructLayout::totalSizeToAlloc(Ty->getNumElements())); // Set SL before calling StructLayout's ctor. The ctor could cause other // entries to be added to TheMap, invalidating our reference.