1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 02:33:06 +01:00

[StructLayout] Use TrailingObjects to allocate space for MemberOffsets.

MemberOffsets are stored at the end of StructLayout. The class
contains a single entry array to mark the start of the member
offsets. getStructLayout calculates the additional space needed
for additional elements before allocating memory.

This patch converts this to use TrailingObjects. This simplifies
the size computation in getStructLayout and gets rid of the
single entry array.

This is prep work, but to use TypeSize instead of uint64_t for
D98169. The single entry array doesn't work with TypeSize because
TypeSize doesn't have a default constructor. We thought this
change was an improvement by itself so we've separated it out.

Reviewed By: mehdi_amini

Differential Revision: https://reviews.llvm.org/D99608
This commit is contained in:
Craig Topper 2021-03-30 16:43:12 -07:00
parent 950096655f
commit 58085bdcab
2 changed files with 25 additions and 13 deletions

View File

@ -29,6 +29,7 @@
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h" #include "llvm/Support/MathExtras.h"
#include "llvm/Support/Alignment.h" #include "llvm/Support/Alignment.h"
#include "llvm/Support/TrailingObjects.h"
#include "llvm/Support/TypeSize.h" #include "llvm/Support/TypeSize.h"
#include <cassert> #include <cassert>
#include <cstdint> #include <cstdint>
@ -619,12 +620,11 @@ inline LLVMTargetDataRef wrap(const DataLayout *P) {
/// Used to lazily calculate structure layout information for a target machine, /// Used to lazily calculate structure layout information for a target machine,
/// based on the DataLayout structure. /// based on the DataLayout structure.
class StructLayout { class StructLayout final : public TrailingObjects<StructLayout, uint64_t> {
uint64_t StructSize; uint64_t StructSize;
Align StructAlignment; Align StructAlignment;
unsigned IsPadded : 1; unsigned IsPadded : 1;
unsigned NumElements : 31; unsigned NumElements : 31;
uint64_t MemberOffsets[1]; // variable sized array!
public: public:
uint64_t getSizeInBytes() const { return StructSize; } uint64_t getSizeInBytes() const { return StructSize; }
@ -641,9 +641,18 @@ public:
/// index that contains it. /// index that contains it.
unsigned getElementContainingOffset(uint64_t Offset) const; 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 { uint64_t getElementOffset(unsigned Idx) const {
assert(Idx < NumElements && "Invalid element idx!"); assert(Idx < NumElements && "Invalid element idx!");
return MemberOffsets[Idx]; return getMemberOffsets()[Idx];
} }
uint64_t getElementOffsetInBits(unsigned Idx) const { uint64_t getElementOffsetInBits(unsigned Idx) const {
@ -654,6 +663,10 @@ private:
friend class DataLayout; // Only DataLayout can create this class friend class DataLayout; // Only DataLayout can create this class
StructLayout(StructType *ST, const DataLayout &DL); 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 // The implementation of this method is provided inline as it is particularly

View File

@ -64,7 +64,7 @@ StructLayout::StructLayout(StructType *ST, const DataLayout &DL) {
// Keep track of maximum alignment constraint. // Keep track of maximum alignment constraint.
StructAlignment = std::max(TyAlign, StructAlignment); StructAlignment = std::max(TyAlign, StructAlignment);
MemberOffsets[i] = StructSize; getMemberOffsets()[i] = StructSize;
// Consume space for this data item // Consume space for this data item
StructSize += DL.getTypeAllocSize(Ty).getFixedValue(); StructSize += DL.getTypeAllocSize(Ty).getFixedValue();
} }
@ -80,13 +80,13 @@ StructLayout::StructLayout(StructType *ST, const DataLayout &DL) {
/// getElementContainingOffset - Given a valid offset into the structure, /// getElementContainingOffset - Given a valid offset into the structure,
/// return the structure index that contains it. /// return the structure index that contains it.
unsigned StructLayout::getElementContainingOffset(uint64_t Offset) const { unsigned StructLayout::getElementContainingOffset(uint64_t Offset) const {
const uint64_t *SI = ArrayRef<uint64_t> MemberOffsets = getMemberOffsets();
std::upper_bound(&MemberOffsets[0], &MemberOffsets[NumElements], Offset); auto SI = llvm::upper_bound(MemberOffsets, Offset);
assert(SI != &MemberOffsets[0] && "Offset not in structure type!"); assert(SI != MemberOffsets.begin() && "Offset not in structure type!");
--SI; --SI;
assert(*SI <= Offset && "upper_bound didn't work"); assert(*SI <= Offset && "upper_bound didn't work");
assert((SI == &MemberOffsets[0] || *(SI-1) <= Offset) && assert((SI == MemberOffsets.begin() || *(SI - 1) <= Offset) &&
(SI+1 == &MemberOffsets[NumElements] || *(SI+1) > Offset) && (SI + 1 == MemberOffsets.end() || *(SI + 1) > Offset) &&
"Upper bound didn't work!"); "Upper bound didn't work!");
// Multiple fields can have the same offset if any of them are zero sized. // Multiple fields can have the same offset if any of them are zero sized.
@ -94,7 +94,7 @@ unsigned StructLayout::getElementContainingOffset(uint64_t Offset) const {
// at the i32 element, because it is the last element at that offset. This is // 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 // the right one to return, because anything after it will have a higher
// offset, implying that this element is non-empty. // offset, implying that this element is non-empty.
return SI-&MemberOffsets[0]; return SI - MemberOffsets.begin();
} }
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -678,9 +678,8 @@ const StructLayout *DataLayout::getStructLayout(StructType *Ty) const {
// Otherwise, create the struct layout. Because it is variable length, we // Otherwise, create the struct layout. Because it is variable length, we
// malloc it, then use placement new. // malloc it, then use placement new.
int NumElts = Ty->getNumElements(); StructLayout *L = (StructLayout *)safe_malloc(
StructLayout *L = (StructLayout *) StructLayout::totalSizeToAlloc<uint64_t>(Ty->getNumElements()));
safe_malloc(sizeof(StructLayout)+(NumElts-1) * sizeof(uint64_t));
// Set SL before calling StructLayout's ctor. The ctor could cause other // Set SL before calling StructLayout's ctor. The ctor could cause other
// entries to be added to TheMap, invalidating our reference. // entries to be added to TheMap, invalidating our reference.