[llvm] f59ba08 - [StructLayout] Use TrailingObjects to allocate space for MemberOffsets.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 30 17:37:44 PDT 2021


Author: Craig Topper
Date: 2021-03-30T17:36:50-07:00
New Revision: f59ba0849f7a148265dcc89d36a11717d365f368

URL: https://github.com/llvm/llvm-project/commit/f59ba0849f7a148265dcc89d36a11717d365f368
DIFF: https://github.com/llvm/llvm-project/commit/f59ba0849f7a148265dcc89d36a11717d365f368.diff

LOG: [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

Added: 
    

Modified: 
    llvm/include/llvm/IR/DataLayout.h
    llvm/lib/IR/DataLayout.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/DataLayout.h b/llvm/include/llvm/IR/DataLayout.h
index eae409e75293..80bb349d3e28 100644
--- 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 <cassert>
 #include <cstdint>
@@ -619,12 +620,11 @@ inline LLVMTargetDataRef wrap(const DataLayout *P) {
 
 /// 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; }
@@ -641,9 +641,18 @@ class StructLayout {
   /// 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 {
@@ -654,6 +663,10 @@ class StructLayout {
   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

diff  --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp
index 274ea0aa5fd1..ecd74449dc38 100644
--- a/llvm/lib/IR/DataLayout.cpp
+++ b/llvm/lib/IR/DataLayout.cpp
@@ -64,7 +64,7 @@ StructLayout::StructLayout(StructType *ST, const DataLayout &DL) {
     // 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 @@ StructLayout::StructLayout(StructType *ST, const DataLayout &DL) {
 /// 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.
@@ -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
   // 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 @@ const StructLayout *DataLayout::getStructLayout(StructType *Ty) const {
 
   // 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.


        


More information about the llvm-commits mailing list