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:
parent
950096655f
commit
58085bdcab
@ -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
|
||||||
|
@ -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.
|
||||||
|
Loading…
Reference in New Issue
Block a user