[clang] [NFC] Refactor ConstantArrayType size storage (PR #85716)

Eli Friedman via cfe-commits cfe-commits at lists.llvm.org
Mon Mar 25 14:58:35 PDT 2024


================
@@ -3182,34 +3182,100 @@ class ArrayType : public Type, public llvm::FoldingSetNode {
 /// For example, the canonical type for 'int A[4 + 4*100]' is a
 /// ConstantArrayType where the element type is 'int' and the size is 404.
 class ConstantArrayType final
-    : public ArrayType,
-      private llvm::TrailingObjects<ConstantArrayType, const Expr *> {
+    : public ArrayType {
   friend class ASTContext; // ASTContext creates these.
-  friend TrailingObjects;
 
-  llvm::APInt Size; // Allows us to unique the type.
+  struct ExternalSize {
+    ExternalSize(const llvm::APInt &Sz, const Expr *SE)
+        : Size(Sz), SizeExpr(SE) {}
+    llvm::APInt Size; // Allows us to unique the type.
+    const Expr *SizeExpr;
+  };
+  struct InlineSize {
+    InlineSize(uint64_t TSz, uint64_t Sz) : ByteWidth(TSz), Size(Sz) {}
+    uint64_t ByteWidth : 4;
+    uint64_t Size : 60;
+  };
+  union {
+    struct InlineSize I;
+    ExternalSize *SizePtr;
+  };
 
-  ConstantArrayType(QualType et, QualType can, const llvm::APInt &size,
-                    const Expr *sz, ArraySizeModifier sm, unsigned tq)
-      : ArrayType(ConstantArray, et, can, sm, tq, sz), Size(size) {
-    ConstantArrayTypeBits.HasStoredSizeExpr = sz != nullptr;
-    if (ConstantArrayTypeBits.HasStoredSizeExpr) {
-      assert(!can.isNull() && "canonical constant array should not have size");
-      *getTrailingObjects<const Expr*>() = sz;
-    }
+  ConstantArrayType(QualType Et, QualType Can, uint64_t Width, uint64_t Sz,
+                    ArraySizeModifier SM, unsigned TQ)
+      : ArrayType(ConstantArray, Et, Can, SM, TQ, nullptr), I(Width / 8, Sz) {
+    ConstantArrayTypeBits.HasExternalSize = false;
+    assert(Sz < 0x0FFFFFFFFFFFFFFF && "Size must fit in 60 bits");
+    // The in-structure size stores the size in bytes rather than bits so we
+    // drop the four least significant bits since they're always zero anyways.
+    assert(Width < 0xFF && "Type width must fit in 8 bits");
   }
 
-  unsigned numTrailingObjects(OverloadToken<const Expr*>) const {
-    return ConstantArrayTypeBits.HasStoredSizeExpr;
+  ConstantArrayType(QualType Et, QualType Can, ExternalSize *SzPtr,
+                    ArraySizeModifier SM, unsigned TQ)
+      : ArrayType(ConstantArray, Et, Can, SM, TQ, SzPtr->SizeExpr),
+        SizePtr(SzPtr) {
+    ConstantArrayTypeBits.HasExternalSize = true;
+
+    assert((SzPtr->SizeExpr == nullptr || !Can.isNull()) &&
+           "canonical constant array should not have size expression");
   }
 
+  static ConstantArrayType *Create(const ASTContext &Ctx, QualType ET,
+                                   QualType Can, const llvm::APInt &Sz,
+                                   const Expr *SzExpr, ArraySizeModifier SzMod,
+                                   unsigned Qual);
+
 public:
-  const llvm::APInt &getSize() const { return Size; }
+  /// Return the constant array size as an APInt.
+  llvm::APInt getSize() const {
+    return ConstantArrayTypeBits.HasExternalSize
+               ? SizePtr->Size
+               : llvm::APInt(I.ByteWidth * 8, I.Size);
+  }
+
+  /// Return the bit width of the size type.
+  unsigned getSizeBitWidth() const {
+    return ConstantArrayTypeBits.HasExternalSize
+               ? SizePtr->Size.getBitWidth()
+               : static_cast<unsigned>(I.ByteWidth * 8);
+  }
+
+  /// Return true if the size is zero.
+  bool isZeroSize() const {
+    return ConstantArrayTypeBits.HasExternalSize ? SizePtr->Size.isZero()
+                                                   : 0 == I.Size;
+  }
+
+  /// Return the size zero-extended as a uint64_t.
+  uint64_t getZExtSize() const {
+    return ConstantArrayTypeBits.HasExternalSize
+               ? SizePtr->Size.getZExtValue()
+               : I.Size;
+  }
+
+  /// Return the size zero-extended as a uint64_t.
----------------
efriedma-quic wrote:

Sign-extended

https://github.com/llvm/llvm-project/pull/85716


More information about the cfe-commits mailing list