[llvm] [NFC][TableGen] Make TrailingObjects private for Records (PR #138027)

via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 30 22:50:46 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-tablegen

Author: Rahul Joshi (jurahul)

<details>
<summary>Changes</summary>

- Use private inheritance for `TrailingObjects` as suggested in the documentation for `TrailingObjects` class.
- Move std::uninitialized_copy calls from various `get` functions to the constructors of respective classes.
- Eliminate `NumArgNames` from `DagInit`. Its always equal to `NumArgs`.
- Eliminate unused `name_size/name_empty` from `DagInit`.

---

Patch is 20.17 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/138027.diff


2 Files Affected:

- (modified) llvm/include/llvm/TableGen/Record.h (+32-49) 
- (modified) llvm/lib/TableGen/Record.cpp (+85-65) 


``````````diff
diff --git a/llvm/include/llvm/TableGen/Record.h b/llvm/include/llvm/TableGen/Record.h
index 0a10f6a74d009..28d7fcddcc1b1 100644
--- a/llvm/include/llvm/TableGen/Record.h
+++ b/llvm/include/llvm/TableGen/Record.h
@@ -230,14 +230,14 @@ class DagRecTy : public RecTy {
 /// are not the superclass of some other listed class.
 class RecordRecTy final : public RecTy,
                           public FoldingSetNode,
-                          public TrailingObjects<RecordRecTy, const Record *> {
+                          private TrailingObjects<RecordRecTy, const Record *> {
+  friend TrailingObjects;
   friend class Record;
   friend detail::RecordKeeperImpl;
 
   unsigned NumClasses;
 
-  explicit RecordRecTy(RecordKeeper &RK, unsigned Num)
-      : RecTy(RecordRecTyKind, RK), NumClasses(Num) {}
+  explicit RecordRecTy(RecordKeeper &RK, ArrayRef<const Record *> Classes);
 
 public:
   RecordRecTy(const RecordRecTy &) = delete;
@@ -587,11 +587,11 @@ class BitInit final : public TypedInit {
 /// It contains a vector of bits, whose size is determined by the type.
 class BitsInit final : public TypedInit,
                        public FoldingSetNode,
-                       public TrailingObjects<BitsInit, const Init *> {
+                       private TrailingObjects<BitsInit, const Init *> {
+  friend TrailingObjects;
   unsigned NumBits;
 
-  BitsInit(RecordKeeper &RK, unsigned N)
-      : TypedInit(IK_BitsInit, BitsRecTy::get(RK, N)), NumBits(N) {}
+  BitsInit(RecordKeeper &RK, ArrayRef<const Init *> Bits);
 
 public:
   BitsInit(const BitsInit &) = delete;
@@ -757,15 +757,15 @@ class StringInit final : public TypedInit {
 ///
 class ListInit final : public TypedInit,
                        public FoldingSetNode,
-                       public TrailingObjects<ListInit, const Init *> {
+                       private TrailingObjects<ListInit, const Init *> {
+  friend TrailingObjects;
   unsigned NumValues;
 
 public:
   using const_iterator = const Init *const *;
 
 private:
-  explicit ListInit(unsigned N, const RecTy *EltTy)
-      : TypedInit(IK_ListInit, ListRecTy::get(EltTy)), NumValues(N) {}
+  explicit ListInit(ArrayRef<const Init *> Elements, const RecTy *EltTy);
 
 public:
   ListInit(const ListInit &) = delete;
@@ -1019,12 +1019,13 @@ class TernOpInit final : public OpInit, public FoldingSetNode {
 /// Otherwise reports an error.
 class CondOpInit final : public TypedInit,
                          public FoldingSetNode,
-                         public TrailingObjects<CondOpInit, const Init *> {
+                         private TrailingObjects<CondOpInit, const Init *> {
+  friend TrailingObjects;
   unsigned NumConds;
   const RecTy *ValType;
 
-  CondOpInit(unsigned NC, const RecTy *Type)
-      : TypedInit(IK_CondOpInit, Type), NumConds(NC), ValType(Type) {}
+  CondOpInit(ArrayRef<const Init *> C, ArrayRef<const Init *> V,
+             const RecTy *Type);
 
   size_t numTrailingObjects(OverloadToken<Init *>) const {
     return 2*NumConds;
@@ -1038,8 +1039,9 @@ class CondOpInit final : public TypedInit,
     return I->getKind() == IK_CondOpInit;
   }
 
-  static const CondOpInit *get(ArrayRef<const Init *> C,
-                               ArrayRef<const Init *> V, const RecTy *Type);
+  static const CondOpInit *get(ArrayRef<const Init *> Conds,
+                               ArrayRef<const Init *> Values,
+                               const RecTy *Type);
 
   void Profile(FoldingSetNodeID &ID) const;
 
@@ -1047,15 +1049,9 @@ class CondOpInit final : public TypedInit,
 
   unsigned getNumConds() const { return NumConds; }
 
-  const Init *getCond(unsigned Num) const {
-    assert(Num < NumConds && "Condition number out of range!");
-    return getTrailingObjects<const Init *>()[Num];
-  }
+  const Init *getCond(unsigned Num) const { return getConds()[Num]; }
 
-  const Init *getVal(unsigned Num) const {
-    assert(Num < NumConds && "Val number out of range!");
-    return getTrailingObjects<const Init *>()[Num + NumConds];
-  }
+  const Init *getVal(unsigned Num) const { return getVals()[Num]; }
 
   ArrayRef<const Init *> getConds() const {
     return ArrayRef(getTrailingObjects<const Init *>(), NumConds);
@@ -1337,13 +1333,15 @@ class DefInit final : public TypedInit {
 class VarDefInit final
     : public TypedInit,
       public FoldingSetNode,
-      public TrailingObjects<VarDefInit, const ArgumentInit *> {
+      private TrailingObjects<VarDefInit, const ArgumentInit *> {
+  friend TrailingObjects;
   SMLoc Loc;
   const Record *Class;
   const DefInit *Def = nullptr; // after instantiation
   unsigned NumArgs;
 
-  explicit VarDefInit(SMLoc Loc, const Record *Class, unsigned N);
+  explicit VarDefInit(SMLoc Loc, const Record *Class,
+                      ArrayRef<const ArgumentInit *> Args);
 
   const DefInit *instantiate();
 
@@ -1367,23 +1365,18 @@ class VarDefInit final
 
   std::string getAsString() const override;
 
-  const ArgumentInit *getArg(unsigned i) const {
-    assert(i < NumArgs && "Argument index out of range!");
-    return getTrailingObjects<const ArgumentInit *>()[i];
-  }
+  const ArgumentInit *getArg(unsigned i) const { return args()[i]; }
 
   using const_iterator = const ArgumentInit *const *;
 
-  const_iterator args_begin() const {
-    return getTrailingObjects<const ArgumentInit *>();
-  }
-  const_iterator args_end  () const { return args_begin() + NumArgs; }
+  const_iterator args_begin() const { return args().begin(); }
+  const_iterator args_end() const { return args().end(); }
 
   size_t         args_size () const { return NumArgs; }
   bool           args_empty() const { return NumArgs == 0; }
 
   ArrayRef<const ArgumentInit *> args() const {
-    return ArrayRef(args_begin(), NumArgs);
+    return ArrayRef(getTrailingObjects<const ArgumentInit *>(), NumArgs);
   }
 
   const Init *getBit(unsigned Bit) const override {
@@ -1438,18 +1431,15 @@ class FieldInit final : public TypedInit {
 class DagInit final
     : public TypedInit,
       public FoldingSetNode,
-      public TrailingObjects<DagInit, const Init *, const StringInit *> {
+      private TrailingObjects<DagInit, const Init *, const StringInit *> {
   friend TrailingObjects;
 
   const Init *Val;
   const StringInit *ValName;
   unsigned NumArgs;
-  unsigned NumArgNames;
 
-  DagInit(const Init *V, const StringInit *VN, unsigned NumArgs,
-          unsigned NumArgNames)
-      : TypedInit(IK_DagInit, DagRecTy::get(V->getRecordKeeper())), Val(V),
-        ValName(VN), NumArgs(NumArgs), NumArgNames(NumArgNames) {}
+  DagInit(const Init *V, const StringInit *VN, ArrayRef<const Init *> Args,
+          ArrayRef<const StringInit *> ArgNames);
 
   size_t numTrailingObjects(OverloadToken<const Init *>) const {
     return NumArgs;
@@ -1483,18 +1473,14 @@ class DagInit final
 
   unsigned getNumArgs() const { return NumArgs; }
 
-  const Init *getArg(unsigned Num) const {
-    assert(Num < NumArgs && "Arg number out of range!");
-    return getTrailingObjects<const Init *>()[Num];
-  }
+  const Init *getArg(unsigned Num) const { return getArgs()[Num]; }
 
   /// This method looks up the specified argument name and returns its argument
   /// number or std::nullopt if that argument name does not exist.
   std::optional<unsigned> getArgNo(StringRef Name) const;
 
   const StringInit *getArgName(unsigned Num) const {
-    assert(Num < NumArgNames && "Arg number out of range!");
-    return getTrailingObjects<const StringInit *>()[Num];
+    return getArgNames()[Num];
   }
 
   StringRef getArgNameStr(unsigned Num) const {
@@ -1507,7 +1493,7 @@ class DagInit final
   }
 
   ArrayRef<const StringInit *> getArgNames() const {
-    return ArrayRef(getTrailingObjects<const StringInit *>(), NumArgNames);
+    return ArrayRef(getTrailingObjects<const StringInit *>(), NumArgs);
   }
 
   const Init *resolveReferences(Resolver &R) const override;
@@ -1528,9 +1514,6 @@ class DagInit final
   inline const_name_iterator name_begin() const { return getArgNames().begin();}
   inline const_name_iterator name_end  () const { return getArgNames().end(); }
 
-  inline size_t              name_size () const { return NumArgNames; }
-  inline bool                name_empty() const { return NumArgNames == 0; }
-
   const Init *getBit(unsigned Bit) const override {
     llvm_unreachable("Illegal bit reference off dag");
   }
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index c0f2fd957a505..67f237cb7b634 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -55,7 +55,7 @@ namespace detail {
 struct RecordKeeperImpl {
   RecordKeeperImpl(RecordKeeper &RK)
       : SharedBitRecTy(RK), SharedIntRecTy(RK), SharedStringRecTy(RK),
-        SharedDagRecTy(RK), AnyRecord(RK, 0), TheUnsetInit(RK),
+        SharedDagRecTy(RK), AnyRecord(RK, {}), TheUnsetInit(RK),
         TrueBitInit(true, &SharedBitRecTy),
         FalseBitInit(false, &SharedBitRecTy), StringInitStringPool(Allocator),
         StringInitCodePool(Allocator), AnonCounter(0), LastRecordID(0) {}
@@ -238,6 +238,12 @@ static void ProfileRecordRecTy(FoldingSetNodeID &ID,
     ID.AddPointer(R);
 }
 
+RecordRecTy::RecordRecTy(RecordKeeper &RK, ArrayRef<const Record *> Classes)
+    : RecTy(RecordRecTyKind, RK), NumClasses(Classes.size()) {
+  std::uninitialized_copy(Classes.begin(), Classes.end(),
+                          getTrailingObjects<const Record *>());
+}
+
 const RecordRecTy *RecordRecTy::get(RecordKeeper &RK,
                                     ArrayRef<const Record *> UnsortedClasses) {
   detail::RecordKeeperImpl &RKImpl = RK.getImpl();
@@ -270,9 +276,7 @@ const RecordRecTy *RecordRecTy::get(RecordKeeper &RK,
 
   void *Mem = RKImpl.Allocator.Allocate(
       totalSizeToAlloc<const Record *>(Classes.size()), alignof(RecordRecTy));
-  RecordRecTy *Ty = new (Mem) RecordRecTy(RK, Classes.size());
-  std::uninitialized_copy(Classes.begin(), Classes.end(),
-                          Ty->getTrailingObjects<const Record *>());
+  RecordRecTy *Ty = new (Mem) RecordRecTy(RK, Classes);
   ThePool.InsertNode(Ty, IP);
   return Ty;
 }
@@ -467,9 +471,16 @@ static void ProfileBitsInit(FoldingSetNodeID &ID,
     ID.AddPointer(I);
 }
 
-BitsInit *BitsInit::get(RecordKeeper &RK, ArrayRef<const Init *> Range) {
+BitsInit::BitsInit(RecordKeeper &RK, ArrayRef<const Init *> Bits)
+    : TypedInit(IK_BitsInit, BitsRecTy::get(RK, Bits.size())),
+      NumBits(Bits.size()) {
+  std::uninitialized_copy(Bits.begin(), Bits.end(),
+                          getTrailingObjects<const Init *>());
+}
+
+BitsInit *BitsInit::get(RecordKeeper &RK, ArrayRef<const Init *> Bits) {
   FoldingSetNodeID ID;
-  ProfileBitsInit(ID, Range);
+  ProfileBitsInit(ID, Bits);
 
   detail::RecordKeeperImpl &RKImpl = RK.getImpl();
   void *IP = nullptr;
@@ -477,10 +488,8 @@ BitsInit *BitsInit::get(RecordKeeper &RK, ArrayRef<const Init *> Range) {
     return I;
 
   void *Mem = RKImpl.Allocator.Allocate(
-      totalSizeToAlloc<const Init *>(Range.size()), alignof(BitsInit));
-  BitsInit *I = new (Mem) BitsInit(RK, Range.size());
-  std::uninitialized_copy(Range.begin(), Range.end(),
-                          I->getTrailingObjects<const Init *>());
+      totalSizeToAlloc<const Init *>(Bits.size()), alignof(BitsInit));
+  BitsInit *I = new (Mem) BitsInit(RK, Bits);
   RKImpl.TheBitsInitPool.InsertNode(I, IP);
   return I;
 }
@@ -696,31 +705,35 @@ static void ProfileListInit(FoldingSetNodeID &ID, ArrayRef<const Init *> Range,
     ID.AddPointer(I);
 }
 
-const ListInit *ListInit::get(ArrayRef<const Init *> Range,
+ListInit::ListInit(ArrayRef<const Init *> Elements, const RecTy *EltTy)
+    : TypedInit(IK_ListInit, ListRecTy::get(EltTy)),
+      NumValues(Elements.size()) {
+  std::uninitialized_copy(Elements.begin(), Elements.end(),
+                          getTrailingObjects<const Init *>());
+}
+
+const ListInit *ListInit::get(ArrayRef<const Init *> Elements,
                               const RecTy *EltTy) {
   FoldingSetNodeID ID;
-  ProfileListInit(ID, Range, EltTy);
+  ProfileListInit(ID, Elements, EltTy);
 
   detail::RecordKeeperImpl &RK = EltTy->getRecordKeeper().getImpl();
   void *IP = nullptr;
   if (const ListInit *I = RK.TheListInitPool.FindNodeOrInsertPos(ID, IP))
     return I;
 
-  assert(Range.empty() || !isa<TypedInit>(Range[0]) ||
-         cast<TypedInit>(Range[0])->getType()->typeIsConvertibleTo(EltTy));
+  assert(Elements.empty() || !isa<TypedInit>(Elements[0]) ||
+         cast<TypedInit>(Elements[0])->getType()->typeIsConvertibleTo(EltTy));
 
   void *Mem = RK.Allocator.Allocate(
-      totalSizeToAlloc<const Init *>(Range.size()), alignof(ListInit));
-  ListInit *I = new (Mem) ListInit(Range.size(), EltTy);
-  std::uninitialized_copy(Range.begin(), Range.end(),
-                          I->getTrailingObjects<const Init *>());
+      totalSizeToAlloc<const Init *>(Elements.size()), alignof(ListInit));
+  ListInit *I = new (Mem) ListInit(Elements, EltTy);
   RK.TheListInitPool.InsertNode(I, IP);
   return I;
 }
 
 void ListInit::Profile(FoldingSetNodeID &ID) const {
   const RecTy *EltTy = cast<ListRecTy>(getType())->getElementType();
-
   ProfileListInit(ID, getValues(), EltTy);
 }
 
@@ -2418,9 +2431,13 @@ static void ProfileVarDefInit(FoldingSetNodeID &ID, const Record *Class,
     ID.AddPointer(I);
 }
 
-VarDefInit::VarDefInit(SMLoc Loc, const Record *Class, unsigned N)
+VarDefInit::VarDefInit(SMLoc Loc, const Record *Class,
+                       ArrayRef<const ArgumentInit *> Args)
     : TypedInit(IK_VarDefInit, RecordRecTy::get(Class)), Loc(Loc), Class(Class),
-      NumArgs(N) {}
+      NumArgs(Args.size()) {
+  std::uninitialized_copy(Args.begin(), Args.end(),
+                          getTrailingObjects<const ArgumentInit *>());
+}
 
 const VarDefInit *VarDefInit::get(SMLoc Loc, const Record *Class,
                                   ArrayRef<const ArgumentInit *> Args) {
@@ -2434,9 +2451,7 @@ const VarDefInit *VarDefInit::get(SMLoc Loc, const Record *Class,
 
   void *Mem = RK.Allocator.Allocate(
       totalSizeToAlloc<const ArgumentInit *>(Args.size()), alignof(VarDefInit));
-  VarDefInit *I = new (Mem) VarDefInit(Loc, Class, Args.size());
-  std::uninitialized_copy(Args.begin(), Args.end(),
-                          I->getTrailingObjects<const ArgumentInit *>());
+  VarDefInit *I = new (Mem) VarDefInit(Loc, Class, Args);
   RK.TheVarDefInitPool.InsertNode(I, IP);
   return I;
 }
@@ -2589,36 +2604,40 @@ bool FieldInit::isConcrete() const {
 }
 
 static void ProfileCondOpInit(FoldingSetNodeID &ID,
-                              ArrayRef<const Init *> CondRange,
-                              ArrayRef<const Init *> ValRange,
+                              ArrayRef<const Init *> Conds,
+                              ArrayRef<const Init *> Vals,
                               const RecTy *ValType) {
-  assert(CondRange.size() == ValRange.size() &&
+  assert(Conds.size() == Vals.size() &&
          "Number of conditions and values must match!");
   ID.AddPointer(ValType);
-  ArrayRef<const Init *>::iterator Case = CondRange.begin();
-  ArrayRef<const Init *>::iterator Val = ValRange.begin();
 
-  while (Case != CondRange.end()) {
-    ID.AddPointer(*Case++);
-    ID.AddPointer(*Val++);
+  for (const auto &[Cond, Val] : zip(Conds, Vals)) {
+    ID.AddPointer(Cond);
+    ID.AddPointer(Val);
   }
 }
 
+CondOpInit::CondOpInit(ArrayRef<const Init *> Conds,
+                       ArrayRef<const Init *> Values, const RecTy *Type)
+    : TypedInit(IK_CondOpInit, Type), NumConds(Conds.size()), ValType(Type) {
+  auto *TrailingObjects = getTrailingObjects<const Init *>();
+  std::uninitialized_copy(Conds.begin(), Conds.end(), TrailingObjects);
+  std::uninitialized_copy(Values.begin(), Values.end(),
+                          TrailingObjects + NumConds);
+}
+
 void CondOpInit::Profile(FoldingSetNodeID &ID) const {
-  ProfileCondOpInit(
-      ID, ArrayRef(getTrailingObjects<const Init *>(), NumConds),
-      ArrayRef(getTrailingObjects<const Init *>() + NumConds, NumConds),
-      ValType);
+  ProfileCondOpInit(ID, getConds(), getVals(), ValType);
 }
 
-const CondOpInit *CondOpInit::get(ArrayRef<const Init *> CondRange,
-                                  ArrayRef<const Init *> ValRange,
+const CondOpInit *CondOpInit::get(ArrayRef<const Init *> Conds,
+                                  ArrayRef<const Init *> Values,
                                   const RecTy *Ty) {
-  assert(CondRange.size() == ValRange.size() &&
+  assert(Conds.size() == Values.size() &&
          "Number of conditions and values must match!");
 
   FoldingSetNodeID ID;
-  ProfileCondOpInit(ID, CondRange, ValRange, Ty);
+  ProfileCondOpInit(ID, Conds, Values, Ty);
 
   detail::RecordKeeperImpl &RK = Ty->getRecordKeeper().getImpl();
   void *IP = nullptr;
@@ -2626,14 +2645,8 @@ const CondOpInit *CondOpInit::get(ArrayRef<const Init *> CondRange,
     return I;
 
   void *Mem = RK.Allocator.Allocate(
-      totalSizeToAlloc<const Init *>(2 * CondRange.size()), alignof(BitsInit));
-  CondOpInit *I = new(Mem) CondOpInit(CondRange.size(), Ty);
-
-  std::uninitialized_copy(CondRange.begin(), CondRange.end(),
-                          I->getTrailingObjects<const Init *>());
-  std::uninitialized_copy(ValRange.begin(), ValRange.end(),
-                          I->getTrailingObjects<const Init *>() +
-                              CondRange.size());
+      totalSizeToAlloc<const Init *>(2 * Conds.size()), alignof(CondOpInit));
+  CondOpInit *I = new (Mem) CondOpInit(Conds, Values, Ty);
   RK.TheCondOpInitPool.InsertNode(I, IP);
   return I;
 }
@@ -2739,12 +2752,25 @@ static void ProfileDagInit(FoldingSetNodeID &ID, const Init *V,
   assert(Name == NameRange.end() && "Arg name overflow!");
 }
 
+DagInit::DagInit(const Init *V, const StringInit *VN,
+                 ArrayRef<const Init *> Args,
+                 ArrayRef<const StringInit *> ArgNames)
+    : TypedInit(IK_DagInit, DagRecTy::get(V->getRecordKeeper())), Val(V),
+      ValName(VN), NumArgs(Args.size()) {
+  std::uninitialized_copy(Args.begin(), Args.end(),
+                          getTrailingObjects<const Init *>());
+  std::uninitialized_copy(ArgNames.begin(), ArgNames.end(),
+                          getTrailingObjects<const StringInit *>());
+}
+
 const DagInit *DagInit::get(const Init *V, const StringInit *VN,
-                            ArrayRef<const Init *> ArgRange,
-                            ArrayRef<const StringInit *> NameRange) {
-  assert(ArgRange.size() == NameRange.size());
+                            ArrayRef<const Init *> Args,
+                            ArrayRef<const StringInit *> ArgNames) {
+  assert(Args.size() == ArgNames.size() &&
+         "Number of DAG args and arg names must match!");
+
   FoldingSetNodeID ID;
-  ProfileDagInit(ID, V, VN, ArgRange, NameRange);
+  ProfileDagInit(ID, V, VN, Args, ArgNames);
 
   detail::RecordKeeperImpl &RK = V->getRecordKeeper().getImpl();
   void *IP = nullptr;
@@ -2753,13 +2779,9 @@ const DagInit *DagInit::get(const Init *V, const StringInit *VN,
 
   void *Mem =
       RK.Allocator.Allocate(totalSizeToAlloc<const Init *, const StringInit *>(
-                                ArgRange.size(), NameRange.size()),
-                            alignof(BitsInit));
-  DagInit *I = new (Mem) DagInit(V, VN, ArgRange.size(), NameRange.size());
-  std::uninitialized_copy(ArgRange.begin(), ArgRange.end(),
-                          I->getTrailingObjects<const Init *>());
-  std::uninitialized_copy(NameRange.begin(), NameRange.end(),
-                          I->getTrailingObjects<const StringInit *>());
+                                Args.size(), ArgNames.size()),
+                            alignof(DagInit));
+  DagInit *I = new (Mem) DagInit(V, VN, Args, ArgNames);
   RK.TheDagInitPool.InsertNode(I, IP);
   return I;
 }
@@ -2770,18 +2792,16 @@ DagInit::get(const Init *V, const StringInit *VN,
   SmallVector<const Init *, 8> Args;
   SmallVector<const StringInit *, 8> Names;
 
-  for (const auto &Arg : args) {
-    Args.push_back(Arg.first);
-    Names.push_back(Arg.second);
+  for (const auto &[Arg, Name] : args) {
+    Args.push_back(Arg);
+    Names.push_back(Name);
   }
 
   return DagInit::get(V, VN, Args, Names);
 }
 
 void DagInit::Profile(FoldingSetNodeID &ID) const {
-  ProfileDagInit(
-      ID, Val, ValName, ArrayRef(getTrailingObjects<const Init *>(), NumArgs),
-      ArrayRef(getTrailingObjects<c...
[truncated]

``````````

</details>


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


More information about the llvm-commits mailing list