#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 <cassert>
#include <cstdint>
/// Used to lazily calculate structure layout information for a target machine,
/// based on the DataLayout structure.
-class StructLayout {
+class StructLayout final : public TrailingObjects<StructLayout, uint64_t> {
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; }
/// index that contains it.
unsigned getElementContainingOffset(uint64_t Offset) const;
+ MutableArrayRef<uint64_t> getMemberOffsets() {
+ return llvm::makeMutableArrayRef(getTrailingObjects<uint64_t>(),
+ NumElements);
+ }
+
+ ArrayRef<uint64_t> getMemberOffsets() const {
+ return llvm::makeArrayRef(getTrailingObjects<uint64_t>(), 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 {
friend class DataLayout; // Only DataLayout can create this class
StructLayout(StructType *ST, const DataLayout &DL);
+
+ size_t numTrailingObjects(OverloadToken<uint64_t>) const {
+ return NumElements;
+ }
};
// The implementation of this method is provided inline as it is particularly
// 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();
}
/// 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<uint64_t> 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.
// 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();
}
//===----------------------------------------------------------------------===//
// 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<uint64_t>(Ty->getNumElements()));
// Set SL before calling StructLayout's ctor. The ctor could cause other
// entries to be added to TheMap, invalidating our reference.