[llvm] [LLVMABI] Implement the ABI Typesystem (PR #158329)

via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 31 08:04:57 PST 2025


https://github.com/vortex73 updated https://github.com/llvm/llvm-project/pull/158329

>From 938d388bfde0bb189ebb62e39ea324a1bf0bd551 Mon Sep 17 00:00:00 2001
From: Narayan Sreekumar <nsreekumar6 at gmail.com>
Date: Fri, 12 Sep 2025 19:25:56 +0530
Subject: [PATCH 1/4] [LLVMABI] The ABI Typesystem

---
 llvm/include/llvm/ABI/Types.h | 427 ++++++++++++++++++++++++++++++++++
 1 file changed, 427 insertions(+)
 create mode 100644 llvm/include/llvm/ABI/Types.h

diff --git a/llvm/include/llvm/ABI/Types.h b/llvm/include/llvm/ABI/Types.h
new file mode 100644
index 0000000000000..4a2dde8bf50be
--- /dev/null
+++ b/llvm/include/llvm/ABI/Types.h
@@ -0,0 +1,427 @@
+//===- ABI/Types.h ----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file defines the type system for the LLVMABI library, which mirrors
+/// ABI-relevant aspects of frontend types.
+///
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_ABI_TYPES_H
+#define LLVM_ABI_TYPES_H
+
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Alignment.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/TypeSize.h"
+
+namespace llvm {
+namespace abi {
+
+enum class TypeKind {
+  Void,
+  MemberPointer,
+  Complex,
+  Integer,
+  Float,
+  Pointer,
+  Array,
+  Vector,
+  Record,
+};
+
+/// Represents the ABI-specific view of a type in LLVM.
+///
+/// This abstracts platform and language-specific ABI details from the
+/// frontend, providing a consistent interface for the ABI Library.
+class Type {
+private:
+  TypeSize getTypeStoreSize() const {
+    TypeSize StoreSizeInBits = getTypeStoreSizeInBits();
+    return {StoreSizeInBits.getKnownMinValue() / 8,
+            StoreSizeInBits.isScalable()};
+  }
+  TypeSize getTypeStoreSizeInBits() const {
+    TypeSize BaseSize = getSizeInBits();
+    uint64_t AlignedSizeInBits =
+        alignToPowerOf2(BaseSize.getKnownMinValue(), 8);
+    return {AlignedSizeInBits, BaseSize.isScalable()};
+  }
+
+protected:
+  TypeKind Kind;
+  TypeSize SizeInBits;
+  Align ABIAlignment;
+
+  Type(TypeKind K, TypeSize SizeInBits, Align ABIAlign)
+      : Kind(K), SizeInBits(SizeInBits), ABIAlignment(ABIAlign) {}
+
+public:
+  TypeKind getKind() const { return Kind; }
+  TypeSize getSizeInBits() const { return SizeInBits; }
+  Align getAlignment() const { return ABIAlignment; }
+
+  TypeSize getTypeAllocSize() const {
+    return alignTo(getTypeStoreSize(), getAlignment().value());
+  }
+
+  bool isVoid() const { return Kind == TypeKind::Void; }
+  bool isInteger() const { return Kind == TypeKind::Integer; }
+  bool isFloat() const { return Kind == TypeKind::Float; }
+  bool isPointer() const { return Kind == TypeKind::Pointer; }
+  bool isArray() const { return Kind == TypeKind::Array; }
+  bool isVector() const { return Kind == TypeKind::Vector; }
+  bool isRecord() const { return Kind == TypeKind::Record; }
+  bool isMemberPointer() const { return Kind == TypeKind::MemberPointer; }
+  bool isComplex() const { return Kind == TypeKind::Complex; }
+};
+
+class VoidType : public Type {
+public:
+  VoidType() : Type(TypeKind::Void, TypeSize::getFixed(0), Align(1)) {}
+
+  static bool classof(const Type *T) { return T->getKind() == TypeKind::Void; }
+};
+
+class ComplexType : public Type {
+public:
+  ComplexType(const Type *ElementType, uint64_t SizeInBits, Align Alignment)
+      : Type(TypeKind::Complex, TypeSize::getFixed(SizeInBits), Alignment),
+        ElementType(ElementType) {}
+
+  const Type *getElementType() const { return ElementType; }
+
+  static bool classof(const Type *T) {
+    return T->getKind() == TypeKind::Complex;
+  }
+
+private:
+  const Type *ElementType;
+};
+
+class IntegerType : public Type {
+private:
+  bool IsSigned;
+  bool IsBitInt;
+
+public:
+  IntegerType(uint64_t BitWidth, Align ABIAlign, bool IsSigned,
+              bool IsBitInt = false)
+      : Type(TypeKind::Integer, TypeSize::getFixed(BitWidth), ABIAlign),
+        IsSigned(IsSigned), IsBitInt(IsBitInt) {}
+
+  bool isSigned() const { return IsSigned; }
+  bool isBitInt() const { return IsBitInt; }
+  bool isBool() const {
+    return getSizeInBits().getFixedValue() == 1 && !IsBitInt;
+  }
+
+  static bool classof(const Type *T) {
+    return T->getKind() == TypeKind::Integer;
+  }
+};
+
+class FloatType : public Type {
+private:
+  const fltSemantics *Semantics;
+
+public:
+  FloatType(const fltSemantics &FloatSemantics, Align ABIAlign)
+      : Type(TypeKind::Float,
+             TypeSize::getFixed(APFloat::getSizeInBits(FloatSemantics)),
+             ABIAlign),
+        Semantics(&FloatSemantics) {}
+
+  const fltSemantics *getSemantics() const { return Semantics; }
+  static bool classof(const Type *T) { return T->getKind() == TypeKind::Float; }
+};
+
+class PointerLikeType : public Type {
+protected:
+  unsigned AddrSpace;
+  PointerLikeType(TypeKind K, TypeSize SizeInBits, Align ABIAlign, unsigned AS)
+      : Type(K, SizeInBits, ABIAlign), AddrSpace(AS) {}
+
+public:
+  unsigned getAddrSpace() const { return AddrSpace; }
+  bool isMemberPointer() const { return getKind() == TypeKind::MemberPointer; }
+
+  static bool classof(const Type *T) {
+    return T->getKind() == TypeKind::Pointer ||
+           T->getKind() == TypeKind::MemberPointer;
+  }
+};
+
+class PointerType : public PointerLikeType {
+public:
+  PointerType(uint64_t Size, Align ABIAlign, unsigned AddressSpace = 0)
+      : PointerLikeType(TypeKind::Pointer, TypeSize::getFixed(Size), ABIAlign,
+                        AddressSpace) {}
+
+  static bool classof(const Type *T) {
+    return T->getKind() == TypeKind::Pointer;
+  }
+};
+
+class MemberPointerType : public PointerLikeType {
+private:
+  bool IsFunctionPointer;
+
+public:
+  MemberPointerType(bool IsFunctionPointer, uint64_t SizeInBits, Align ABIAlign,
+                    unsigned AddressSpace = 0)
+      : PointerLikeType(TypeKind::MemberPointer, TypeSize::getFixed(SizeInBits),
+                        ABIAlign, AddressSpace),
+        IsFunctionPointer(IsFunctionPointer) {}
+  bool isFunctionPointer() const { return IsFunctionPointer; }
+
+  static bool classof(const Type *T) {
+    return T->getKind() == TypeKind::MemberPointer;
+  }
+};
+
+class ArrayType : public Type {
+private:
+  const Type *ElementType;
+  uint64_t NumElements;
+  bool IsMatrix;
+
+public:
+  ArrayType(const Type *ElementType, uint64_t NumElements, uint64_t SizeInBits,
+            bool IsMatrixType = false)
+      : Type(TypeKind::Array, TypeSize::getFixed(SizeInBits),
+             ElementType->getAlignment()),
+        ElementType(ElementType), NumElements(NumElements),
+        IsMatrix(IsMatrixType) {}
+
+  const Type *getElementType() const { return ElementType; }
+  uint64_t getNumElements() const { return NumElements; }
+  bool isMatrixType() const { return IsMatrix; }
+
+  static bool classof(const Type *T) { return T->getKind() == TypeKind::Array; }
+};
+
+class VectorType : public Type {
+private:
+  const Type *ElementType;
+  ElementCount NumElements;
+
+public:
+  VectorType(const Type *ElementType, ElementCount NumElements, Align ABIAlign)
+      : Type(TypeKind::Vector,
+             TypeSize(ElementType->getSizeInBits().getFixedValue() *
+                          NumElements.getKnownMinValue(),
+                      NumElements.isScalable()),
+             ABIAlign),
+        ElementType(ElementType), NumElements(NumElements) {}
+
+  const Type *getElementType() const { return ElementType; }
+  ElementCount getNumElements() const { return NumElements; }
+
+  static bool classof(const Type *T) {
+    return T->getKind() == TypeKind::Vector;
+  }
+};
+
+struct FieldInfo {
+  const Type *FieldType;
+  uint64_t OffsetInBits;
+  uint64_t BitFieldWidth;
+  bool IsBitField;
+  bool IsUnnamedBitfield;
+
+  FieldInfo(const Type *FieldType, uint64_t OffsetInBits = 0,
+            bool IsBitField = false, uint64_t BitFieldWidth = 0,
+            bool IsUnnamedBitField = false)
+      : FieldType(FieldType), OffsetInBits(OffsetInBits),
+        BitFieldWidth(BitFieldWidth), IsBitField(IsBitField),
+        IsUnnamedBitfield(IsUnnamedBitField) {}
+};
+
+enum class StructPacking { Default, Packed, ExplicitPacking };
+
+class RecordType : public Type {
+private:
+  ArrayRef<FieldInfo> Fields;
+  ArrayRef<FieldInfo> BaseClasses;
+  ArrayRef<FieldInfo> VirtualBaseClasses;
+  StructPacking Packing;
+  struct {
+    LLVM_PREFERRED_TYPE(bool) unsigned CanPassInRegisters : 1;
+    LLVM_PREFERRED_TYPE(bool) unsigned IsUnion : 1;
+    LLVM_PREFERRED_TYPE(bool) unsigned IsTransparent : 1;
+    LLVM_PREFERRED_TYPE(bool) unsigned IsCXXRecord : 1;
+    LLVM_PREFERRED_TYPE(bool) unsigned IsPolymorphic : 1;
+    LLVM_PREFERRED_TYPE(bool) unsigned HasFlexibleArrayMember : 1;
+  } Flags = {};
+
+public:
+  RecordType(ArrayRef<FieldInfo> StructFields, ArrayRef<FieldInfo> Bases,
+             ArrayRef<FieldInfo> VBases, TypeSize Size, Align Align,
+             StructPacking Pack = StructPacking::Default, bool Union = false,
+             bool CXXRecord = false, bool Polymorphic = false,
+             bool FlexibleArray = false, bool CanPassInRegs = false,
+             bool Transparent = false)
+      : Type(TypeKind::Record, Size, Align), Fields(StructFields),
+        BaseClasses(Bases), VirtualBaseClasses(VBases), Packing(Pack) {
+
+    Flags.CanPassInRegisters = CanPassInRegs;
+    Flags.IsUnion = Union;
+    Flags.IsTransparent = Transparent;
+    Flags.IsCXXRecord = CXXRecord;
+    Flags.IsPolymorphic = Polymorphic;
+    Flags.HasFlexibleArrayMember = FlexibleArray;
+  }
+  uint32_t getNumFields() const { return Fields.size(); }
+  StructPacking getPacking() const { return Packing; }
+
+  bool isUnion() const { return Flags.IsUnion; }
+  bool isCXXRecord() const { return Flags.IsCXXRecord; }
+  bool isPolymorphic() const { return Flags.IsPolymorphic; }
+  bool canPassInRegisters() const { return Flags.CanPassInRegisters; }
+  bool hasFlexibleArrayMember() const { return Flags.HasFlexibleArrayMember; }
+
+  uint32_t getNumBaseClasses() const { return BaseClasses.size(); }
+  uint32_t getNumVirtualBaseClasses() const {
+    return VirtualBaseClasses.size();
+  }
+  bool isTransparentUnion() const { return Flags.IsTransparent; }
+  ArrayRef<FieldInfo> getFields() const { return Fields; }
+  ArrayRef<FieldInfo> getBaseClasses() const { return BaseClasses; }
+  ArrayRef<FieldInfo> getVirtualBaseClasses() const {
+    return VirtualBaseClasses;
+  }
+};
+
+/// TypeBuilder manages the lifecycle of ABI types using bump pointer
+/// allocation. Types created by a TypeBuilder are valid for the lifetime of the
+/// builder.
+///
+/// Example usage:
+/// \code
+///   BumpPtrAllocator Alloc;
+///   TypeBuilder Builder(Alloc);
+///   const auto *IntTy = Builder.getIntegerType(32, Align(4), true);
+/// \endcode
+class TypeBuilder {
+private:
+  BumpPtrAllocator &Allocator;
+
+public:
+  explicit TypeBuilder(BumpPtrAllocator &Alloc) : Allocator(Alloc) {}
+
+  const VoidType *getVoidType() {
+    return new (Allocator.Allocate<VoidType>()) VoidType();
+  }
+
+  const IntegerType *getIntegerType(uint64_t BitWidth, Align Align, bool Signed,
+                                    bool IsBitInt = false) {
+    return new (Allocator.Allocate<IntegerType>())
+        IntegerType(BitWidth, Align, Signed, IsBitInt);
+  }
+
+  const FloatType *getFloatType(const fltSemantics &Semantics, Align Align) {
+    return new (Allocator.Allocate<FloatType>()) FloatType(Semantics, Align);
+  }
+
+  const PointerType *getPointerType(uint64_t Size, Align Align,
+                                    unsigned Addrspace = 0) {
+    return new (Allocator.Allocate<PointerType>())
+        PointerType(Size, Align, Addrspace);
+  }
+
+  const ArrayType *getArrayType(const Type *ElementType, uint64_t NumElements,
+                                uint64_t SizeInBits,
+                                bool IsMatrixType = false) {
+    return new (Allocator.Allocate<ArrayType>())
+        ArrayType(ElementType, NumElements, SizeInBits, IsMatrixType);
+  }
+
+  const VectorType *getVectorType(const Type *ElementType,
+                                  ElementCount NumElements, Align Align) {
+    return new (Allocator.Allocate<VectorType>())
+        VectorType(ElementType, NumElements, Align);
+  }
+
+  const RecordType *
+  getRecordType(ArrayRef<FieldInfo> Fields, TypeSize Size, Align Align,
+                StructPacking Pack = StructPacking::Default,
+                ArrayRef<FieldInfo> BaseClasses = {},
+                ArrayRef<FieldInfo> VirtualBaseClasses = {},
+                bool CXXRecord = false, bool Polymorphic = false,
+                bool FlexibleArray = false, bool CanPassInRegister = false) {
+    FieldInfo *FieldArray = Allocator.Allocate<FieldInfo>(Fields.size());
+    std::copy(Fields.begin(), Fields.end(), FieldArray);
+
+    FieldInfo *BaseArray = nullptr;
+    if (!BaseClasses.empty()) {
+      BaseArray = Allocator.Allocate<FieldInfo>(BaseClasses.size());
+      std::copy(BaseClasses.begin(), BaseClasses.end(), BaseArray);
+    }
+
+    FieldInfo *VBaseArray = nullptr;
+    if (!VirtualBaseClasses.empty()) {
+      VBaseArray = Allocator.Allocate<FieldInfo>(VirtualBaseClasses.size());
+      std::copy(VirtualBaseClasses.begin(), VirtualBaseClasses.end(),
+                VBaseArray);
+    }
+
+    ArrayRef<FieldInfo> FieldsRef(FieldArray, Fields.size());
+    ArrayRef<FieldInfo> BasesRef(BaseArray, BaseClasses.size());
+    ArrayRef<FieldInfo> VBasesRef(VBaseArray, VirtualBaseClasses.size());
+
+    return new (Allocator.Allocate<RecordType>())
+        RecordType(FieldsRef, BasesRef, VBasesRef, Size, Align, Pack, false,
+                   CXXRecord, Polymorphic, FlexibleArray, CanPassInRegister);
+  }
+
+  const RecordType *getUnionType(ArrayRef<FieldInfo> Fields, TypeSize Size,
+                                 Align Align,
+                                 StructPacking Pack = StructPacking::Default,
+                                 bool IsTransparent = false,
+                                 bool CanPassInRegs = false,
+                                 bool CXXRecord = false) {
+    FieldInfo *FieldArray = Allocator.Allocate<FieldInfo>(Fields.size());
+
+    for (size_t I = 0, E = Fields.size(); I != E; ++I) {
+      const FieldInfo &Field = Fields[I];
+      new (&FieldArray[I])
+          FieldInfo(Field.FieldType, 0, Field.IsBitField, Field.BitFieldWidth,
+                    Field.IsUnnamedBitfield);
+    }
+
+    ArrayRef<FieldInfo> FieldsRef(FieldArray, Fields.size());
+
+    return new (Allocator.Allocate<RecordType>()) RecordType(
+        FieldsRef, ArrayRef<FieldInfo>(), ArrayRef<FieldInfo>(), Size, Align,
+        Pack, true, CXXRecord, false, false, CanPassInRegs, IsTransparent);
+  }
+
+  const ComplexType *getComplexType(const Type *ElementType, Align Align) {
+    // Complex types have two elements (real and imaginary parts)
+    uint64_t ElementSizeInBits = ElementType->getSizeInBits().getFixedValue();
+    uint64_t ComplexSizeInBits = ElementSizeInBits * 2;
+
+    return new (Allocator.Allocate<ComplexType>())
+        ComplexType(ElementType, ComplexSizeInBits, Align);
+  }
+
+  const MemberPointerType *getMemberPointerType(bool IsFunctionPointer,
+                                                uint64_t SizeInBits,
+                                                Align Align) {
+    return new (Allocator.Allocate<MemberPointerType>())
+        MemberPointerType(IsFunctionPointer, SizeInBits, Align);
+  }
+};
+
+} // namespace abi
+} // namespace llvm
+
+#endif

>From 91f268d172a61d2e6f18839108872167d84e3819 Mon Sep 17 00:00:00 2001
From: Narayan Sreekumar <nsreekumar6 at gmail.com>
Date: Fri, 5 Dec 2025 21:07:21 +0530
Subject: [PATCH 2/4] chore: added enum flags

---
 llvm/include/llvm/ABI/Types.h | 102 ++++++++++++++++++++--------------
 1 file changed, 59 insertions(+), 43 deletions(-)

diff --git a/llvm/include/llvm/ABI/Types.h b/llvm/include/llvm/ABI/Types.h
index 4a2dde8bf50be..55bc4a7bf15d3 100644
--- a/llvm/include/llvm/ABI/Types.h
+++ b/llvm/include/llvm/ABI/Types.h
@@ -247,52 +247,72 @@ struct FieldInfo {
 
 enum class StructPacking { Default, Packed, ExplicitPacking };
 
+enum RecordFlags : unsigned {
+  None = 0,
+  CanPassInRegisters = 1 << 0,
+  IsUnion = 1 << 1,
+  IsTransparent = 1 << 2,
+  IsCXXRecord = 1 << 3,
+  IsPolymorphic = 1 << 4,
+  HasFlexibleArrayMember = 1 << 5,
+};
+
+inline RecordFlags operator|(RecordFlags LHS, RecordFlags RHS) {
+  return static_cast<RecordFlags>(static_cast<unsigned>(LHS) |
+                                  static_cast<unsigned>(RHS));
+}
+
+inline RecordFlags operator&(RecordFlags LHS, RecordFlags RHS) {
+  return static_cast<RecordFlags>(static_cast<unsigned>(LHS) &
+                                  static_cast<unsigned>(RHS));
+}
+
+inline RecordFlags &operator|=(RecordFlags &LHS, RecordFlags RHS) {
+  LHS = LHS | RHS;
+  return LHS;
+}
 class RecordType : public Type {
 private:
   ArrayRef<FieldInfo> Fields;
   ArrayRef<FieldInfo> BaseClasses;
   ArrayRef<FieldInfo> VirtualBaseClasses;
   StructPacking Packing;
-  struct {
-    LLVM_PREFERRED_TYPE(bool) unsigned CanPassInRegisters : 1;
-    LLVM_PREFERRED_TYPE(bool) unsigned IsUnion : 1;
-    LLVM_PREFERRED_TYPE(bool) unsigned IsTransparent : 1;
-    LLVM_PREFERRED_TYPE(bool) unsigned IsCXXRecord : 1;
-    LLVM_PREFERRED_TYPE(bool) unsigned IsPolymorphic : 1;
-    LLVM_PREFERRED_TYPE(bool) unsigned HasFlexibleArrayMember : 1;
-  } Flags = {};
+  RecordFlags Flags;
 
 public:
   RecordType(ArrayRef<FieldInfo> StructFields, ArrayRef<FieldInfo> Bases,
              ArrayRef<FieldInfo> VBases, TypeSize Size, Align Align,
-             StructPacking Pack = StructPacking::Default, bool Union = false,
-             bool CXXRecord = false, bool Polymorphic = false,
-             bool FlexibleArray = false, bool CanPassInRegs = false,
-             bool Transparent = false)
+             StructPacking Pack = StructPacking::Default,
+             RecordFlags RecFlags = RecordFlags::None)
       : Type(TypeKind::Record, Size, Align), Fields(StructFields),
-        BaseClasses(Bases), VirtualBaseClasses(VBases), Packing(Pack) {
-
-    Flags.CanPassInRegisters = CanPassInRegs;
-    Flags.IsUnion = Union;
-    Flags.IsTransparent = Transparent;
-    Flags.IsCXXRecord = CXXRecord;
-    Flags.IsPolymorphic = Polymorphic;
-    Flags.HasFlexibleArrayMember = FlexibleArray;
-  }
+        BaseClasses(Bases), VirtualBaseClasses(VBases), Packing(Pack),
+        Flags(RecFlags) {}
   uint32_t getNumFields() const { return Fields.size(); }
   StructPacking getPacking() const { return Packing; }
 
-  bool isUnion() const { return Flags.IsUnion; }
-  bool isCXXRecord() const { return Flags.IsCXXRecord; }
-  bool isPolymorphic() const { return Flags.IsPolymorphic; }
-  bool canPassInRegisters() const { return Flags.CanPassInRegisters; }
-  bool hasFlexibleArrayMember() const { return Flags.HasFlexibleArrayMember; }
-
+  bool isUnion() const {
+    return static_cast<unsigned>(Flags & RecordFlags::IsUnion) != 0;
+  }
+  bool isCXXRecord() const {
+    return static_cast<unsigned>(Flags & RecordFlags::IsCXXRecord) != 0;
+  }
+  bool isPolymorphic() const {
+    return static_cast<unsigned>(Flags & RecordFlags::IsPolymorphic) != 0;
+  }
+  bool canPassInRegisters() const {
+    return static_cast<unsigned>(Flags & RecordFlags::CanPassInRegisters) != 0;
+  }
+  bool hasFlexibleArrayMember() const {
+    return static_cast<unsigned>(Flags & RecordFlags::HasFlexibleArrayMember) !=
+           0;
+  }
   uint32_t getNumBaseClasses() const { return BaseClasses.size(); }
   uint32_t getNumVirtualBaseClasses() const {
     return VirtualBaseClasses.size();
   }
-  bool isTransparentUnion() const { return Flags.IsTransparent; }
+  bool isTransparentUnion() const {
+    return static_cast<unsigned>(Flags & RecordFlags::IsTransparent) != 0;
+  }
   ArrayRef<FieldInfo> getFields() const { return Fields; }
   ArrayRef<FieldInfo> getBaseClasses() const { return BaseClasses; }
   ArrayRef<FieldInfo> getVirtualBaseClasses() const {
@@ -350,13 +370,12 @@ class TypeBuilder {
         VectorType(ElementType, NumElements, Align);
   }
 
-  const RecordType *
-  getRecordType(ArrayRef<FieldInfo> Fields, TypeSize Size, Align Align,
-                StructPacking Pack = StructPacking::Default,
-                ArrayRef<FieldInfo> BaseClasses = {},
-                ArrayRef<FieldInfo> VirtualBaseClasses = {},
-                bool CXXRecord = false, bool Polymorphic = false,
-                bool FlexibleArray = false, bool CanPassInRegister = false) {
+  const RecordType *getRecordType(ArrayRef<FieldInfo> Fields, TypeSize Size,
+                                  Align Align,
+                                  StructPacking Pack = StructPacking::Default,
+                                  ArrayRef<FieldInfo> BaseClasses = {},
+                                  ArrayRef<FieldInfo> VirtualBaseClasses = {},
+                                  RecordFlags RecFlags = RecordFlags::None) {
     FieldInfo *FieldArray = Allocator.Allocate<FieldInfo>(Fields.size());
     std::copy(Fields.begin(), Fields.end(), FieldArray);
 
@@ -378,16 +397,13 @@ class TypeBuilder {
     ArrayRef<FieldInfo> VBasesRef(VBaseArray, VirtualBaseClasses.size());
 
     return new (Allocator.Allocate<RecordType>())
-        RecordType(FieldsRef, BasesRef, VBasesRef, Size, Align, Pack, false,
-                   CXXRecord, Polymorphic, FlexibleArray, CanPassInRegister);
+        RecordType(FieldsRef, BasesRef, VBasesRef, Size, Align, Pack, RecFlags);
   }
 
   const RecordType *getUnionType(ArrayRef<FieldInfo> Fields, TypeSize Size,
                                  Align Align,
                                  StructPacking Pack = StructPacking::Default,
-                                 bool IsTransparent = false,
-                                 bool CanPassInRegs = false,
-                                 bool CXXRecord = false) {
+                                 RecordFlags RecFlags = RecordFlags::None) {
     FieldInfo *FieldArray = Allocator.Allocate<FieldInfo>(Fields.size());
 
     for (size_t I = 0, E = Fields.size(); I != E; ++I) {
@@ -399,9 +415,9 @@ class TypeBuilder {
 
     ArrayRef<FieldInfo> FieldsRef(FieldArray, Fields.size());
 
-    return new (Allocator.Allocate<RecordType>()) RecordType(
-        FieldsRef, ArrayRef<FieldInfo>(), ArrayRef<FieldInfo>(), Size, Align,
-        Pack, true, CXXRecord, false, false, CanPassInRegs, IsTransparent);
+    return new (Allocator.Allocate<RecordType>())
+        RecordType(FieldsRef, ArrayRef<FieldInfo>(), ArrayRef<FieldInfo>(),
+                   Size, Align, Pack, RecFlags | RecordFlags::IsUnion);
   }
 
   const ComplexType *getComplexType(const Type *ElementType, Align Align) {

>From 4ec629f50e8e89b6cf1e0924fd77e5a6cce6dea5 Mon Sep 17 00:00:00 2001
From: Narayan Sreekumar <nsreekumar6 at gmail.com>
Date: Wed, 31 Dec 2025 18:43:00 +0530
Subject: [PATCH 3/4] fixed nits

---
 llvm/include/llvm/ABI/Types.h | 18 +++---------------
 1 file changed, 3 insertions(+), 15 deletions(-)

diff --git a/llvm/include/llvm/ABI/Types.h b/llvm/include/llvm/ABI/Types.h
index 55bc4a7bf15d3..7365a5218f230 100644
--- a/llvm/include/llvm/ABI/Types.h
+++ b/llvm/include/llvm/ABI/Types.h
@@ -16,6 +16,7 @@
 
 #include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitmaskEnum.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Alignment.h"
 #include "llvm/Support/Allocator.h"
@@ -255,22 +256,9 @@ enum RecordFlags : unsigned {
   IsCXXRecord = 1 << 3,
   IsPolymorphic = 1 << 4,
   HasFlexibleArrayMember = 1 << 5,
+  LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ HasFlexibleArrayMember),
 };
 
-inline RecordFlags operator|(RecordFlags LHS, RecordFlags RHS) {
-  return static_cast<RecordFlags>(static_cast<unsigned>(LHS) |
-                                  static_cast<unsigned>(RHS));
-}
-
-inline RecordFlags operator&(RecordFlags LHS, RecordFlags RHS) {
-  return static_cast<RecordFlags>(static_cast<unsigned>(LHS) &
-                                  static_cast<unsigned>(RHS));
-}
-
-inline RecordFlags &operator|=(RecordFlags &LHS, RecordFlags RHS) {
-  LHS = LHS | RHS;
-  return LHS;
-}
 class RecordType : public Type {
 private:
   ArrayRef<FieldInfo> Fields;
@@ -322,7 +310,7 @@ class RecordType : public Type {
 
 /// TypeBuilder manages the lifecycle of ABI types using bump pointer
 /// allocation. Types created by a TypeBuilder are valid for the lifetime of the
-/// builder.
+/// builder->allocator.
 ///
 /// Example usage:
 /// \code

>From 8def0f955ddd454c6c88f8ef15e3daedef6c51db Mon Sep 17 00:00:00 2001
From: Narayan Sreekumar <nsreekumar6 at gmail.com>
Date: Wed, 31 Dec 2025 21:34:35 +0530
Subject: [PATCH 4/4] add CMakeLists.txt

---
 llvm/lib/ABI/CMakeLists.txt | 14 ++++++++++++++
 llvm/lib/ABI/Types.cpp      |  1 +
 llvm/lib/CMakeLists.txt     |  1 +
 3 files changed, 16 insertions(+)
 create mode 100644 llvm/lib/ABI/CMakeLists.txt
 create mode 100644 llvm/lib/ABI/Types.cpp

diff --git a/llvm/lib/ABI/CMakeLists.txt b/llvm/lib/ABI/CMakeLists.txt
new file mode 100644
index 0000000000000..bace28e0aa2b3
--- /dev/null
+++ b/llvm/lib/ABI/CMakeLists.txt
@@ -0,0 +1,14 @@
+add_llvm_component_library(LLVMABI
+	Types.cpp
+
+  ADDITIONAL_HEADER_DIRS
+  ${LLVM_MAIN_INCLUDE_DIR}/llvm/ABI
+
+  DEPENDS
+  intrinsics_gen
+
+  LINK_COMPONENTS
+  Core
+  Support
+)
+
diff --git a/llvm/lib/ABI/Types.cpp b/llvm/lib/ABI/Types.cpp
new file mode 100644
index 0000000000000..b3e7e681b9204
--- /dev/null
+++ b/llvm/lib/ABI/Types.cpp
@@ -0,0 +1 @@
+#include "llvm/ABI/Types.h"
diff --git a/llvm/lib/CMakeLists.txt b/llvm/lib/CMakeLists.txt
index a9432977718c6..c2ce8fd6eb686 100644
--- a/llvm/lib/CMakeLists.txt
+++ b/llvm/lib/CMakeLists.txt
@@ -3,6 +3,7 @@ include(LLVM-Build)
 # `Demangle', `Support' and `TableGen' libraries are added on the top-level
 # CMakeLists.txt
 
+add_subdirectory(ABI)
 add_subdirectory(IR)
 add_subdirectory(FuzzMutate)
 add_subdirectory(FileCheck)



More information about the llvm-commits mailing list