[clang] [llvm] [WIP] ABI Lowering Library (PR #140112)

via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 21 06:38:12 PDT 2025


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

>From 322c1cfb925f3073f3d3b30abe1b2e35ae7745f3 Mon Sep 17 00:00:00 2001
From: Narayan Sreekumar <nsreekumar6 at gmail.com>
Date: Thu, 15 May 2025 23:13:50 +0530
Subject: [PATCH 01/12] [LLVM ABI] The Typesystem

---
 llvm/include/llvm/ABI/Types.h | 121 ++++++++++++++++++++++++++++++++++
 1 file changed, 121 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..443a6c1eab4e7
--- /dev/null
+++ b/llvm/include/llvm/ABI/Types.h
@@ -0,0 +1,121 @@
+#ifndef LLVM_ABI_TYPES_H
+#define LLVM_ABI_TYPES_H
+
+#include <cstdint>
+#include <memory>
+#include <string>
+
+namespace llvm {
+namespace abi {
+
+enum class TypeKind {
+  Void,
+  Integer,
+  Float,
+  Pointer,
+  Array,
+  Vector,
+  Struct,
+  Union,
+  Function
+};
+class Type {
+protected:
+  TypeKind Kind;
+  uint64_t SizeInBits;
+  uint64_t AlignInBits;
+  bool IsExplicitlyAligned;
+
+  Type(TypeKind K, uint64_t Size, uint64_t Align, bool ExplicitAlign = false)
+      : Kind(K), SizeInBits(Size), AlignInBits(Align),
+        IsExplicitlyAligned(ExplicitAlign) {}
+
+public:
+  virtual ~Type() = default;
+
+  TypeKind getKind() const { return Kind; }
+  uint64_t getSizeInBits() const { return SizeInBits; }
+  uint64_t getAlignInBits() const { return AlignInBits; }
+  bool hasExplicitAlignment() const { return IsExplicitlyAligned; }
+
+  void setExplicitAlignment(uint64_t Align) {
+    AlignInBits = Align;
+    IsExplicitlyAligned = true;
+  }
+
+  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 isStruct() const { return Kind == TypeKind::Struct; }
+  bool isUnion() const { return Kind == TypeKind::Union; }
+  bool isFunction() const { return Kind == TypeKind::Function; }
+
+  static bool classof(const Type *) { return true; }
+};
+class VoidType : public Type {
+public:
+  VoidType() : Type(TypeKind::Void, 0, 0) {}
+
+  static bool classof(const Type *T) { return T->getKind() == TypeKind::Void; }
+};
+
+class IntegerType : public Type {
+private:
+  bool IsSigned;
+  bool IsAltRepresentation;
+  std::string TypeName;
+
+public:
+  IntegerType(uint64_t BitWidth, uint64_t Align, bool Signed,
+              bool AltRep = false, const std::string &Name = "")
+      : Type(TypeKind::Integer, BitWidth, Align), IsSigned(Signed),
+        IsAltRepresentation(AltRep), TypeName(Name) {}
+
+  bool isSigned() const { return IsSigned; }
+  bool isAltRepresentation() const { return IsAltRepresentation; }
+  const std::string &getTypeName() const { return TypeName; }
+
+  static bool classof(const Type *T) {
+    return T->getKind() == TypeKind::Integer;
+  }
+};
+class FloatType : public Type {
+private:
+  std::string TypeName;
+
+public:
+  FloatType(uint64_t BitWidth, uint64_t Align, const std::string &Name)
+      : Type(TypeKind::Float, BitWidth, Align), TypeName(Name) {}
+
+  const std::string &getTypeName() const { return TypeName; }
+
+  static bool classof(const Type *T) { return T->getKind() == TypeKind::Float; }
+};
+class PointerType : public Type {
+private:
+  std::unique_ptr<Type> PointeeType;
+  bool IsConst;
+  bool IsVolatile;
+
+public:
+  PointerType(std::unique_ptr<Type> Pointee, uint64_t Size, uint64_t Align,
+              bool Const = false, bool Volatile = false)
+      : Type(TypeKind::Pointer, Size, Align), PointeeType(std::move(Pointee)),
+        IsConst(Const), IsVolatile(Volatile) {}
+
+  const Type *getPointeeType() const { return PointeeType.get(); }
+  bool isConst() const { return IsConst; }
+  bool isVolatile() const { return IsVolatile; }
+
+  static bool classof(const Type *T) {
+    return T->getKind() == TypeKind::Pointer;
+  }
+};
+
+} // namespace abi
+} // namespace llvm
+
+#endif

>From 0858b1f327c7a49c2e2825124a8d5cabbd8654fd Mon Sep 17 00:00:00 2001
From: Narayan Sreekumar <nsreekumar6 at gmail.com>
Date: Fri, 23 May 2025 17:53:53 +0530
Subject: [PATCH 02/12] [LLVMABI] API for Creating types

---
 llvm/include/llvm/ABI/Types.h | 244 +++++++++++++++++++++++++++++-----
 1 file changed, 213 insertions(+), 31 deletions(-)

diff --git a/llvm/include/llvm/ABI/Types.h b/llvm/include/llvm/ABI/Types.h
index 443a6c1eab4e7..84cb586832dbd 100644
--- a/llvm/include/llvm/ABI/Types.h
+++ b/llvm/include/llvm/ABI/Types.h
@@ -1,9 +1,9 @@
 #ifndef LLVM_ABI_TYPES_H
 #define LLVM_ABI_TYPES_H
 
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Allocator.h"
 #include <cstdint>
-#include <memory>
-#include <string>
 
 namespace llvm {
 namespace abi {
@@ -19,6 +19,7 @@ enum class TypeKind {
   Union,
   Function
 };
+
 class Type {
 protected:
   TypeKind Kind;
@@ -31,8 +32,6 @@ class Type {
         IsExplicitlyAligned(ExplicitAlign) {}
 
 public:
-  virtual ~Type() = default;
-
   TypeKind getKind() const { return Kind; }
   uint64_t getSizeInBits() const { return SizeInBits; }
   uint64_t getAlignInBits() const { return AlignInBits; }
@@ -52,9 +51,8 @@ class Type {
   bool isStruct() const { return Kind == TypeKind::Struct; }
   bool isUnion() const { return Kind == TypeKind::Union; }
   bool isFunction() const { return Kind == TypeKind::Function; }
-
-  static bool classof(const Type *) { return true; }
 };
+
 class VoidType : public Type {
 public:
   VoidType() : Type(TypeKind::Void, 0, 0) {}
@@ -65,53 +63,237 @@ class VoidType : public Type {
 class IntegerType : public Type {
 private:
   bool IsSigned;
-  bool IsAltRepresentation;
-  std::string TypeName;
 
 public:
-  IntegerType(uint64_t BitWidth, uint64_t Align, bool Signed,
-              bool AltRep = false, const std::string &Name = "")
-      : Type(TypeKind::Integer, BitWidth, Align), IsSigned(Signed),
-        IsAltRepresentation(AltRep), TypeName(Name) {}
+  IntegerType(uint64_t BitWidth, uint64_t Align, bool Signed)
+      : Type(TypeKind::Integer, BitWidth, Align), IsSigned(Signed) {}
 
   bool isSigned() const { return IsSigned; }
-  bool isAltRepresentation() const { return IsAltRepresentation; }
-  const std::string &getTypeName() const { return TypeName; }
 
   static bool classof(const Type *T) {
     return T->getKind() == TypeKind::Integer;
   }
 };
+
 class FloatType : public Type {
+public:
+  FloatType(uint64_t BitWidth, uint64_t Align)
+      : Type(TypeKind::Float, BitWidth, Align) {}
+
+  static bool classof(const Type *T) { return T->getKind() == TypeKind::Float; }
+};
+
+class PointerType : public Type {
+public:
+  PointerType(uint64_t Size, uint64_t Align)
+      : Type(TypeKind::Pointer, Size, Align) {}
+
+  static bool classof(const Type *T) {
+    return T->getKind() == TypeKind::Pointer;
+  }
+};
+
+class ArrayType : public Type {
 private:
-  std::string TypeName;
+  const Type *ElementType;
+  uint64_t NumElements;
 
 public:
-  FloatType(uint64_t BitWidth, uint64_t Align, const std::string &Name)
-      : Type(TypeKind::Float, BitWidth, Align), TypeName(Name) {}
+  ArrayType(const Type *ElemType, uint64_t NumElems)
+      : Type(TypeKind::Array, ElemType->getSizeInBits() * NumElems,
+             ElemType->getAlignInBits()),
+        ElementType(ElemType), NumElements(NumElems) {}
 
-  const std::string &getTypeName() const { return TypeName; }
+  const Type *getElementType() const { return ElementType; }
+  uint64_t getNumElements() const { return NumElements; }
 
-  static bool classof(const Type *T) { return T->getKind() == TypeKind::Float; }
+  static bool classof(const Type *T) { return T->getKind() == TypeKind::Array; }
 };
-class PointerType : public Type {
+
+class VectorType : public Type {
 private:
-  std::unique_ptr<Type> PointeeType;
-  bool IsConst;
-  bool IsVolatile;
+  const Type *ElementType;
+  uint64_t NumElements;
 
 public:
-  PointerType(std::unique_ptr<Type> Pointee, uint64_t Size, uint64_t Align,
-              bool Const = false, bool Volatile = false)
-      : Type(TypeKind::Pointer, Size, Align), PointeeType(std::move(Pointee)),
-        IsConst(Const), IsVolatile(Volatile) {}
+  VectorType(const Type *ElemType, uint64_t NumElems, uint64_t Align)
+      : Type(TypeKind::Vector, ElemType->getSizeInBits() * NumElems, Align),
+        ElementType(ElemType), NumElements(NumElems) {}
 
-  const Type *getPointeeType() const { return PointeeType.get(); }
-  bool isConst() const { return IsConst; }
-  bool isVolatile() const { return IsVolatile; }
+  const Type *getElementType() const { return ElementType; }
+  uint64_t getNumElements() const { return NumElements; }
 
   static bool classof(const Type *T) {
-    return T->getKind() == TypeKind::Pointer;
+    return T->getKind() == TypeKind::Vector;
+  }
+};
+
+struct FieldInfo {
+  const Type *FieldType;
+  uint64_t OffsetInBits;
+  bool IsBitField;
+  uint64_t BitFieldWidth;
+
+  FieldInfo(const Type *Type, uint64_t Offset = 0, bool BitField = false,
+            uint64_t BFWidth = 0)
+      : FieldType(Type), OffsetInBits(Offset), IsBitField(BitField),
+        BitFieldWidth(BFWidth) {}
+};
+
+enum class StructPacking { Default, Packed, ExplicitPacking };
+
+class StructType : public Type {
+private:
+  const FieldInfo *Fields;
+  uint32_t NumFields;
+  StructPacking Packing;
+
+public:
+  StructType(const FieldInfo *StructFields, uint32_t FieldCount, uint64_t Size,
+             uint64_t Align, StructPacking Pack = StructPacking::Default)
+      : Type(TypeKind::Struct, Size, Align), Fields(StructFields),
+        NumFields(FieldCount), Packing(Pack) {}
+
+  const FieldInfo *getFields() const { return Fields; }
+  uint32_t getNumFields() const { return NumFields; }
+  StructPacking getPacking() const { return Packing; }
+
+  static bool classof(const Type *T) {
+    return T->getKind() == TypeKind::Struct;
+  }
+};
+
+class UnionType : public Type {
+private:
+  const FieldInfo *Fields;
+  uint32_t NumFields;
+  StructPacking Packing;
+
+public:
+  UnionType(const FieldInfo *UnionFields, uint32_t FieldCount, uint64_t Size,
+            uint64_t Align, StructPacking Pack = StructPacking::Default)
+      : Type(TypeKind::Union, Size, Align), Fields(UnionFields),
+        NumFields(FieldCount), Packing(Pack) {}
+
+  const FieldInfo *getFields() const { return Fields; }
+  uint32_t getNumFields() const { return NumFields; }
+  StructPacking getPacking() const { return Packing; }
+
+  static bool classof(const Type *T) { return T->getKind() == TypeKind::Union; }
+};
+
+enum class CallConv {
+  C,
+  // TODO: extend for more CallConvs
+};
+
+class FunctionType : public Type {
+private:
+  const Type *ReturnType;
+  const Type *const *ParameterTypes;
+  uint32_t NumParams;
+  bool IsVarArg;
+  CallConv CC;
+
+public:
+  FunctionType(const Type *RetType, const Type *const *ParamTypes,
+               uint32_t ParamCount, bool VarArgs, CallConv CallConv)
+      : Type(TypeKind::Function, 0, 0), ReturnType(RetType),
+        ParameterTypes(ParamTypes), NumParams(ParamCount), IsVarArg(VarArgs),
+        CC(CallConv) {}
+
+  const Type *getReturnType() const { return ReturnType; }
+  const Type *const *getParameterTypes() const { return ParameterTypes; }
+  uint32_t getNumParameters() const { return NumParams; }
+  const Type *getParameterType(uint32_t Index) const {
+    assert(Index < NumParams && "Parameter index out of bounds");
+    return ParameterTypes[Index];
+  }
+  bool isVarArg() const { return IsVarArg; }
+  CallConv getCallingConv() const { return CC; }
+
+  static bool classof(const Type *T) {
+    return T->getKind() == TypeKind::Function;
+  }
+};
+
+// API for creating ABI Types
+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, uint64_t Align,
+                                    bool Signed) {
+    return new (Allocator.Allocate<IntegerType>())
+        IntegerType(BitWidth, Align, Signed);
+  }
+
+  const FloatType *getFloatType(uint64_t BitWidth, uint64_t Align) {
+    return new (Allocator.Allocate<FloatType>()) FloatType(BitWidth, Align);
+  }
+
+  const PointerType *getPointerType(uint64_t Size, uint64_t Align) {
+    return new (Allocator.Allocate<PointerType>()) PointerType(Size, Align);
+  }
+
+  const ArrayType *getArrayType(const Type *ElementType, uint64_t NumElements) {
+    return new (Allocator.Allocate<ArrayType>())
+        ArrayType(ElementType, NumElements);
+  }
+
+  const VectorType *getVectorType(const Type *ElementType, uint64_t NumElements,
+                                  uint64_t Align) {
+    return new (Allocator.Allocate<VectorType>())
+        VectorType(ElementType, NumElements, Align);
+  }
+
+  const StructType *getStructType(ArrayRef<FieldInfo> Fields, uint64_t Size,
+                                  uint64_t Align,
+                                  StructPacking Pack = StructPacking::Default) {
+    FieldInfo *FieldArray = Allocator.Allocate<FieldInfo>(Fields.size());
+
+    for (size_t I = 0; I < Fields.size(); ++I) {
+      new (&FieldArray[I]) FieldInfo(Fields[I]);
+    }
+
+    return new (Allocator.Allocate<StructType>()) StructType(
+        FieldArray, static_cast<uint32_t>(Fields.size()), Size, Align, Pack);
+  }
+
+  const UnionType *getUnionType(ArrayRef<FieldInfo> Fields, uint64_t Size,
+                                uint64_t Align,
+                                StructPacking Pack = StructPacking::Default) {
+    FieldInfo *FieldArray = Allocator.Allocate<FieldInfo>(Fields.size());
+
+    for (size_t I = 0; I < Fields.size(); ++I) {
+      new (&FieldArray[I]) FieldInfo(Fields[I]);
+    }
+
+    return new (Allocator.Allocate<UnionType>()) UnionType(
+        FieldArray, static_cast<uint32_t>(Fields.size()), Size, Align, Pack);
+  }
+
+  const FunctionType *getFunctionType(const Type *ReturnType,
+                                      ArrayRef<const Type *> ParamTypes,
+                                      bool IsVarArg,
+                                      CallConv CC = CallConv::C) {
+    const Type **ParamArray =
+        Allocator.Allocate<const Type *>(ParamTypes.size());
+
+    for (size_t I = 0; I < ParamTypes.size(); ++I) {
+      ParamArray[I] = ParamTypes[I];
+    }
+
+    return new (Allocator.Allocate<FunctionType>())
+        FunctionType(ReturnType, ParamArray,
+                     static_cast<uint32_t>(ParamTypes.size()), IsVarArg, CC);
   }
 };
 

>From 114cab7c06c080bf9661c31f405b39b2a8575d6d Mon Sep 17 00:00:00 2001
From: Narayan Sreekumar <nsreekumar6 at gmail.com>
Date: Tue, 27 May 2025 03:07:20 +0530
Subject: [PATCH 03/12] [LLVMABI] Mapper Interface

---
 llvm/include/llvm/ABI/QualTypeMapper.h |  52 +++++++++++
 llvm/include/llvm/ABI/Types.h          | 117 ++++++++-----------------
 llvm/lib/ABI/CMakeLists.txt            |  17 ++++
 llvm/lib/ABI/QualTypeMapper.cpp        |  16 ++++
 llvm/lib/CMakeLists.txt                |   1 +
 5 files changed, 123 insertions(+), 80 deletions(-)
 create mode 100644 llvm/include/llvm/ABI/QualTypeMapper.h
 create mode 100644 llvm/lib/ABI/CMakeLists.txt
 create mode 100644 llvm/lib/ABI/QualTypeMapper.cpp

diff --git a/llvm/include/llvm/ABI/QualTypeMapper.h b/llvm/include/llvm/ABI/QualTypeMapper.h
new file mode 100644
index 0000000000000..f408325dad007
--- /dev/null
+++ b/llvm/include/llvm/ABI/QualTypeMapper.h
@@ -0,0 +1,52 @@
+#ifndef LLVM_ABI_QUALTYPE_MAPPER_H
+#define LLVM_ABI_QUALTYPE_MAPPER_H
+
+#include "llvm/Support/Allocator.h"
+#include <clang/AST/ASTContext.h>
+#include <clang/AST/Type.h>
+#include <llvm/ABI/Types.h>
+#include <llvm/ADT/DenseMap.h>
+
+namespace llvm {
+namespace abi {
+
+class QualTypeMapper {
+private:
+  clang::ASTContext &ASTCtx;
+  TypeBuilder Builder;
+
+  // llvm::DenseMap<clang::QualType	, const Type*> TypeCache;
+
+  const Type *convertBuiltinType(const clang::BuiltinType *BT);
+  const Type *convertPointerType(const clang::PointerType *PT);
+  const Type *convertArrayType(const clang::ArrayType *AT);
+  const Type *convertVectorType(const clang::VectorType *VT);
+  const Type *convertRecordType(const clang::RecordType *RT);
+  const Type *convertFunctionType(const clang::FunctionProtoType *FT);
+  const Type *convertEnumType(const clang::EnumType *ET);
+
+  void computeRecordLayout(const clang::RecordDecl *RD,
+                           llvm::SmallVectorImpl<FieldInfo> &Fields,
+                           uint64_t &TotalSize, uint64_t &Alignment,
+                           StructPacking &Packing);
+
+  uint64_t getTypeSize(clang::QualType QT) const;
+  uint64_t getTypeAlign(clang::QualType QT) const;
+  uint64_t getPointerSize() const;
+  uint64_t getPointerAlign() const;
+
+public:
+  explicit QualTypeMapper(clang::ASTContext &Ctx, BumpPtrAllocator &Alloc)
+      : ASTCtx(Ctx), Builder(Alloc) {}
+
+  const Type *convertType(clang::QualType QT);
+
+  // void clearCache() {TypeCache.clear();}
+
+  TypeBuilder getTypeBuilder() { return Builder; }
+};
+
+} // namespace abi
+} // namespace llvm
+
+#endif // !LLVM_ABI_QUALTYPE_MAPPER_H
diff --git a/llvm/include/llvm/ABI/Types.h b/llvm/include/llvm/ABI/Types.h
index 84cb586832dbd..e99bee35acf77 100644
--- a/llvm/include/llvm/ABI/Types.h
+++ b/llvm/include/llvm/ABI/Types.h
@@ -1,9 +1,13 @@
 #ifndef LLVM_ABI_TYPES_H
 #define LLVM_ABI_TYPES_H
 
+#include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Alignment.h"
 #include "llvm/Support/Allocator.h"
+#include "llvm/Support/TypeSize.h"
 #include <cstdint>
+#include <llvm/IR/CallingConv.h>
 
 namespace llvm {
 namespace abi {
@@ -17,27 +21,26 @@ enum class TypeKind {
   Vector,
   Struct,
   Union,
-  Function
 };
 
 class Type {
 protected:
   TypeKind Kind;
-  uint64_t SizeInBits;
-  uint64_t AlignInBits;
+  TypeSize SizeInBits;
+  Align AlignInBits;
   bool IsExplicitlyAligned;
 
-  Type(TypeKind K, uint64_t Size, uint64_t Align, bool ExplicitAlign = false)
+  Type(TypeKind K, TypeSize Size, Align Align, bool ExplicitAlign = false)
       : Kind(K), SizeInBits(Size), AlignInBits(Align),
         IsExplicitlyAligned(ExplicitAlign) {}
 
 public:
   TypeKind getKind() const { return Kind; }
-  uint64_t getSizeInBits() const { return SizeInBits; }
-  uint64_t getAlignInBits() const { return AlignInBits; }
+  TypeSize getSizeInBits() const { return SizeInBits; }
+  Align getAlignInBits() const { return AlignInBits; }
   bool hasExplicitAlignment() const { return IsExplicitlyAligned; }
 
-  void setExplicitAlignment(uint64_t Align) {
+  void setExplicitAlignment(Align Align) {
     AlignInBits = Align;
     IsExplicitlyAligned = true;
   }
@@ -50,12 +53,11 @@ class Type {
   bool isVector() const { return Kind == TypeKind::Vector; }
   bool isStruct() const { return Kind == TypeKind::Struct; }
   bool isUnion() const { return Kind == TypeKind::Union; }
-  bool isFunction() const { return Kind == TypeKind::Function; }
 };
 
 class VoidType : public Type {
 public:
-  VoidType() : Type(TypeKind::Void, 0, 0) {}
+  VoidType() : Type(TypeKind::Void, TypeSize::getFixed(0), Align(1)) {}
 
   static bool classof(const Type *T) { return T->getKind() == TypeKind::Void; }
 };
@@ -65,8 +67,9 @@ class IntegerType : public Type {
   bool IsSigned;
 
 public:
-  IntegerType(uint64_t BitWidth, uint64_t Align, bool Signed)
-      : Type(TypeKind::Integer, BitWidth, Align), IsSigned(Signed) {}
+  IntegerType(uint64_t BitWidth, Align Align, bool Signed)
+      : Type(TypeKind::Integer, TypeSize::getFixed(BitWidth), Align),
+        IsSigned(Signed) {}
 
   bool isSigned() const { return IsSigned; }
 
@@ -76,17 +79,22 @@ class IntegerType : public Type {
 };
 
 class FloatType : public Type {
+private:
+  const fltSemantics *Semantics;
+
 public:
-  FloatType(uint64_t BitWidth, uint64_t Align)
-      : Type(TypeKind::Float, BitWidth, Align) {}
+  FloatType(const fltSemantics &FloatSemantics, Align Align)
+      : Type(TypeKind::Float,
+             TypeSize::getFixed(APFloat::getSizeInBits(FloatSemantics)), Align),
+        Semantics(&FloatSemantics) {}
 
   static bool classof(const Type *T) { return T->getKind() == TypeKind::Float; }
 };
 
 class PointerType : public Type {
 public:
-  PointerType(uint64_t Size, uint64_t Align)
-      : Type(TypeKind::Pointer, Size, Align) {}
+  PointerType(uint64_t Size, Align Align)
+      : Type(TypeKind::Pointer, TypeSize::getFixed(Size), Align) {}
 
   static bool classof(const Type *T) {
     return T->getKind() == TypeKind::Pointer;
@@ -116,7 +124,7 @@ class VectorType : public Type {
   uint64_t NumElements;
 
 public:
-  VectorType(const Type *ElemType, uint64_t NumElems, uint64_t Align)
+  VectorType(const Type *ElemType, uint64_t NumElems, Align Align)
       : Type(TypeKind::Vector, ElemType->getSizeInBits() * NumElems, Align),
         ElementType(ElemType), NumElements(NumElems) {}
 
@@ -149,8 +157,8 @@ class StructType : public Type {
   StructPacking Packing;
 
 public:
-  StructType(const FieldInfo *StructFields, uint32_t FieldCount, uint64_t Size,
-             uint64_t Align, StructPacking Pack = StructPacking::Default)
+  StructType(const FieldInfo *StructFields, uint32_t FieldCount, TypeSize Size,
+             Align Align, StructPacking Pack = StructPacking::Default)
       : Type(TypeKind::Struct, Size, Align), Fields(StructFields),
         NumFields(FieldCount), Packing(Pack) {}
 
@@ -170,8 +178,8 @@ class UnionType : public Type {
   StructPacking Packing;
 
 public:
-  UnionType(const FieldInfo *UnionFields, uint32_t FieldCount, uint64_t Size,
-            uint64_t Align, StructPacking Pack = StructPacking::Default)
+  UnionType(const FieldInfo *UnionFields, uint32_t FieldCount, TypeSize Size,
+            Align Align, StructPacking Pack = StructPacking::Default)
       : Type(TypeKind::Union, Size, Align), Fields(UnionFields),
         NumFields(FieldCount), Packing(Pack) {}
 
@@ -182,41 +190,6 @@ class UnionType : public Type {
   static bool classof(const Type *T) { return T->getKind() == TypeKind::Union; }
 };
 
-enum class CallConv {
-  C,
-  // TODO: extend for more CallConvs
-};
-
-class FunctionType : public Type {
-private:
-  const Type *ReturnType;
-  const Type *const *ParameterTypes;
-  uint32_t NumParams;
-  bool IsVarArg;
-  CallConv CC;
-
-public:
-  FunctionType(const Type *RetType, const Type *const *ParamTypes,
-               uint32_t ParamCount, bool VarArgs, CallConv CallConv)
-      : Type(TypeKind::Function, 0, 0), ReturnType(RetType),
-        ParameterTypes(ParamTypes), NumParams(ParamCount), IsVarArg(VarArgs),
-        CC(CallConv) {}
-
-  const Type *getReturnType() const { return ReturnType; }
-  const Type *const *getParameterTypes() const { return ParameterTypes; }
-  uint32_t getNumParameters() const { return NumParams; }
-  const Type *getParameterType(uint32_t Index) const {
-    assert(Index < NumParams && "Parameter index out of bounds");
-    return ParameterTypes[Index];
-  }
-  bool isVarArg() const { return IsVarArg; }
-  CallConv getCallingConv() const { return CC; }
-
-  static bool classof(const Type *T) {
-    return T->getKind() == TypeKind::Function;
-  }
-};
-
 // API for creating ABI Types
 class TypeBuilder {
 private:
@@ -229,17 +202,17 @@ class TypeBuilder {
     return new (Allocator.Allocate<VoidType>()) VoidType();
   }
 
-  const IntegerType *getIntegerType(uint64_t BitWidth, uint64_t Align,
+  const IntegerType *getIntegerType(uint64_t BitWidth, Align Align,
                                     bool Signed) {
     return new (Allocator.Allocate<IntegerType>())
         IntegerType(BitWidth, Align, Signed);
   }
 
-  const FloatType *getFloatType(uint64_t BitWidth, uint64_t Align) {
-    return new (Allocator.Allocate<FloatType>()) FloatType(BitWidth, Align);
+  const FloatType *getFloatType(const fltSemantics &Semantics, Align Align) {
+    return new (Allocator.Allocate<FloatType>()) FloatType(Semantics, Align);
   }
 
-  const PointerType *getPointerType(uint64_t Size, uint64_t Align) {
+  const PointerType *getPointerType(uint64_t Size, Align Align) {
     return new (Allocator.Allocate<PointerType>()) PointerType(Size, Align);
   }
 
@@ -249,13 +222,13 @@ class TypeBuilder {
   }
 
   const VectorType *getVectorType(const Type *ElementType, uint64_t NumElements,
-                                  uint64_t Align) {
+                                  Align Align) {
     return new (Allocator.Allocate<VectorType>())
         VectorType(ElementType, NumElements, Align);
   }
 
-  const StructType *getStructType(ArrayRef<FieldInfo> Fields, uint64_t Size,
-                                  uint64_t Align,
+  const StructType *getStructType(ArrayRef<FieldInfo> Fields, TypeSize Size,
+                                  Align Align,
                                   StructPacking Pack = StructPacking::Default) {
     FieldInfo *FieldArray = Allocator.Allocate<FieldInfo>(Fields.size());
 
@@ -267,8 +240,8 @@ class TypeBuilder {
         FieldArray, static_cast<uint32_t>(Fields.size()), Size, Align, Pack);
   }
 
-  const UnionType *getUnionType(ArrayRef<FieldInfo> Fields, uint64_t Size,
-                                uint64_t Align,
+  const UnionType *getUnionType(ArrayRef<FieldInfo> Fields, TypeSize Size,
+                                Align Align,
                                 StructPacking Pack = StructPacking::Default) {
     FieldInfo *FieldArray = Allocator.Allocate<FieldInfo>(Fields.size());
 
@@ -279,22 +252,6 @@ class TypeBuilder {
     return new (Allocator.Allocate<UnionType>()) UnionType(
         FieldArray, static_cast<uint32_t>(Fields.size()), Size, Align, Pack);
   }
-
-  const FunctionType *getFunctionType(const Type *ReturnType,
-                                      ArrayRef<const Type *> ParamTypes,
-                                      bool IsVarArg,
-                                      CallConv CC = CallConv::C) {
-    const Type **ParamArray =
-        Allocator.Allocate<const Type *>(ParamTypes.size());
-
-    for (size_t I = 0; I < ParamTypes.size(); ++I) {
-      ParamArray[I] = ParamTypes[I];
-    }
-
-    return new (Allocator.Allocate<FunctionType>())
-        FunctionType(ReturnType, ParamArray,
-                     static_cast<uint32_t>(ParamTypes.size()), IsVarArg, CC);
-  }
 };
 
 } // namespace abi
diff --git a/llvm/lib/ABI/CMakeLists.txt b/llvm/lib/ABI/CMakeLists.txt
new file mode 100644
index 0000000000000..d6aa9b542cc05
--- /dev/null
+++ b/llvm/lib/ABI/CMakeLists.txt
@@ -0,0 +1,17 @@
+add_llvm_component_library(LLVMABI
+  QualTypeMapper.cpp
+
+  ADDITIONAL_HEADER_DIRS
+  ${LLVM_MAIN_INCLUDE_DIR}/llvm/ABI
+
+  DEPENDS
+  intrinsics_gen
+
+  LINK_COMPONENTS
+  Core
+  Support
+)
+
+target_include_directories(LLVMABI PRIVATE
+  ${LLVM_MAIN_INCLUDE_DIR}
+)
diff --git a/llvm/lib/ABI/QualTypeMapper.cpp b/llvm/lib/ABI/QualTypeMapper.cpp
new file mode 100644
index 0000000000000..fcf3555aaf369
--- /dev/null
+++ b/llvm/lib/ABI/QualTypeMapper.cpp
@@ -0,0 +1,16 @@
+//===-- llvm/ABI/QualTypeMapper.cpp - QualType to ABI Mapping -------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This File contains the logic for converting clang::Qualtype to
+// llvm::abi::Type for ABI Lowering
+//
+//===----------------------------------------------------------------------===//
+
+#include <llvm/ABI/QualTypeMapper.h>
+
+// TODO: Implementation of Qualtype -> abi::Type Mapping
diff --git a/llvm/lib/CMakeLists.txt b/llvm/lib/CMakeLists.txt
index f6465612d30c0..b888f6637a925 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)

>From 3a5827125418875f6976b40751b7628d5faf6d4f Mon Sep 17 00:00:00 2001
From: Narayan Sreekumar <nsreekumar6 at gmail.com>
Date: Fri, 30 May 2025 03:00:01 +0530
Subject: [PATCH 04/12] [LLVMABI] QualType Mapper Implementation

---
 clang/include/clang/ABI/QualTypeMapper.h |  78 +++++++++
 clang/lib/ABI/CMakeLists.txt             |   9 +
 clang/lib/ABI/QualTypeMapper.cpp         | 209 +++++++++++++++++++++++
 clang/lib/CMakeLists.txt                 |   1 +
 llvm/include/llvm/ABI/QualTypeMapper.h   |  52 ------
 llvm/lib/ABI/CMakeLists.txt              |  17 --
 llvm/lib/ABI/QualTypeMapper.cpp          |  16 --
 llvm/lib/CMakeLists.txt                  |   2 +-
 8 files changed, 298 insertions(+), 86 deletions(-)
 create mode 100644 clang/include/clang/ABI/QualTypeMapper.h
 create mode 100644 clang/lib/ABI/CMakeLists.txt
 create mode 100644 clang/lib/ABI/QualTypeMapper.cpp
 delete mode 100644 llvm/include/llvm/ABI/QualTypeMapper.h
 delete mode 100644 llvm/lib/ABI/CMakeLists.txt
 delete mode 100644 llvm/lib/ABI/QualTypeMapper.cpp

diff --git a/clang/include/clang/ABI/QualTypeMapper.h b/clang/include/clang/ABI/QualTypeMapper.h
new file mode 100644
index 0000000000000..70ae9e0f83130
--- /dev/null
+++ b/clang/include/clang/ABI/QualTypeMapper.h
@@ -0,0 +1,78 @@
+#ifndef LLVM_ABI_QUALTYPE_MAPPER_H
+#define LLVM_ABI_QUALTYPE_MAPPER_H
+
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/Support/Allocator.h"
+#include <clang/AST/ASTContext.h>
+#include <clang/AST/Decl.h>
+#include <clang/AST/Type.h>
+#include <llvm/ABI/Types.h>
+#include <llvm/ADT/DenseMap.h>
+
+// Specialization for QualType
+template <> struct llvm::DenseMapInfo<clang::QualType> {
+  static inline clang::QualType getEmptyKey() {
+    return clang::QualType::getFromOpaquePtr(
+        reinterpret_cast<clang::Type *>(-1));
+  }
+
+  static inline clang::QualType getTombstoneKey() {
+    return clang::QualType::getFromOpaquePtr(
+        reinterpret_cast<clang::Type *>(-2));
+  }
+
+  static unsigned getHashValue(const clang::QualType &Val) {
+    return (unsigned)((uintptr_t)Val.getAsOpaquePtr()) ^
+           ((unsigned)((uintptr_t)Val.getAsOpaquePtr() >> 9));
+  }
+
+  static bool isEqual(const clang::QualType &LHS, const clang::QualType &RHS) {
+    return LHS == RHS;
+  }
+};
+
+namespace clang {
+namespace mapper {
+
+class QualTypeMapper {
+private:
+  clang::ASTContext &ASTCtx;
+  llvm::abi::TypeBuilder Builder;
+
+  llvm::DenseMap<clang::QualType, const llvm::abi::Type *> TypeCache;
+
+  const llvm::abi::Type *convertBuiltinType(const clang::BuiltinType *BT);
+  const llvm::abi::Type *convertPointerType(const clang::PointerType *PT);
+  const llvm::abi::Type *convertArrayType(const clang::ArrayType *AT);
+  const llvm::abi::Type *convertVectorType(const clang::VectorType *VT);
+  const llvm::abi::Type *convertRecordType(const clang::RecordType *RT);
+  const llvm::abi::Type *convertEnumType(const clang::EnumType *ET);
+
+  const llvm::abi::StructType *convertStructType(const clang::RecordDecl *RD);
+  const llvm::abi::UnionType *convertUnionType(const clang::RecordDecl *RD);
+  const llvm::abi::Type *createPointerTypeForPointee(QualType PointeeType);
+
+  void computeFieldInfo(const clang::RecordDecl *RD,
+                        SmallVectorImpl<llvm::abi::FieldInfo> &Fields,
+                        const clang::ASTRecordLayout &Layout);
+
+  llvm::TypeSize getTypeSize(clang::QualType QT) const;
+  llvm::Align getTypeAlign(clang::QualType QT) const;
+  uint64_t getPointerSize() const;
+  uint64_t getPointerAlign() const;
+
+public:
+  explicit QualTypeMapper(clang::ASTContext &Ctx, llvm::BumpPtrAllocator &Alloc)
+      : ASTCtx(Ctx), Builder(Alloc) {}
+
+  const llvm::abi::Type *convertType(clang::QualType QT);
+
+  void clearCache() { TypeCache.clear(); }
+
+  llvm::abi::TypeBuilder getTypeBuilder() { return Builder; }
+};
+
+} // namespace mapper
+} // namespace clang
+
+#endif // !LLVM_ABI_QUALTYPE_MAPPER_H
diff --git a/clang/lib/ABI/CMakeLists.txt b/clang/lib/ABI/CMakeLists.txt
new file mode 100644
index 0000000000000..86a8324b5716a
--- /dev/null
+++ b/clang/lib/ABI/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_clang_library(clangABI
+  QualTypeMapper.cpp
+
+  LINK_LIBS
+  clangAST
+  clangBasic
+  LLVMABI
+  LLVMSupport
+)
diff --git a/clang/lib/ABI/QualTypeMapper.cpp b/clang/lib/ABI/QualTypeMapper.cpp
new file mode 100644
index 0000000000000..22070f250026e
--- /dev/null
+++ b/clang/lib/ABI/QualTypeMapper.cpp
@@ -0,0 +1,209 @@
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/TargetInfo.h"
+#include "llvm/ABI/Types.h"
+#include "llvm/Support/Alignment.h"
+#include "llvm/Support/Casting.h"
+#include <clang/ABI/QualTypeMapper.h>
+
+namespace clang {
+namespace mapper {
+
+const llvm::abi::Type *QualTypeMapper::convertType(QualType QT) {
+  QT = QT.getCanonicalType().getUnqualifiedType();
+
+  auto It = TypeCache.find(QT);
+  if (It != TypeCache.end())
+    return It->second;
+
+  const llvm::abi::Type *Result = nullptr;
+  if (const auto *BT = dyn_cast<BuiltinType>(QT.getTypePtr())) {
+    Result = convertBuiltinType(BT);
+  } else if (const auto *PT = dyn_cast<PointerType>(QT.getTypePtr())) {
+    Result = convertPointerType(PT);
+  } else if (const auto *AT = dyn_cast<ArrayType>(QT.getTypePtr())) {
+    Result = convertArrayType(AT);
+  } else if (const auto *VT = dyn_cast<VectorType>(QT.getTypePtr())) {
+    Result = convertVectorType(VT);
+  } else if (const auto *RT = dyn_cast<RecordType>(QT.getTypePtr())) {
+    Result = convertRecordType(RT);
+  } else if (const auto *ET = dyn_cast<EnumType>(QT.getTypePtr())) {
+    Result = convertEnumType(ET);
+  } else {
+    // TODO: Write Fallback logic for unsupported types.
+  }
+  TypeCache[QT] = Result;
+  return Result;
+}
+
+const llvm::abi::Type *
+QualTypeMapper::convertBuiltinType(const BuiltinType *BT) {
+  switch (BT->getKind()) {
+  case BuiltinType::Void:
+    return Builder.getVoidType();
+
+  case BuiltinType::Bool:
+  case BuiltinType::UChar:
+  case BuiltinType::Char_U:
+  case BuiltinType::UShort:
+    return Builder.getIntegerType(ASTCtx.getTypeSize(QualType(BT, 0)),
+                                  getTypeAlign(QualType(BT, 0)), false);
+
+  case BuiltinType::Char_S:
+  case BuiltinType::SChar:
+  case BuiltinType::Short:
+    return Builder.getIntegerType(ASTCtx.getCharWidth(),
+                                  getTypeAlign(QualType(BT, 0)), true);
+
+  case BuiltinType::WChar_U:
+    return Builder.getIntegerType(ASTCtx.getCharWidth(),
+                                  getTypeAlign(QualType(BT, 0)), false);
+
+  case BuiltinType::WChar_S:
+    return Builder.getIntegerType(ASTCtx.getCharWidth(),
+                                  getTypeAlign(QualType(BT, 0)), true);
+
+  case BuiltinType::Char8:
+    return Builder.getIntegerType(8, getTypeAlign(QualType(BT, 0)), false);
+
+  case BuiltinType::Char16:
+    return Builder.getIntegerType(16, getTypeAlign(QualType(BT, 0)), false);
+
+  case BuiltinType::Char32:
+    return Builder.getIntegerType(32, getTypeAlign(QualType(BT, 0)), false);
+
+  case BuiltinType::Int:
+  case BuiltinType::UInt:
+    return Builder.getIntegerType(ASTCtx.getIntWidth(QualType(BT, 0)),
+                                  getTypeAlign(QualType(BT, 0)),
+                                  BT->getKind() == BuiltinType::Int);
+
+  case BuiltinType::Long:
+  case BuiltinType::ULong:
+    return Builder.getIntegerType(ASTCtx.getTypeSize(QualType(BT, 0)),
+                                  getTypeAlign(QualType(BT, 0)),
+                                  BT->getKind() == BuiltinType::Long);
+
+  case BuiltinType::LongLong:
+  case BuiltinType::ULongLong:
+    return Builder.getIntegerType(ASTCtx.getTypeSize(QualType(BT, 0)),
+                                  getTypeAlign(QualType(BT, 0)),
+                                  BT->getKind() == BuiltinType::LongLong);
+
+  case BuiltinType::Int128:
+  case BuiltinType::UInt128:
+    return Builder.getIntegerType(128, getTypeAlign(QualType(BT, 0)),
+                                  BT->getKind() == BuiltinType::Int128);
+
+  case BuiltinType::Half:
+  case BuiltinType::Float16:
+    return Builder.getFloatType(llvm::APFloat::IEEEhalf(),
+                                getTypeAlign(QualType(BT, 0)));
+
+  case BuiltinType::Float:
+    return Builder.getFloatType(llvm::APFloat::IEEEsingle(),
+                                getTypeAlign(QualType(BT, 0)));
+
+  case BuiltinType::Double:
+    return Builder.getFloatType(llvm::APFloat::IEEEdouble(),
+                                getTypeAlign(QualType(BT, 0)));
+
+  case BuiltinType::LongDouble:
+    return Builder.getFloatType(ASTCtx.getFloatTypeSemantics(QualType(BT, 0)),
+                                getTypeAlign(QualType(BT, 0)));
+
+  case BuiltinType::BFloat16:
+    return Builder.getFloatType(llvm::APFloat::BFloat(),
+                                getTypeAlign(QualType(BT, 0)));
+
+  case BuiltinType::Float128:
+    return Builder.getFloatType(llvm::APFloat::IEEEquad(),
+                                getTypeAlign(QualType(BT, 0)));
+
+  default:
+    return Builder.getIntegerType(ASTCtx.getTypeSize(QualType(BT, 0)),
+                                  getTypeAlign(QualType(BT, 0)), false);
+  }
+}
+
+const llvm::abi::Type *
+QualTypeMapper::convertArrayType(const clang::ArrayType *AT) {
+  const llvm::abi::Type *ElementType = convertType(AT->getElementType());
+
+  if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) {
+    auto NumElements = CAT->getZExtSize();
+    return Builder.getArrayType(ElementType, NumElements);
+  }
+  if (const auto *IAT = dyn_cast<IncompleteArrayType>(AT))
+    return Builder.getArrayType(ElementType, 0);
+  if (const auto *VAT = dyn_cast<VariableArrayType>(AT))
+    return createPointerTypeForPointee(VAT->getPointeeType());
+  // TODO: This of a better fallback.
+  return Builder.getArrayType(ElementType, 1);
+}
+
+const llvm::abi::Type *QualTypeMapper::convertVectorType(const VectorType *VT) {
+  const llvm::abi::Type *ElementType = convertType(VT->getElementType());
+  uint64_t NumElements = VT->getNumElements();
+
+  llvm::Align VectorAlign = getTypeAlign(QualType(VT, 0));
+
+  return Builder.getVectorType(ElementType, NumElements, VectorAlign);
+}
+
+const llvm::abi::Type *QualTypeMapper::convertRecordType(const RecordType *RT) {
+  const RecordDecl *RD = RT->getDecl()->getDefinition();
+  if (!RD) {
+    SmallVector<llvm::abi::FieldInfo, 0> Fields;
+    return Builder.getStructType(Fields, llvm::TypeSize::getFixed(0),
+                                 llvm::Align(1));
+  }
+
+  if (RD->isUnion())
+    return convertUnionType(RD);
+  return convertStructType(RD);
+}
+
+const llvm::abi::Type *
+QualTypeMapper::convertPointerType(const clang::PointerType *PT) {
+  return createPointerTypeForPointee(PT->getPointeeType());
+}
+
+llvm::Align QualTypeMapper::getTypeAlign(QualType QT) const {
+  return llvm::Align(ASTCtx.getTypeAlign(QT));
+}
+
+const llvm::abi::Type *
+QualTypeMapper::createPointerTypeForPointee(QualType PointeeType) {
+  auto AddrSpace = PointeeType.getAddressSpace();
+  auto PointerSize = ASTCtx.getTargetInfo().getPointerWidth(AddrSpace);
+  llvm::Align Alignment =
+      llvm::Align(ASTCtx.getTargetInfo().getPointerAlign(AddrSpace));
+  return Builder.getPointerType(PointerSize, Alignment);
+}
+
+void QualTypeMapper::computeFieldInfo(
+    const RecordDecl *RD, SmallVectorImpl<llvm::abi::FieldInfo> &Fields,
+    const ASTRecordLayout &Layout) {
+  unsigned FieldIndex = 0;
+
+  for (const auto *FD : RD->fields()) {
+    const llvm::abi::Type *FieldType = convertType(FD->getType());
+    uint64_t OffsetInBits = Layout.getFieldOffset(FieldIndex);
+
+    bool IsBitField = FD->isBitField();
+    uint64_t BitFieldWidth = 0;
+
+    if (IsBitField) {
+      BitFieldWidth = FD->getBitWidthValue();
+    }
+
+    Fields.emplace_back(FieldType, OffsetInBits, IsBitField, BitFieldWidth);
+    ++FieldIndex;
+  }
+}
+
+} // namespace mapper
+} // namespace clang
diff --git a/clang/lib/CMakeLists.txt b/clang/lib/CMakeLists.txt
index 4f2218b583e41..f034622c06c2f 100644
--- a/clang/lib/CMakeLists.txt
+++ b/clang/lib/CMakeLists.txt
@@ -1,3 +1,4 @@
+add_subdirectory(ABI)
 add_subdirectory(Headers)
 add_subdirectory(Basic)
 add_subdirectory(APINotes)
diff --git a/llvm/include/llvm/ABI/QualTypeMapper.h b/llvm/include/llvm/ABI/QualTypeMapper.h
deleted file mode 100644
index f408325dad007..0000000000000
--- a/llvm/include/llvm/ABI/QualTypeMapper.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef LLVM_ABI_QUALTYPE_MAPPER_H
-#define LLVM_ABI_QUALTYPE_MAPPER_H
-
-#include "llvm/Support/Allocator.h"
-#include <clang/AST/ASTContext.h>
-#include <clang/AST/Type.h>
-#include <llvm/ABI/Types.h>
-#include <llvm/ADT/DenseMap.h>
-
-namespace llvm {
-namespace abi {
-
-class QualTypeMapper {
-private:
-  clang::ASTContext &ASTCtx;
-  TypeBuilder Builder;
-
-  // llvm::DenseMap<clang::QualType	, const Type*> TypeCache;
-
-  const Type *convertBuiltinType(const clang::BuiltinType *BT);
-  const Type *convertPointerType(const clang::PointerType *PT);
-  const Type *convertArrayType(const clang::ArrayType *AT);
-  const Type *convertVectorType(const clang::VectorType *VT);
-  const Type *convertRecordType(const clang::RecordType *RT);
-  const Type *convertFunctionType(const clang::FunctionProtoType *FT);
-  const Type *convertEnumType(const clang::EnumType *ET);
-
-  void computeRecordLayout(const clang::RecordDecl *RD,
-                           llvm::SmallVectorImpl<FieldInfo> &Fields,
-                           uint64_t &TotalSize, uint64_t &Alignment,
-                           StructPacking &Packing);
-
-  uint64_t getTypeSize(clang::QualType QT) const;
-  uint64_t getTypeAlign(clang::QualType QT) const;
-  uint64_t getPointerSize() const;
-  uint64_t getPointerAlign() const;
-
-public:
-  explicit QualTypeMapper(clang::ASTContext &Ctx, BumpPtrAllocator &Alloc)
-      : ASTCtx(Ctx), Builder(Alloc) {}
-
-  const Type *convertType(clang::QualType QT);
-
-  // void clearCache() {TypeCache.clear();}
-
-  TypeBuilder getTypeBuilder() { return Builder; }
-};
-
-} // namespace abi
-} // namespace llvm
-
-#endif // !LLVM_ABI_QUALTYPE_MAPPER_H
diff --git a/llvm/lib/ABI/CMakeLists.txt b/llvm/lib/ABI/CMakeLists.txt
deleted file mode 100644
index d6aa9b542cc05..0000000000000
--- a/llvm/lib/ABI/CMakeLists.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-add_llvm_component_library(LLVMABI
-  QualTypeMapper.cpp
-
-  ADDITIONAL_HEADER_DIRS
-  ${LLVM_MAIN_INCLUDE_DIR}/llvm/ABI
-
-  DEPENDS
-  intrinsics_gen
-
-  LINK_COMPONENTS
-  Core
-  Support
-)
-
-target_include_directories(LLVMABI PRIVATE
-  ${LLVM_MAIN_INCLUDE_DIR}
-)
diff --git a/llvm/lib/ABI/QualTypeMapper.cpp b/llvm/lib/ABI/QualTypeMapper.cpp
deleted file mode 100644
index fcf3555aaf369..0000000000000
--- a/llvm/lib/ABI/QualTypeMapper.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-//===-- llvm/ABI/QualTypeMapper.cpp - QualType to ABI Mapping -------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-//
-// This File contains the logic for converting clang::Qualtype to
-// llvm::abi::Type for ABI Lowering
-//
-//===----------------------------------------------------------------------===//
-
-#include <llvm/ABI/QualTypeMapper.h>
-
-// TODO: Implementation of Qualtype -> abi::Type Mapping
diff --git a/llvm/lib/CMakeLists.txt b/llvm/lib/CMakeLists.txt
index b888f6637a925..c84690abda028 100644
--- a/llvm/lib/CMakeLists.txt
+++ b/llvm/lib/CMakeLists.txt
@@ -3,7 +3,7 @@ include(LLVM-Build)
 # `Demangle', `Support' and `TableGen' libraries are added on the top-level
 # CMakeLists.txt
 
-add_subdirectory(ABI)
+# add_subdirectory(ABI)
 add_subdirectory(IR)
 add_subdirectory(FuzzMutate)
 add_subdirectory(FileCheck)

>From 283264277936dfc5f8b86cc30af4fa468910c887 Mon Sep 17 00:00:00 2001
From: Narayan Sreekumar <nsreekumar6 at gmail.com>
Date: Sun, 1 Jun 2025 22:05:23 +0530
Subject: [PATCH 05/12] [LLVMABI] Added mappings for record types

---
 .../QualtypeMapper.h}                         |  58 ++++----
 clang/lib/ABI/CMakeLists.txt                  |   9 --
 clang/lib/CMakeLists.txt                      |   1 -
 clang/lib/CodeGen/CMakeLists.txt              |   1 +
 .../QualtypeMapper.cpp}                       | 128 ++++++++++--------
 llvm/include/llvm/ABI/Types.h                 |  26 +++-
 6 files changed, 117 insertions(+), 106 deletions(-)
 rename clang/include/clang/{ABI/QualTypeMapper.h => CodeGen/QualtypeMapper.h} (59%)
 delete mode 100644 clang/lib/ABI/CMakeLists.txt
 rename clang/lib/{ABI/QualTypeMapper.cpp => CodeGen/QualtypeMapper.cpp} (67%)

diff --git a/clang/include/clang/ABI/QualTypeMapper.h b/clang/include/clang/CodeGen/QualtypeMapper.h
similarity index 59%
rename from clang/include/clang/ABI/QualTypeMapper.h
rename to clang/include/clang/CodeGen/QualtypeMapper.h
index 70ae9e0f83130..e99c6847a67b0 100644
--- a/clang/include/clang/ABI/QualTypeMapper.h
+++ b/clang/include/clang/CodeGen/QualtypeMapper.h
@@ -1,35 +1,29 @@
-#ifndef LLVM_ABI_QUALTYPE_MAPPER_H
-#define LLVM_ABI_QUALTYPE_MAPPER_H
-
-#include "llvm/IR/DerivedTypes.h"
+//==---- QualtypeMapper.h - Maps Clang Qualtype to LLVMABI Types -----------==//
+//
+// 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
+/// Maps Clang QualType instances to corresponding LLVM ABI type
+/// representations. This mapper translates high-level type information from the
+/// AST into low-level ABI-specific types that encode size, alignment, and
+/// layout details required for code generation and cross-language
+/// interoperability.
+///
+//===----------------------------------------------------------------------===//
+#ifndef CLANG_CODEGEN_QUALTYPE_MAPPER_H
+#define CLANG_CODEGEN_QUALTYPE_MAPPER_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeOrdering.h"
+#include "llvm/ABI/Types.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/Support/Allocator.h"
-#include <clang/AST/ASTContext.h>
-#include <clang/AST/Decl.h>
-#include <clang/AST/Type.h>
-#include <llvm/ABI/Types.h>
-#include <llvm/ADT/DenseMap.h>
-
-// Specialization for QualType
-template <> struct llvm::DenseMapInfo<clang::QualType> {
-  static inline clang::QualType getEmptyKey() {
-    return clang::QualType::getFromOpaquePtr(
-        reinterpret_cast<clang::Type *>(-1));
-  }
-
-  static inline clang::QualType getTombstoneKey() {
-    return clang::QualType::getFromOpaquePtr(
-        reinterpret_cast<clang::Type *>(-2));
-  }
-
-  static unsigned getHashValue(const clang::QualType &Val) {
-    return (unsigned)((uintptr_t)Val.getAsOpaquePtr()) ^
-           ((unsigned)((uintptr_t)Val.getAsOpaquePtr() >> 9));
-  }
-
-  static bool isEqual(const clang::QualType &LHS, const clang::QualType &RHS) {
-    return LHS == RHS;
-  }
-};
 
 namespace clang {
 namespace mapper {
@@ -75,4 +69,4 @@ class QualTypeMapper {
 } // namespace mapper
 } // namespace clang
 
-#endif // !LLVM_ABI_QUALTYPE_MAPPER_H
+#endif // !CLANG_CODEGEN_QUALTYPE_MAPPER_H
diff --git a/clang/lib/ABI/CMakeLists.txt b/clang/lib/ABI/CMakeLists.txt
deleted file mode 100644
index 86a8324b5716a..0000000000000
--- a/clang/lib/ABI/CMakeLists.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-add_clang_library(clangABI
-  QualTypeMapper.cpp
-
-  LINK_LIBS
-  clangAST
-  clangBasic
-  LLVMABI
-  LLVMSupport
-)
diff --git a/clang/lib/CMakeLists.txt b/clang/lib/CMakeLists.txt
index f034622c06c2f..4f2218b583e41 100644
--- a/clang/lib/CMakeLists.txt
+++ b/clang/lib/CMakeLists.txt
@@ -1,4 +1,3 @@
-add_subdirectory(ABI)
 add_subdirectory(Headers)
 add_subdirectory(Basic)
 add_subdirectory(APINotes)
diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt
index a05b31f971e18..c70862a05d35d 100644
--- a/clang/lib/CodeGen/CMakeLists.txt
+++ b/clang/lib/CodeGen/CMakeLists.txt
@@ -115,6 +115,7 @@ add_clang_library(clangCodeGen
   ModuleBuilder.cpp
   ObjectFilePCHContainerWriter.cpp
   PatternInit.cpp
+  QualtypeMapper.cpp
   SanitizerMetadata.cpp
   SwiftCallingConv.cpp
   TargetBuiltins/ARM.cpp
diff --git a/clang/lib/ABI/QualTypeMapper.cpp b/clang/lib/CodeGen/QualtypeMapper.cpp
similarity index 67%
rename from clang/lib/ABI/QualTypeMapper.cpp
rename to clang/lib/CodeGen/QualtypeMapper.cpp
index 22070f250026e..f1577383af4dc 100644
--- a/clang/lib/ABI/QualTypeMapper.cpp
+++ b/clang/lib/CodeGen/QualtypeMapper.cpp
@@ -1,12 +1,28 @@
+//==---- QualtypeMapper.cpp - Maps Clang Qualtype to LLVMABI Types ---------==//
+//
+// 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
+/// Maps Clang QualType instances to corresponding LLVM ABI type
+/// representations. This mapper translates high-level type information from the
+/// AST into low-level ABI-specific types that encode size, alignment, and
+/// layout details required for code generation and cross-language
+/// interoperability.
+///
+//===----------------------------------------------------------------------===//
+#include "clang/CodeGen/QualtypeMapper.h"
+#include "clang/AST/Decl.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/AST/Type.h"
-#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/TargetInfo.h"
 #include "llvm/ABI/Types.h"
 #include "llvm/Support/Alignment.h"
-#include "llvm/Support/Casting.h"
-#include <clang/ABI/QualTypeMapper.h>
+#include "llvm/Support/TypeSize.h"
 
 namespace clang {
 namespace mapper {
@@ -40,87 +56,44 @@ const llvm::abi::Type *QualTypeMapper::convertType(QualType QT) {
 
 const llvm::abi::Type *
 QualTypeMapper::convertBuiltinType(const BuiltinType *BT) {
+  QualType QT(BT, 0);
+
   switch (BT->getKind()) {
   case BuiltinType::Void:
     return Builder.getVoidType();
 
   case BuiltinType::Bool:
-  case BuiltinType::UChar:
-  case BuiltinType::Char_U:
-  case BuiltinType::UShort:
-    return Builder.getIntegerType(ASTCtx.getTypeSize(QualType(BT, 0)),
-                                  getTypeAlign(QualType(BT, 0)), false);
-
   case BuiltinType::Char_S:
+  case BuiltinType::Char_U:
   case BuiltinType::SChar:
-  case BuiltinType::Short:
-    return Builder.getIntegerType(ASTCtx.getCharWidth(),
-                                  getTypeAlign(QualType(BT, 0)), true);
-
-  case BuiltinType::WChar_U:
-    return Builder.getIntegerType(ASTCtx.getCharWidth(),
-                                  getTypeAlign(QualType(BT, 0)), false);
-
+  case BuiltinType::UChar:
   case BuiltinType::WChar_S:
-    return Builder.getIntegerType(ASTCtx.getCharWidth(),
-                                  getTypeAlign(QualType(BT, 0)), true);
-
+  case BuiltinType::WChar_U:
   case BuiltinType::Char8:
-    return Builder.getIntegerType(8, getTypeAlign(QualType(BT, 0)), false);
-
   case BuiltinType::Char16:
-    return Builder.getIntegerType(16, getTypeAlign(QualType(BT, 0)), false);
-
   case BuiltinType::Char32:
-    return Builder.getIntegerType(32, getTypeAlign(QualType(BT, 0)), false);
-
+  case BuiltinType::Short:
+  case BuiltinType::UShort:
   case BuiltinType::Int:
   case BuiltinType::UInt:
-    return Builder.getIntegerType(ASTCtx.getIntWidth(QualType(BT, 0)),
-                                  getTypeAlign(QualType(BT, 0)),
-                                  BT->getKind() == BuiltinType::Int);
-
   case BuiltinType::Long:
   case BuiltinType::ULong:
-    return Builder.getIntegerType(ASTCtx.getTypeSize(QualType(BT, 0)),
-                                  getTypeAlign(QualType(BT, 0)),
-                                  BT->getKind() == BuiltinType::Long);
-
   case BuiltinType::LongLong:
   case BuiltinType::ULongLong:
-    return Builder.getIntegerType(ASTCtx.getTypeSize(QualType(BT, 0)),
-                                  getTypeAlign(QualType(BT, 0)),
-                                  BT->getKind() == BuiltinType::LongLong);
-
   case BuiltinType::Int128:
   case BuiltinType::UInt128:
-    return Builder.getIntegerType(128, getTypeAlign(QualType(BT, 0)),
-                                  BT->getKind() == BuiltinType::Int128);
+    return Builder.getIntegerType(ASTCtx.getTypeSize(QT), getTypeAlign(QT),
+                                  BT->isSignedInteger());
 
   case BuiltinType::Half:
   case BuiltinType::Float16:
-    return Builder.getFloatType(llvm::APFloat::IEEEhalf(),
-                                getTypeAlign(QualType(BT, 0)));
-
+  case BuiltinType::BFloat16:
   case BuiltinType::Float:
-    return Builder.getFloatType(llvm::APFloat::IEEEsingle(),
-                                getTypeAlign(QualType(BT, 0)));
-
   case BuiltinType::Double:
-    return Builder.getFloatType(llvm::APFloat::IEEEdouble(),
-                                getTypeAlign(QualType(BT, 0)));
-
   case BuiltinType::LongDouble:
-    return Builder.getFloatType(ASTCtx.getFloatTypeSemantics(QualType(BT, 0)),
-                                getTypeAlign(QualType(BT, 0)));
-
-  case BuiltinType::BFloat16:
-    return Builder.getFloatType(llvm::APFloat::BFloat(),
-                                getTypeAlign(QualType(BT, 0)));
-
   case BuiltinType::Float128:
-    return Builder.getFloatType(llvm::APFloat::IEEEquad(),
-                                getTypeAlign(QualType(BT, 0)));
+    return Builder.getFloatType(ASTCtx.getFloatTypeSemantics(QT),
+                                getTypeAlign(QT));
 
   default:
     return Builder.getIntegerType(ASTCtx.getTypeSize(QualType(BT, 0)),
@@ -171,6 +144,45 @@ QualTypeMapper::convertPointerType(const clang::PointerType *PT) {
   return createPointerTypeForPointee(PT->getPointeeType());
 }
 
+const llvm::abi::Type *
+QualTypeMapper::convertEnumType(const clang::EnumType *ET) {
+  const EnumDecl *ED = ET->getDecl();
+  QualType UnderlyingType = ED->getIntegerType();
+
+  if (UnderlyingType.isNull())
+    UnderlyingType = ASTCtx.IntTy;
+
+  return convertType(UnderlyingType);
+}
+
+const llvm::abi::StructType *
+QualTypeMapper::convertStructType(const clang::RecordDecl *RD) {
+  const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
+
+  SmallVector<llvm::abi::FieldInfo, 16> Fields;
+  computeFieldInfo(RD, Fields, Layout);
+
+  llvm::TypeSize Size =
+      llvm::TypeSize::getFixed(Layout.getSize().getQuantity() * 8);
+  llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity());
+
+  return Builder.getStructType(Fields, Size, Alignment);
+}
+
+const llvm::abi::UnionType *
+QualTypeMapper::convertUnionType(const clang::RecordDecl *RD) {
+  const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
+
+  SmallVector<llvm::abi::FieldInfo, 16> Fields;
+  computeFieldInfo(RD, Fields, Layout);
+
+  llvm::TypeSize Size =
+      llvm::TypeSize::getFixed(Layout.getSize().getQuantity() * 8);
+  llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity());
+
+  return Builder.getUnionType(Fields, Size, Alignment);
+}
+
 llvm::Align QualTypeMapper::getTypeAlign(QualType QT) const {
   return llvm::Align(ASTCtx.getTypeAlign(QT));
 }
diff --git a/llvm/include/llvm/ABI/Types.h b/llvm/include/llvm/ABI/Types.h
index e99bee35acf77..2b91b72e9daf1 100644
--- a/llvm/include/llvm/ABI/Types.h
+++ b/llvm/include/llvm/ABI/Types.h
@@ -1,13 +1,27 @@
+//===- 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 Types and related helper methods concerned to the
+/// LLVMABI library which mirrors ABI related type information from
+/// the LLVM frontend.
+///
+//===----------------------------------------------------------------------===//
 #ifndef LLVM_ABI_TYPES_H
 #define LLVM_ABI_TYPES_H
 
 #include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/IR/CallingConv.h"
 #include "llvm/Support/Alignment.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/TypeSize.h"
 #include <cstdint>
-#include <llvm/IR/CallingConv.h>
 
 namespace llvm {
 namespace abi {
@@ -27,21 +41,21 @@ class Type {
 protected:
   TypeKind Kind;
   TypeSize SizeInBits;
-  Align AlignInBits;
+  Align Alignment;
   bool IsExplicitlyAligned;
 
   Type(TypeKind K, TypeSize Size, Align Align, bool ExplicitAlign = false)
-      : Kind(K), SizeInBits(Size), AlignInBits(Align),
+      : Kind(K), SizeInBits(Size), Alignment(Align),
         IsExplicitlyAligned(ExplicitAlign) {}
 
 public:
   TypeKind getKind() const { return Kind; }
   TypeSize getSizeInBits() const { return SizeInBits; }
-  Align getAlignInBits() const { return AlignInBits; }
+  Align getAlignment() const { return Alignment; }
   bool hasExplicitAlignment() const { return IsExplicitlyAligned; }
 
   void setExplicitAlignment(Align Align) {
-    AlignInBits = Align;
+    Alignment = Align;
     IsExplicitlyAligned = true;
   }
 
@@ -109,7 +123,7 @@ class ArrayType : public Type {
 public:
   ArrayType(const Type *ElemType, uint64_t NumElems)
       : Type(TypeKind::Array, ElemType->getSizeInBits() * NumElems,
-             ElemType->getAlignInBits()),
+             ElemType->getAlignment()),
         ElementType(ElemType), NumElements(NumElems) {}
 
   const Type *getElementType() const { return ElementType; }

>From 74cbee261d6a4292f8a484e0c791598ab5f515ec Mon Sep 17 00:00:00 2001
From: Narayan Sreekumar <nsreekumar6 at gmail.com>
Date: Wed, 4 Jun 2025 17:22:21 +0530
Subject: [PATCH 06/12] [LLVMABI] Support CXX classes with base classes

---
 .../{QualtypeMapper.h => QualTypeMapper.h}    |  3 +-
 clang/lib/CodeGen/CMakeLists.txt              |  2 +-
 ...{QualtypeMapper.cpp => QualTypeMapper.cpp} | 68 +++++++++++++++++--
 3 files changed, 67 insertions(+), 6 deletions(-)
 rename clang/include/clang/CodeGen/{QualtypeMapper.h => QualTypeMapper.h} (94%)
 rename clang/lib/CodeGen/{QualtypeMapper.cpp => QualTypeMapper.cpp} (77%)

diff --git a/clang/include/clang/CodeGen/QualtypeMapper.h b/clang/include/clang/CodeGen/QualTypeMapper.h
similarity index 94%
rename from clang/include/clang/CodeGen/QualtypeMapper.h
rename to clang/include/clang/CodeGen/QualTypeMapper.h
index e99c6847a67b0..d0a2d29093d15 100644
--- a/clang/include/clang/CodeGen/QualtypeMapper.h
+++ b/clang/include/clang/CodeGen/QualTypeMapper.h
@@ -1,4 +1,4 @@
-//==---- QualtypeMapper.h - Maps Clang Qualtype to LLVMABI Types -----------==//
+//==---- QualTypeMapper.h - Maps Clang QualType to LLVMABI Types -----------==//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -45,6 +45,7 @@ class QualTypeMapper {
   const llvm::abi::StructType *convertStructType(const clang::RecordDecl *RD);
   const llvm::abi::UnionType *convertUnionType(const clang::RecordDecl *RD);
   const llvm::abi::Type *createPointerTypeForPointee(QualType PointeeType);
+  const llvm::abi::StructType *convertCXXRecordType(const CXXRecordDecl *RD);
 
   void computeFieldInfo(const clang::RecordDecl *RD,
                         SmallVectorImpl<llvm::abi::FieldInfo> &Fields,
diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt
index c70862a05d35d..f805819de300f 100644
--- a/clang/lib/CodeGen/CMakeLists.txt
+++ b/clang/lib/CodeGen/CMakeLists.txt
@@ -115,7 +115,7 @@ add_clang_library(clangCodeGen
   ModuleBuilder.cpp
   ObjectFilePCHContainerWriter.cpp
   PatternInit.cpp
-  QualtypeMapper.cpp
+  QualTypeMapper.cpp
   SanitizerMetadata.cpp
   SwiftCallingConv.cpp
   TargetBuiltins/ARM.cpp
diff --git a/clang/lib/CodeGen/QualtypeMapper.cpp b/clang/lib/CodeGen/QualTypeMapper.cpp
similarity index 77%
rename from clang/lib/CodeGen/QualtypeMapper.cpp
rename to clang/lib/CodeGen/QualTypeMapper.cpp
index f1577383af4dc..41fd70c9b1855 100644
--- a/clang/lib/CodeGen/QualtypeMapper.cpp
+++ b/clang/lib/CodeGen/QualTypeMapper.cpp
@@ -1,4 +1,4 @@
-//==---- QualtypeMapper.cpp - Maps Clang Qualtype to LLVMABI Types ---------==//
+//==---- QualTypeMapper.cpp - Maps Clang QualType to LLVMABI Types ---------==//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -14,8 +14,9 @@
 /// interoperability.
 ///
 //===----------------------------------------------------------------------===//
-#include "clang/CodeGen/QualtypeMapper.h"
+#include "clang/CodeGen/QualTypeMapper.h"
 #include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/LLVM.h"
@@ -48,7 +49,7 @@ const llvm::abi::Type *QualTypeMapper::convertType(QualType QT) {
   } else if (const auto *ET = dyn_cast<EnumType>(QT.getTypePtr())) {
     Result = convertEnumType(ET);
   } else {
-    // TODO: Write Fallback logic for unsupported types.
+    llvm_unreachable("Unsupported type for ABI lowering");
   }
   TypeCache[QT] = Result;
   return Result;
@@ -113,7 +114,6 @@ QualTypeMapper::convertArrayType(const clang::ArrayType *AT) {
     return Builder.getArrayType(ElementType, 0);
   if (const auto *VAT = dyn_cast<VariableArrayType>(AT))
     return createPointerTypeForPointee(VAT->getPointeeType());
-  // TODO: This of a better fallback.
   return Builder.getArrayType(ElementType, 1);
 }
 
@@ -136,9 +136,69 @@ const llvm::abi::Type *QualTypeMapper::convertRecordType(const RecordType *RT) {
 
   if (RD->isUnion())
     return convertUnionType(RD);
+
+  // Handle C++ classes with base classes
+  auto *const CXXRd = dyn_cast<CXXRecordDecl>(RD);
+  if (CXXRd && (CXXRd->getNumBases() > 0 || CXXRd->getNumVBases() > 0)) {
+    return convertCXXRecordType(CXXRd);
+  }
   return convertStructType(RD);
 }
 
+const llvm::abi::StructType *
+QualTypeMapper::convertCXXRecordType(const CXXRecordDecl *RD) {
+  const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
+  SmallVector<llvm::abi::FieldInfo, 16> Fields;
+
+  if (RD->isPolymorphic()) {
+    const llvm::abi::Type *VtablePointer =
+        createPointerTypeForPointee(ASTCtx.VoidPtrTy);
+    Fields.emplace_back(VtablePointer, 0);
+  }
+
+  for (const auto &Base : RD->bases()) {
+    if (Base.isVirtual())
+      continue;
+
+    const RecordType *BaseRT = Base.getType()->getAs<RecordType>();
+    if (!BaseRT)
+      continue;
+
+    const llvm::abi::Type *BaseType = convertType(Base.getType());
+    uint64_t BaseOffset =
+        Layout.getBaseClassOffset(BaseRT->getAsCXXRecordDecl()).getQuantity() *
+        8;
+
+    Fields.emplace_back(BaseType, BaseOffset);
+  }
+
+  for (const auto &VBase : RD->vbases()) {
+    const RecordType *VBaseRT = VBase.getType()->getAs<RecordType>();
+    if (!VBaseRT)
+      continue;
+
+    const llvm::abi::Type *VBaseType = convertType(VBase.getType());
+    uint64_t VBaseOffset =
+        Layout.getVBaseClassOffset(VBaseRT->getAsCXXRecordDecl())
+            .getQuantity() *
+        8;
+
+    Fields.emplace_back(VBaseType, VBaseOffset);
+  }
+  computeFieldInfo(RD, Fields, Layout);
+
+  llvm::sort(Fields,
+             [](const llvm::abi::FieldInfo &A, const llvm::abi::FieldInfo &B) {
+               return A.OffsetInBits < B.OffsetInBits;
+             });
+
+  llvm::TypeSize Size =
+      llvm::TypeSize::getFixed(Layout.getSize().getQuantity() * 8);
+  llvm::Align Alignment = llvm::Align(Layout.getAlignment().getQuantity());
+
+  return Builder.getStructType(Fields, Size, Alignment);
+}
+
 const llvm::abi::Type *
 QualTypeMapper::convertPointerType(const clang::PointerType *PT) {
   return createPointerTypeForPointee(PT->getPointeeType());

>From da1bef05de4e9ec2abfb63fcf19acefd9cbc736f Mon Sep 17 00:00:00 2001
From: Narayan Sreekumar <nsreekumar6 at gmail.com>
Date: Thu, 5 Jun 2025 01:00:47 +0530
Subject: [PATCH 07/12] [LLVMABI] Mapper Benchmark 1

---
 clang/include/clang/CodeGen/QualTypeMapper.h |  1 +
 clang/lib/CodeGen/QualTypeMapper.cpp         | 55 +++++++++++++++++++-
 2 files changed, 54 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/CodeGen/QualTypeMapper.h b/clang/include/clang/CodeGen/QualTypeMapper.h
index d0a2d29093d15..94fc74763a8ee 100644
--- a/clang/include/clang/CodeGen/QualTypeMapper.h
+++ b/clang/include/clang/CodeGen/QualTypeMapper.h
@@ -41,6 +41,7 @@ class QualTypeMapper {
   const llvm::abi::Type *convertVectorType(const clang::VectorType *VT);
   const llvm::abi::Type *convertRecordType(const clang::RecordType *RT);
   const llvm::abi::Type *convertEnumType(const clang::EnumType *ET);
+  const llvm::abi::Type *convertReferenceType(const ReferenceType *RT);
 
   const llvm::abi::StructType *convertStructType(const clang::RecordDecl *RD);
   const llvm::abi::UnionType *convertUnionType(const clang::RecordDecl *RD);
diff --git a/clang/lib/CodeGen/QualTypeMapper.cpp b/clang/lib/CodeGen/QualTypeMapper.cpp
index 41fd70c9b1855..b78b815b85880 100644
--- a/clang/lib/CodeGen/QualTypeMapper.cpp
+++ b/clang/lib/CodeGen/QualTypeMapper.cpp
@@ -19,11 +19,13 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/AST/Type.h"
+#include "clang/Basic/AddressSpaces.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/TargetInfo.h"
 #include "llvm/ABI/Types.h"
 #include "llvm/Support/Alignment.h"
 #include "llvm/Support/TypeSize.h"
+#include "llvm/Support/raw_ostream.h"
 
 namespace clang {
 namespace mapper {
@@ -40,6 +42,8 @@ const llvm::abi::Type *QualTypeMapper::convertType(QualType QT) {
     Result = convertBuiltinType(BT);
   } else if (const auto *PT = dyn_cast<PointerType>(QT.getTypePtr())) {
     Result = convertPointerType(PT);
+  } else if (const auto *RT = dyn_cast<ReferenceType>(QT.getTypePtr())) {
+    Result = convertReferenceType(RT);
   } else if (const auto *AT = dyn_cast<ArrayType>(QT.getTypePtr())) {
     Result = convertArrayType(AT);
   } else if (const auto *VT = dyn_cast<VectorType>(QT.getTypePtr())) {
@@ -48,6 +52,18 @@ const llvm::abi::Type *QualTypeMapper::convertType(QualType QT) {
     Result = convertRecordType(RT);
   } else if (const auto *ET = dyn_cast<EnumType>(QT.getTypePtr())) {
     Result = convertEnumType(ET);
+  } else if (const auto *BIT = dyn_cast<BitIntType>(QT.getTypePtr())) {
+    QualType QT(BIT, 0);
+    uint64_t NumBits = BIT->getNumBits();
+    bool IsSigned = BIT->isSigned();
+    llvm::Align TypeAlign = getTypeAlign(QT);
+    return Builder.getIntegerType(NumBits, TypeAlign, IsSigned);
+  } else if (isa<ObjCObjectType>(QT.getTypePtr()) ||
+             isa<ObjCObjectPointerType>(QT.getTypePtr())) {
+    auto PointerSize = ASTCtx.getTargetInfo().getPointerWidth(LangAS::Default);
+    llvm::Align PointerAlign =
+        llvm::Align(ASTCtx.getTargetInfo().getPointerAlign(LangAS::Default));
+    return Builder.getPointerType(PointerSize, PointerAlign);
   } else {
     llvm_unreachable("Unsupported type for ABI lowering");
   }
@@ -199,6 +215,11 @@ QualTypeMapper::convertCXXRecordType(const CXXRecordDecl *RD) {
   return Builder.getStructType(Fields, Size, Alignment);
 }
 
+const llvm::abi::Type *
+QualTypeMapper::convertReferenceType(const ReferenceType *RT) {
+  return createPointerTypeForPointee(RT->getPointeeType());
+}
+
 const llvm::abi::Type *
 QualTypeMapper::convertPointerType(const clang::PointerType *PT) {
   return createPointerTypeForPointee(PT->getPointeeType());
@@ -206,13 +227,43 @@ QualTypeMapper::convertPointerType(const clang::PointerType *PT) {
 
 const llvm::abi::Type *
 QualTypeMapper::convertEnumType(const clang::EnumType *ET) {
+  if (!ET)
+    return Builder.getIntegerType(32, llvm::Align(4), true);
   const EnumDecl *ED = ET->getDecl();
+  if (!ED)
+    return Builder.getIntegerType(32, llvm::Align(4), true);
+  if (ED->isInvalidDecl())
+    return Builder.getIntegerType(32, llvm::Align(4), true);
+
+  if (!ED->isComplete()) {
+    if (ED->isFixed()) {
+      QualType UnderlyingType = ED->getIntegerType();
+      if (!UnderlyingType.isNull()) {
+        return convertType(UnderlyingType);
+      }
+    }
+    return Builder.getIntegerType(32, llvm::Align(4), true);
+  }
   QualType UnderlyingType = ED->getIntegerType();
 
-  if (UnderlyingType.isNull())
+  if (UnderlyingType.isNull()) {
+    UnderlyingType = ED->getPromotionType();
+  }
+
+  if (UnderlyingType.isNull()) {
     UnderlyingType = ASTCtx.IntTy;
+  }
+
+  if (const auto *BT = dyn_cast<BuiltinType>(UnderlyingType.getTypePtr())) {
+    return convertBuiltinType(BT);
+  }
+
+  // For non-builtin underlying types, extract type information safely
+  uint64_t TypeSize = ASTCtx.getTypeSize(UnderlyingType);
+  llvm::Align TypeAlign = getTypeAlign(UnderlyingType);
+  bool IsSigned = UnderlyingType->isSignedIntegerType();
 
-  return convertType(UnderlyingType);
+  return Builder.getIntegerType(TypeSize, TypeAlign, IsSigned);
 }
 
 const llvm::abi::StructType *

>From 3ac524826fb8855b82c65956502c7e5d4ae6b5d6 Mon Sep 17 00:00:00 2001
From: Narayan Sreekumar <nsreekumar6 at gmail.com>
Date: Sun, 8 Jun 2025 18:39:14 +0530
Subject: [PATCH 08/12] [LLVMABI] Refactor and Docs

---
 clang/lib/CodeGen/QualTypeMapper.cpp | 96 ++++++++++++++++++++++++----
 llvm/include/llvm/ABI/Types.h        | 16 +++--
 2 files changed, 96 insertions(+), 16 deletions(-)

diff --git a/clang/lib/CodeGen/QualTypeMapper.cpp b/clang/lib/CodeGen/QualTypeMapper.cpp
index b78b815b85880..420c25975a844 100644
--- a/clang/lib/CodeGen/QualTypeMapper.cpp
+++ b/clang/lib/CodeGen/QualTypeMapper.cpp
@@ -30,9 +30,18 @@
 namespace clang {
 namespace mapper {
 
+/// Main entry point for converting Clang QualType to LLVM ABI Type.
+/// This method performs type canonicalization, caching, and dispatches
+/// to specialized conversion methods based on the type kind.
+///
+/// \param QT The Clang QualType to convert
+/// \return Corresponding LLVM ABI Type representation, or nullptr on error
 const llvm::abi::Type *QualTypeMapper::convertType(QualType QT) {
+  // Canonicalize type and strip qualifiers
+  // This ensures consistent type representation across different contexts
   QT = QT.getCanonicalType().getUnqualifiedType();
 
+  // Results are cached since type conversion may be expensive
   auto It = TypeCache.find(QT);
   if (It != TypeCache.end())
     return It->second;
@@ -53,6 +62,7 @@ const llvm::abi::Type *QualTypeMapper::convertType(QualType QT) {
   } else if (const auto *ET = dyn_cast<EnumType>(QT.getTypePtr())) {
     Result = convertEnumType(ET);
   } else if (const auto *BIT = dyn_cast<BitIntType>(QT.getTypePtr())) {
+    // Handle C23 _BitInt(N) types - arbitrary precision integers
     QualType QT(BIT, 0);
     uint64_t NumBits = BIT->getNumBits();
     bool IsSigned = BIT->isSigned();
@@ -60,6 +70,7 @@ const llvm::abi::Type *QualTypeMapper::convertType(QualType QT) {
     return Builder.getIntegerType(NumBits, TypeAlign, IsSigned);
   } else if (isa<ObjCObjectType>(QT.getTypePtr()) ||
              isa<ObjCObjectPointerType>(QT.getTypePtr())) {
+    // Objective-C objects are represented as pointers in the ABI
     auto PointerSize = ASTCtx.getTargetInfo().getPointerWidth(LangAS::Default);
     llvm::Align PointerAlign =
         llvm::Align(ASTCtx.getTargetInfo().getPointerAlign(LangAS::Default));
@@ -71,6 +82,12 @@ const llvm::abi::Type *QualTypeMapper::convertType(QualType QT) {
   return Result;
 }
 
+/// Converts C/C++ builtin types to LLVM ABI types.
+/// This handles all fundamental scalar types including integers, floats,
+/// and special types like void and bool.
+///
+/// \param BT The BuiltinType to convert
+/// \return Corresponding LLVM ABI integer, float, or void type
 const llvm::abi::Type *
 QualTypeMapper::convertBuiltinType(const BuiltinType *BT) {
   QualType QT(BT, 0);
@@ -113,11 +130,18 @@ QualTypeMapper::convertBuiltinType(const BuiltinType *BT) {
                                 getTypeAlign(QT));
 
   default:
+    // Unhandled BuiltinTypes are treated as unsigned integers.
     return Builder.getIntegerType(ASTCtx.getTypeSize(QualType(BT, 0)),
                                   getTypeAlign(QualType(BT, 0)), false);
   }
 }
 
+/// Converts array types to LLVM ABI array representations.
+/// Handles different array kinds: constant arrays, incomplete arrays,
+/// and variable-length arrays.
+///
+/// \param AT The ArrayType to convert
+/// \return LLVM ABI ArrayType or PointerType
 const llvm::abi::Type *
 QualTypeMapper::convertArrayType(const clang::ArrayType *AT) {
   const llvm::abi::Type *ElementType = convertType(AT->getElementType());
@@ -130,9 +154,14 @@ QualTypeMapper::convertArrayType(const clang::ArrayType *AT) {
     return Builder.getArrayType(ElementType, 0);
   if (const auto *VAT = dyn_cast<VariableArrayType>(AT))
     return createPointerTypeForPointee(VAT->getPointeeType());
+  // Fallback for other array types
   return Builder.getArrayType(ElementType, 1);
 }
 
+/// Converts vector types to LLVM ABI vector representations.
+///
+/// \param VT The VectorType to convert
+/// \return LLVM ABI VectorType with element type, count, and alignment
 const llvm::abi::Type *QualTypeMapper::convertVectorType(const VectorType *VT) {
   const llvm::abi::Type *ElementType = convertType(VT->getElementType());
   uint64_t NumElements = VT->getNumElements();
@@ -142,6 +171,12 @@ const llvm::abi::Type *QualTypeMapper::convertVectorType(const VectorType *VT) {
   return Builder.getVectorType(ElementType, NumElements, VectorAlign);
 }
 
+/// Converts record types (struct/class/union) to LLVM ABI representations.
+/// This is the main dispatch method that handles different record kinds
+/// and delegates to specialized converters.
+///
+/// \param RT The RecordType to convert
+/// \return LLVM ABI StructType or UnionType
 const llvm::abi::Type *QualTypeMapper::convertRecordType(const RecordType *RT) {
   const RecordDecl *RD = RT->getDecl()->getDefinition();
   if (!RD) {
@@ -161,6 +196,14 @@ const llvm::abi::Type *QualTypeMapper::convertRecordType(const RecordType *RT) {
   return convertStructType(RD);
 }
 
+/// Converts C++ classes with inheritance to LLVM ABI struct representations.
+/// This method handles the complex layout of C++ objects including:
+/// - Virtual table pointers for polymorphic classes
+/// - Base class subobjects (both direct and virtual bases)
+/// - Member field layout with proper offsets
+///
+/// \param RD The C++ record declaration
+/// \return LLVM ABI StructType representing the complete object layout
 const llvm::abi::StructType *
 QualTypeMapper::convertCXXRecordType(const CXXRecordDecl *RD) {
   const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
@@ -176,9 +219,7 @@ QualTypeMapper::convertCXXRecordType(const CXXRecordDecl *RD) {
     if (Base.isVirtual())
       continue;
 
-    const RecordType *BaseRT = Base.getType()->getAs<RecordType>();
-    if (!BaseRT)
-      continue;
+    const RecordType *BaseRT = Base.getType()->castAs<RecordType>();
 
     const llvm::abi::Type *BaseType = convertType(Base.getType());
     uint64_t BaseOffset =
@@ -215,16 +256,33 @@ QualTypeMapper::convertCXXRecordType(const CXXRecordDecl *RD) {
   return Builder.getStructType(Fields, Size, Alignment);
 }
 
+/// Converts reference types to pointer representations in the ABI.
+/// Both lvalue references (T&) and rvalue references (T&&) are represented
+/// as pointers at the ABI level.
+///
+/// \param RT The ReferenceType to convert
+/// \return LLVM ABI PointerType
 const llvm::abi::Type *
 QualTypeMapper::convertReferenceType(const ReferenceType *RT) {
   return createPointerTypeForPointee(RT->getPointeeType());
 }
 
+/// Converts pointer types to LLVM ABI pointer representations.
+/// Takes into account address space information for the pointed-to type.
+///
+/// \param PT The PointerType to convert
+/// \return LLVM ABI PointerType with appropriate size and alignment
 const llvm::abi::Type *
 QualTypeMapper::convertPointerType(const clang::PointerType *PT) {
   return createPointerTypeForPointee(PT->getPointeeType());
 }
 
+/// Converts enumeration types to their underlying integer representations.
+/// This method handles various enum states and falls back to safe defaults
+/// when enum information is incomplete or invalid.
+///
+/// \param ET The EnumType to convert
+/// \return LLVM ABI IntegerType representing the enum's underlying type
 const llvm::abi::Type *
 QualTypeMapper::convertEnumType(const clang::EnumType *ET) {
   if (!ET)
@@ -246,19 +304,15 @@ QualTypeMapper::convertEnumType(const clang::EnumType *ET) {
   }
   QualType UnderlyingType = ED->getIntegerType();
 
-  if (UnderlyingType.isNull()) {
+  if (UnderlyingType.isNull())
     UnderlyingType = ED->getPromotionType();
-  }
 
-  if (UnderlyingType.isNull()) {
+  if (UnderlyingType.isNull())
     UnderlyingType = ASTCtx.IntTy;
-  }
 
-  if (const auto *BT = dyn_cast<BuiltinType>(UnderlyingType.getTypePtr())) {
+  if (const auto *BT = dyn_cast<BuiltinType>(UnderlyingType.getTypePtr()))
     return convertBuiltinType(BT);
-  }
 
-  // For non-builtin underlying types, extract type information safely
   uint64_t TypeSize = ASTCtx.getTypeSize(UnderlyingType);
   llvm::Align TypeAlign = getTypeAlign(UnderlyingType);
   bool IsSigned = UnderlyingType->isSignedIntegerType();
@@ -266,6 +320,12 @@ QualTypeMapper::convertEnumType(const clang::EnumType *ET) {
   return Builder.getIntegerType(TypeSize, TypeAlign, IsSigned);
 }
 
+/// Converts plain C structs and C++ classes without inheritance.
+/// This handles the simpler case where we only need to layout member fields
+/// without considering base classes or virtual functions.
+///
+/// \param RD The RecordDecl to convert
+/// \return LLVM ABI StructType
 const llvm::abi::StructType *
 QualTypeMapper::convertStructType(const clang::RecordDecl *RD) {
   const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
@@ -280,6 +340,12 @@ QualTypeMapper::convertStructType(const clang::RecordDecl *RD) {
   return Builder.getStructType(Fields, Size, Alignment);
 }
 
+/// Converts C union types where all fields occupy the same memory location.
+/// The union size is determined by its largest member, and all fields
+/// start at offset 0.
+///
+/// \param RD The RecordDecl representing the union
+/// \return LLVM ABI UnionType
 const llvm::abi::UnionType *
 QualTypeMapper::convertUnionType(const clang::RecordDecl *RD) {
   const ASTRecordLayout &Layout = ASTCtx.getASTRecordLayout(RD);
@@ -307,6 +373,13 @@ QualTypeMapper::createPointerTypeForPointee(QualType PointeeType) {
   return Builder.getPointerType(PointerSize, Alignment);
 }
 
+/// Processes the fields of a record (struct/class/union) and populates
+/// the Fields vector with FieldInfo objects containing type, offset,
+/// and bitfield information.
+///
+/// \param RD The RecordDecl whose fields to process
+/// \param Fields Output vector to populate with field information
+/// \param Layout The AST record layout containing field offset information
 void QualTypeMapper::computeFieldInfo(
     const RecordDecl *RD, SmallVectorImpl<llvm::abi::FieldInfo> &Fields,
     const ASTRecordLayout &Layout) {
@@ -319,9 +392,8 @@ void QualTypeMapper::computeFieldInfo(
     bool IsBitField = FD->isBitField();
     uint64_t BitFieldWidth = 0;
 
-    if (IsBitField) {
+    if (IsBitField)
       BitFieldWidth = FD->getBitWidthValue();
-    }
 
     Fields.emplace_back(FieldType, OffsetInBits, IsBitField, BitFieldWidth);
     ++FieldIndex;
diff --git a/llvm/include/llvm/ABI/Types.h b/llvm/include/llvm/ABI/Types.h
index 2b91b72e9daf1..e4642142662d3 100644
--- a/llvm/include/llvm/ABI/Types.h
+++ b/llvm/include/llvm/ABI/Types.h
@@ -135,15 +135,23 @@ class ArrayType : public Type {
 class VectorType : public Type {
 private:
   const Type *ElementType;
-  uint64_t NumElements;
+  ElementCount NumElements;
 
 public:
-  VectorType(const Type *ElemType, uint64_t NumElems, Align Align)
-      : Type(TypeKind::Vector, ElemType->getSizeInBits() * NumElems, Align),
+  VectorType(const Type *ElemType, ElementCount NumElems, Align Align)
+      : Type(
+            TypeKind::Vector,
+            NumElems.isScalable()
+                ? TypeSize(ElemType->getSizeInBits().getFixedValue() *
+                               NumElems.getKnownMinValue(),
+                           true)
+                : TypeSize::getFixed(ElemType->getSizeInBits().getFixedValue() *
+                                     NumElems.getFixedValue()),
+            Align),
         ElementType(ElemType), NumElements(NumElems) {}
 
   const Type *getElementType() const { return ElementType; }
-  uint64_t getNumElements() const { return NumElements; }
+  ElementCount getNumElements() const { return NumElements; }
 
   static bool classof(const Type *T) {
     return T->getKind() == TypeKind::Vector;

>From 0f045dabf0fe045c2812d8062ade8dad66eeb64a Mon Sep 17 00:00:00 2001
From: Narayan Sreekumar <nsreekumar6 at gmail.com>
Date: Thu, 12 Jun 2025 23:18:12 +0530
Subject: [PATCH 09/12] [LLVMABI] Init ABIInfo

---
 llvm/include/llvm/ABI/ABIFunctionInfo.h | 172 ++++++++++++++++++++++++
 llvm/include/llvm/ABI/ABIInfo.h         | 136 +++++++++++++++++++
 llvm/lib/ABI/ABIFunctionInfo.cpp        |  40 ++++++
 3 files changed, 348 insertions(+)
 create mode 100644 llvm/include/llvm/ABI/ABIFunctionInfo.h
 create mode 100644 llvm/include/llvm/ABI/ABIInfo.h
 create mode 100644 llvm/lib/ABI/ABIFunctionInfo.cpp

diff --git a/llvm/include/llvm/ABI/ABIFunctionInfo.h b/llvm/include/llvm/ABI/ABIFunctionInfo.h
new file mode 100644
index 0000000000000..b0a590373b586
--- /dev/null
+++ b/llvm/include/llvm/ABI/ABIFunctionInfo.h
@@ -0,0 +1,172 @@
+//===----- ABIFunctionInfo.h - ABI Function Information ----- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines ABIFunctionInfo and associated types used in representing the
+// ABI-coerced types for function arguments and return values.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ABI_ABIFUNCTIONINFO_H
+#define LLVM_ABI_ABIFUNCTIONINFO_H
+
+#include "ABIInfo.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/IR/CallingConv.h"
+#include "llvm/Support/TrailingObjects.h"
+
+namespace llvm {
+namespace abi {
+
+struct FunctionABIInfo {
+  llvm::CallingConv::ID CC = llvm::CallingConv::C;
+  llvm::CallingConv::ID EffectiveCC = llvm::CallingConv::C;
+
+  // Core ABI attributes
+  bool NoReturn = false;
+  bool NoUnwind = false;
+  bool HasSRet = false;
+  bool IsVariadic = false;
+  bool IsInstanceMethod = false;
+  // Are these ABI Relavent(?)
+  bool IsChainCall = false;
+  bool IsDelegateCall = false;
+
+  // Register usage controls
+  bool HasRegParm = false;
+  unsigned RegParm = 0;
+  bool NoCallerSavedRegs = false;
+  // Security/extensions(are they ABI related?)
+  bool NoCfCheck = false;
+  bool CmseNSCall = false;
+
+  // Optimization hints
+  bool ReturnsRetained = false;
+  unsigned MaxVectorWidth = 0;
+
+  FunctionABIInfo() = default;
+  FunctionABIInfo(llvm::CallingConv::ID CC) : CC(CC), EffectiveCC(CC) {}
+};
+
+// Not an Immediate requirement for BPF
+struct RequiredArgs {
+private:
+  unsigned NumRequired;
+  static constexpr unsigned All = ~0U;
+
+public:
+  RequiredArgs() : NumRequired(All) {}
+  explicit RequiredArgs(unsigned N) : NumRequired(N) {}
+
+  static RequiredArgs forPrototypedFunction(unsigned NumArgs) {
+    return RequiredArgs(NumArgs);
+  }
+
+  static RequiredArgs forVariadicFunction(unsigned NumRequired) {
+    return RequiredArgs(NumRequired);
+  }
+
+  bool allowsOptionalArgs() const { return NumRequired != All; }
+
+  unsigned getNumRequiredArgs() const {
+    return allowsOptionalArgs() ? NumRequired : 0;
+  }
+
+  bool operator==(const RequiredArgs &Other) const {
+    return NumRequired == Other.NumRequired;
+  }
+};
+
+// Implementation detail of ABIFunctionInfo, factored out so it can be named
+// in the TrailingObjects base class of ABIFunctionInfo.
+struct ABIFunctionInfoArgInfo {
+  const Type *ABIType;
+  ABIArgInfo ArgInfo;
+
+  ABIFunctionInfoArgInfo()
+      : ABIType(nullptr), ArgInfo(ABIArgInfo::getDirect()) {}
+  ABIFunctionInfoArgInfo(Type *T)
+      : ABIType(T), ArgInfo(ABIArgInfo::getDirect()) {}
+  ABIFunctionInfoArgInfo(Type *T, ABIArgInfo A) : ABIType(T), ArgInfo(A) {}
+};
+
+class ABIFunctionInfo final
+    : public llvm::FoldingSetNode,
+      private TrailingObjects<ABIFunctionInfo, ABIFunctionInfoArgInfo> {
+  typedef ABIFunctionInfoArgInfo ArgInfo;
+
+private:
+  const Type *ReturnType;
+  ABIArgInfo ReturnInfo;
+  unsigned NumArgs;
+  FunctionABIInfo ABIInfo;
+  RequiredArgs
+      Required; // For Variadic Functions but we can focus on this later
+
+  ABIFunctionInfo(const Type *RetTy, unsigned NumArguments)
+      : ReturnType(RetTy), ReturnInfo(ABIArgInfo::getDirect()),
+        NumArgs(NumArguments) {}
+
+  friend class TrailingObjects;
+
+public:
+  static ABIFunctionInfo *
+  create(llvm::CallingConv::ID CC, const Type *ReturnType,
+         llvm::ArrayRef<const Type *> ArgTypes,
+         const FunctionABIInfo &ABIInfo = FunctionABIInfo(),
+         RequiredArgs Required = RequiredArgs());
+
+  const Type *getReturnType() const { return ReturnType; }
+  ABIArgInfo &getReturnInfo() { return ReturnInfo; }
+  const ABIArgInfo &getReturnInfo() const { return ReturnInfo; }
+
+  llvm::CallingConv::ID getCallingConvention() const { return ABIInfo.CC; }
+
+  const FunctionABIInfo &getExtInfo() const { return ABIInfo; }
+  RequiredArgs getRequiredArgs() const { return Required; }
+  llvm::ArrayRef<ArgInfo> arguments() const {
+    return {getTrailingObjects<ArgInfo>(), NumArgs};
+  }
+
+  llvm::MutableArrayRef<ArgInfo> arguments() {
+    return {getTrailingObjects<ArgInfo>(), NumArgs};
+  }
+
+  ArgInfo &getArgInfo(unsigned Index) {
+    assert(Index < NumArgs && "Invalid argument index");
+    return arguments()[Index];
+  }
+
+  const ArgInfo &getArgInfo(unsigned Index) const {
+    assert(Index < NumArgs && "Invalid argument index");
+    return arguments()[Index];
+  }
+  void Profile(llvm::FoldingSetNodeID &ID) const {
+    ID.AddInteger(static_cast<unsigned>(ABIInfo.CC));
+    ID.AddPointer(ReturnType);
+    ID.AddInteger(static_cast<unsigned>(ReturnInfo.getKind()));
+    if (ReturnInfo.getCoerceToType())
+      ID.AddPointer(ReturnInfo.getCoerceToType());
+    ID.AddInteger(NumArgs);
+    for (const auto &ArgInfo : arguments()) {
+      ID.AddPointer(ArgInfo.ABIType);
+      ID.AddInteger(static_cast<unsigned>(ArgInfo.ArgInfo.getKind()));
+      if (ArgInfo.ArgInfo.getCoerceToType())
+        ID.AddPointer(ArgInfo.ArgInfo.getCoerceToType());
+    }
+    ID.AddInteger(Required.getNumRequiredArgs());
+    ID.AddBoolean(Required.allowsOptionalArgs());
+    ID.AddBoolean(ABIInfo.NoReturn);
+    ID.AddBoolean(ABIInfo.IsVariadic);
+    // TODO: Add more flags
+  }
+};
+} // namespace abi
+} // namespace llvm
+
+#endif // !LLVM_ABI_ABIFUNCTIONINFO_H
diff --git a/llvm/include/llvm/ABI/ABIInfo.h b/llvm/include/llvm/ABI/ABIInfo.h
new file mode 100644
index 0000000000000..aa56dd5e96f2c
--- /dev/null
+++ b/llvm/include/llvm/ABI/ABIInfo.h
@@ -0,0 +1,136 @@
+//===----- ABIInfo.h - ABI information access & encapsulation ----- 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
+/// ABI information access & encapsulation
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ABI_ABIINFO_H
+#define LLVM_ABI_ABIINFO_H
+
+#include "llvm/ABI/Types.h"
+#include <cassert>
+
+namespace llvm {
+namespace abi {
+
+/// ABIArgInfo - Helper class to encapsulate information about how a
+/// specific C type should be passed to or returned from a function.
+class ABIArgInfo {
+public:
+  enum Kind { Direct, Indirect, Ignore, Expand, CoerceAndExpand, InAlloca };
+
+private:
+  Kind TheKind;
+  const Type *CoercionType;
+
+  bool InReg : 1;
+  bool PaddingInReg : 1;
+
+  unsigned IndirectAlign : 16;
+  bool IndirectByVal : 1;
+
+  ABIArgInfo(Kind K = Direct)
+      : TheKind(K), CoercionType(nullptr), InReg(false), PaddingInReg(false),
+        IndirectAlign(0), IndirectByVal(false) {}
+
+public:
+  static ABIArgInfo getDirect(const Type *T = nullptr) {
+    ABIArgInfo AI(Direct);
+    AI.CoercionType = T;
+    return AI;
+  }
+
+  static ABIArgInfo getDirectInReg(const Type *T = nullptr) {
+    ABIArgInfo AI = getDirect(T);
+    AI.InReg = true;
+    return AI;
+  }
+
+  static ABIArgInfo getIndirect(unsigned Align = 0, bool ByVal = true) {
+    ABIArgInfo AI(Indirect);
+    AI.IndirectAlign = Align;
+    AI.IndirectByVal = ByVal;
+    return AI;
+  }
+
+  static ABIArgInfo getIndirectInReg(unsigned Align = 0, bool ByVal = true) {
+    ABIArgInfo AI = getIndirect(Align, ByVal);
+    AI.InReg = true;
+    return AI;
+  }
+
+  static ABIArgInfo getIgnore() { return ABIArgInfo(Ignore); }
+
+  static ABIArgInfo getExpand() { return ABIArgInfo(Expand); }
+
+  static ABIArgInfo getCoerceAndExpand(const Type *CoercionType) {
+    ABIArgInfo AI(CoerceAndExpand);
+    AI.CoercionType = CoercionType;
+    return AI;
+  }
+
+  Kind getKind() const { return TheKind; }
+
+  bool isDirect() const { return TheKind == Direct; }
+  bool isIndirect() const { return TheKind == Indirect; }
+  bool isIgnore() const { return TheKind == Ignore; }
+  bool isExpand() const { return TheKind == Expand; }
+  bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; }
+  bool isInAlloca() const { return TheKind == InAlloca; }
+
+  bool isInReg() const { return InReg; }
+  bool hasPaddingInReg() const { return PaddingInReg; }
+
+  unsigned getIndirectAlign() const {
+    assert(isIndirect() && "Only indirect arguments have alignment");
+    return IndirectAlign;
+  }
+
+  bool getIndirectByVal() const {
+    assert(isIndirect() && "Only indirect arguments can be ByVal");
+    return IndirectByVal;
+  }
+
+  const Type *getCoerceToType() const {
+    assert((isDirect() || isCoerceAndExpand()) &&
+           "Only Direct and CoerceAndExpand arguments can have coercion types");
+    return CoercionType;
+  }
+
+  ABIArgInfo &setInReg(bool InReg = true) {
+    this->InReg = InReg;
+    return *this;
+  }
+
+  ABIArgInfo &setPaddingInReg(bool HasPadding = true) {
+    this->PaddingInReg = HasPadding;
+    return *this;
+  }
+};
+
+/// Abstract base class for target-specific ABI information.
+class ABIInfo {
+public:
+  virtual ~ABIInfo() = default;
+
+  virtual ABIArgInfo classifyReturnType(const Type *RetTy) const = 0;
+  virtual ABIArgInfo classifyArgumentType(const Type *ArgTy) const = 0;
+
+  virtual bool isPassByRef(const Type *Ty) const { return false; }
+
+  virtual unsigned getTypeAlignment(const Type *Ty) const = 0;
+
+  virtual unsigned getTypeSize(const Type *Ty) const = 0;
+};
+
+} // namespace abi
+} // namespace llvm
+
+#endif // LLVM_ABI_ABIINFO_H
diff --git a/llvm/lib/ABI/ABIFunctionInfo.cpp b/llvm/lib/ABI/ABIFunctionInfo.cpp
new file mode 100644
index 0000000000000..f0a75fa7f8151
--- /dev/null
+++ b/llvm/lib/ABI/ABIFunctionInfo.cpp
@@ -0,0 +1,40 @@
+//===----- ABIFunctionInfo.cpp - ABI Function Information --------- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ABI/ABIFunctionInfo.h"
+
+using namespace llvm;
+using namespace llvm::abi;
+
+ABIFunctionInfo *ABIFunctionInfo::create(llvm::CallingConv::ID CC,
+                                         const Type *ReturnType,
+                                         llvm::ArrayRef<const Type *> ArgTypes,
+                                         const FunctionABIInfo &ABIInfo,
+                                         RequiredArgs Required) {
+
+  assert(!Required.allowsOptionalArgs() ||
+         Required.getNumRequiredArgs() <= ArgTypes.size());
+
+  void *Buffer = operator new(
+      totalSizeToAlloc<ABIFunctionInfoArgInfo>(ArgTypes.size()));
+
+  ABIFunctionInfo *FI =
+      new (Buffer) ABIFunctionInfo(ReturnType, ArgTypes.size());
+
+  FI->ABIInfo = ABIInfo;
+  FI->ABIInfo.CC = CC;
+  FI->Required = Required;
+
+  auto Args = FI->arguments();
+  for (unsigned I = 0; I < ArgTypes.size(); ++I) {
+    Args[I].ABIType = ArgTypes[I];
+    Args[I].ArgInfo = ABIArgInfo::getDirect();
+  }
+
+  return FI;
+}

>From b458dab65c9de603926955e2b0b6ae7d820bc06d Mon Sep 17 00:00:00 2001
From: Narayan Sreekumar <nsreekumar6 at gmail.com>
Date: Sat, 14 Jun 2025 01:55:46 +0530
Subject: [PATCH 10/12] [LLVMABI] Added BPF Target

---
 llvm/lib/ABI/Targets/BPF.cpp | 102 +++++++++++++++++++++++++++++++++++
 1 file changed, 102 insertions(+)
 create mode 100644 llvm/lib/ABI/Targets/BPF.cpp

diff --git a/llvm/lib/ABI/Targets/BPF.cpp b/llvm/lib/ABI/Targets/BPF.cpp
new file mode 100644
index 0000000000000..52aff3ca368bd
--- /dev/null
+++ b/llvm/lib/ABI/Targets/BPF.cpp
@@ -0,0 +1,102 @@
+//===- BPF.cpp ------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ABI/ABIInfo.h"
+#include "llvm/ABI/Types.h"
+#include "llvm/Support/Alignment.h"
+#include "llvm/Support/Casting.h"
+
+namespace llvm::abi {
+
+class BPFABIInfo : public ABIInfo {
+private:
+  TypeBuilder &TB;
+
+  bool isAggregateType(const Type *Ty) const {
+    return Ty->isStruct() || Ty->isUnion() || Ty->isArray() ||
+           (Ty->isVector() && !isSimpleVector(dyn_cast<VectorType>(Ty)));
+  }
+
+  bool isSimpleVector(const VectorType *VecTy) const {
+    const Type *ElemTy = VecTy->getElementType();
+
+    if (!ElemTy->isInteger() && !ElemTy->isFloat())
+      return false;
+
+    auto VecSizeInBits = VecTy->getSizeInBits().getFixedValue();
+    return VecSizeInBits <= 128;
+  }
+
+  bool isPromotableIntegerType(const IntegerType *IntTy) const {
+    auto BitWidth = IntTy->getSizeInBits().getFixedValue();
+    return BitWidth > 0 && BitWidth < 32;
+  }
+
+public:
+  BPFABIInfo(TypeBuilder &TypeBuilder) : TB(TypeBuilder) {}
+
+  ABIArgInfo classifyReturnType(const Type *RetTy) const override {
+    if (RetTy->isVoid())
+      return ABIArgInfo::getIgnore();
+
+    if (isAggregateType(RetTy)) {
+      auto SizeInBits = RetTy->getSizeInBits().getFixedValue();
+
+      if (SizeInBits == 0)
+        return ABIArgInfo::getIgnore();
+
+      return ABIArgInfo::getIndirect(RetTy->getAlignment().value());
+    }
+
+    if (const auto *IntTy = dyn_cast<IntegerType>(RetTy)) {
+      if (IntTy->getSizeInBits().getFixedValue() > 128) {
+        return ABIArgInfo::getIndirect(RetTy->getAlignment().value());
+      }
+    }
+
+    return ABIArgInfo::getDirect();
+  }
+
+  ABIArgInfo classifyArgumentType(const Type *ArgTy) const override {
+    if (isAggregateType(ArgTy)) {
+      auto SizeInBits = ArgTy->getSizeInBits().getFixedValue();
+
+      if (SizeInBits == 0)
+        return ABIArgInfo::getIgnore();
+
+      if (SizeInBits <= 128) {
+        const Type *CoerceTy;
+        if (SizeInBits <= 64) {
+          auto AlignedBits = alignTo(SizeInBits, 8);
+          CoerceTy = TB.getIntegerType(AlignedBits, Align(8), false);
+        } else {
+          const Type *RegTy = TB.getIntegerType(64, Align(8), false);
+          CoerceTy = TB.getArrayType(RegTy, 2);
+        }
+        return ABIArgInfo::getDirect(CoerceTy);
+      }
+      return ABIArgInfo::getIndirect(ArgTy->getAlignment().value());
+    }
+
+    if (const auto *IntTy = dyn_cast<IntegerType>(ArgTy)) {
+      auto BitWidth = IntTy->getSizeInBits().getFixedValue();
+      if (BitWidth > 128)
+        return ABIArgInfo::getIndirect(ArgTy->getAlignment().value());
+      if (isPromotableIntegerType(IntTy)) {
+        const Type *PromotedTy =
+            TB.getIntegerType(32, Align(4), IntTy->isSigned());
+        return ABIArgInfo::getDirect(
+            PromotedTy); // change to getExtend when implemented
+      }
+    }
+
+    return ABIArgInfo::getDirect();
+  }
+};
+
+} // namespace llvm::abi

>From 9bfcba959c3bccfae7763f01cea2ed6f99be4cd5 Mon Sep 17 00:00:00 2001
From: Narayan Sreekumar <nsreekumar6 at gmail.com>
Date: Sun, 15 Jun 2025 16:01:47 +0530
Subject: [PATCH 11/12] [LLVMABI] Refactored the BPF Impl

---
 clang/include/clang/CodeGen/QualTypeMapper.h |   4 +-
 clang/lib/CodeGen/QualTypeMapper.cpp         |  35 +---
 llvm/include/llvm/ABI/ABIFunctionInfo.h      | 199 ++++++++++++++-----
 llvm/include/llvm/ABI/ABIInfo.h              | 102 +---------
 llvm/include/llvm/ABI/Types.h                |  18 +-
 llvm/lib/ABI/ABIFunctionInfo.cpp             |  10 +-
 llvm/lib/ABI/CMakeLists.txt                  |  14 ++
 llvm/lib/ABI/Targets/BPF.cpp                 |  35 ++--
 llvm/lib/CMakeLists.txt                      |   2 +-
 9 files changed, 202 insertions(+), 217 deletions(-)
 create mode 100644 llvm/lib/ABI/CMakeLists.txt

diff --git a/clang/include/clang/CodeGen/QualTypeMapper.h b/clang/include/clang/CodeGen/QualTypeMapper.h
index 94fc74763a8ee..1c748bc633447 100644
--- a/clang/include/clang/CodeGen/QualTypeMapper.h
+++ b/clang/include/clang/CodeGen/QualTypeMapper.h
@@ -26,7 +26,7 @@
 #include "llvm/Support/Allocator.h"
 
 namespace clang {
-namespace mapper {
+namespace CodeGen {
 
 class QualTypeMapper {
 private:
@@ -68,7 +68,7 @@ class QualTypeMapper {
   llvm::abi::TypeBuilder getTypeBuilder() { return Builder; }
 };
 
-} // namespace mapper
+} // namespace CodeGen
 } // namespace clang
 
 #endif // !CLANG_CODEGEN_QUALTYPE_MAPPER_H
diff --git a/clang/lib/CodeGen/QualTypeMapper.cpp b/clang/lib/CodeGen/QualTypeMapper.cpp
index 420c25975a844..6d2d4618ac2b4 100644
--- a/clang/lib/CodeGen/QualTypeMapper.cpp
+++ b/clang/lib/CodeGen/QualTypeMapper.cpp
@@ -28,7 +28,7 @@
 #include "llvm/Support/raw_ostream.h"
 
 namespace clang {
-namespace mapper {
+namespace CodeGen {
 
 /// Main entry point for converting Clang QualType to LLVM ABI Type.
 /// This method performs type canonicalization, caching, and dispatches
@@ -164,7 +164,8 @@ QualTypeMapper::convertArrayType(const clang::ArrayType *AT) {
 /// \return LLVM ABI VectorType with element type, count, and alignment
 const llvm::abi::Type *QualTypeMapper::convertVectorType(const VectorType *VT) {
   const llvm::abi::Type *ElementType = convertType(VT->getElementType());
-  uint64_t NumElements = VT->getNumElements();
+  llvm::ElementCount NumElements =
+      llvm::ElementCount::getFixed(VT->getNumElements());
 
   llvm::Align VectorAlign = getTypeAlign(QualType(VT, 0));
 
@@ -285,39 +286,13 @@ QualTypeMapper::convertPointerType(const clang::PointerType *PT) {
 /// \return LLVM ABI IntegerType representing the enum's underlying type
 const llvm::abi::Type *
 QualTypeMapper::convertEnumType(const clang::EnumType *ET) {
-  if (!ET)
-    return Builder.getIntegerType(32, llvm::Align(4), true);
   const EnumDecl *ED = ET->getDecl();
-  if (!ED)
-    return Builder.getIntegerType(32, llvm::Align(4), true);
-  if (ED->isInvalidDecl())
-    return Builder.getIntegerType(32, llvm::Align(4), true);
-
-  if (!ED->isComplete()) {
-    if (ED->isFixed()) {
-      QualType UnderlyingType = ED->getIntegerType();
-      if (!UnderlyingType.isNull()) {
-        return convertType(UnderlyingType);
-      }
-    }
-    return Builder.getIntegerType(32, llvm::Align(4), true);
-  }
   QualType UnderlyingType = ED->getIntegerType();
 
-  if (UnderlyingType.isNull())
-    UnderlyingType = ED->getPromotionType();
-
   if (UnderlyingType.isNull())
     UnderlyingType = ASTCtx.IntTy;
 
-  if (const auto *BT = dyn_cast<BuiltinType>(UnderlyingType.getTypePtr()))
-    return convertBuiltinType(BT);
-
-  uint64_t TypeSize = ASTCtx.getTypeSize(UnderlyingType);
-  llvm::Align TypeAlign = getTypeAlign(UnderlyingType);
-  bool IsSigned = UnderlyingType->isSignedIntegerType();
-
-  return Builder.getIntegerType(TypeSize, TypeAlign, IsSigned);
+  return convertType(UnderlyingType);
 }
 
 /// Converts plain C structs and C++ classes without inheritance.
@@ -400,5 +375,5 @@ void QualTypeMapper::computeFieldInfo(
   }
 }
 
-} // namespace mapper
+} // namespace CodeGen
 } // namespace clang
diff --git a/llvm/include/llvm/ABI/ABIFunctionInfo.h b/llvm/include/llvm/ABI/ABIFunctionInfo.h
index b0a590373b586..e47015749389b 100644
--- a/llvm/include/llvm/ABI/ABIFunctionInfo.h
+++ b/llvm/include/llvm/ABI/ABIFunctionInfo.h
@@ -14,26 +14,141 @@
 #ifndef LLVM_ABI_ABIFUNCTIONINFO_H
 #define LLVM_ABI_ABIFUNCTIONINFO_H
 
-#include "ABIInfo.h"
+#include "llvm/ABI/Types.h"
 #include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/FoldingSet.h"
 #include "llvm/IR/CallingConv.h"
 #include "llvm/Support/TrailingObjects.h"
 
 namespace llvm {
 namespace abi {
 
-struct FunctionABIInfo {
-  llvm::CallingConv::ID CC = llvm::CallingConv::C;
-  llvm::CallingConv::ID EffectiveCC = llvm::CallingConv::C;
+/// ABIArgInfo - Helper class to encapsulate information about how a
+/// specific type should be passed to or returned from a function.
+class ABIArgInfo {
+public:
+  enum Kind {
+    Direct,
+    Extend,
+    Indirect,
+    Ignore,
+    Expand,
+    CoerceAndExpand,
+    InAlloca
+  };
+
+private:
+  Kind TheKind;
+  const Type *CoercionType;
+  bool InReg : 1;
+  bool PaddingInReg : 1;
+  bool SignExt : 1;
+  bool ZeroExt : 1;
+  unsigned IndirectAlign : 16;
+  bool IndirectByVal : 1;
+
+  ABIArgInfo(Kind K = Direct)
+      : TheKind(K), CoercionType(nullptr), InReg(false), PaddingInReg(false),
+        SignExt(false), ZeroExt(false), IndirectAlign(0), IndirectByVal(false) {
+  }
+
+public:
+  static ABIArgInfo getDirect(const Type *T = nullptr) {
+    ABIArgInfo AI(Direct);
+    AI.CoercionType = T;
+    return AI;
+  }
+
+  static ABIArgInfo getDirectInReg(const Type *T = nullptr) {
+    ABIArgInfo AI = getDirect(T);
+    AI.InReg = true;
+    return AI;
+  }
+
+  static ABIArgInfo getExtend(const Type *T = nullptr) {
+    ABIArgInfo AI(Extend);
+    AI.CoercionType = T;
+    return AI;
+  }
+
+  ABIArgInfo &setSignExt(bool SignExtend = true) {
+    this->SignExt = SignExtend;
+    if (SignExtend)
+      this->ZeroExt = false;
+    return *this;
+  }
+
+  ABIArgInfo &setZeroExt(bool ZeroExtend = true) {
+    this->ZeroExt = ZeroExtend;
+    if (ZeroExtend)
+      this->SignExt = false;
+    return *this;
+  }
+
+  static ABIArgInfo getIndirect(unsigned Align = 0, bool ByVal = true) {
+    ABIArgInfo AI(Indirect);
+    AI.IndirectAlign = Align;
+    AI.IndirectByVal = ByVal;
+    return AI;
+  }
+
+  static ABIArgInfo getIndirectInReg(unsigned Align = 0, bool ByVal = true) {
+    ABIArgInfo AI = getIndirect(Align, ByVal);
+    AI.InReg = true;
+    return AI;
+  }
+
+  static ABIArgInfo getIgnore() { return ABIArgInfo(Ignore); }
+  static ABIArgInfo getExpand() { return ABIArgInfo(Expand); }
+
+  static ABIArgInfo getCoerceAndExpand(const Type *CoercionType) {
+    ABIArgInfo AI(CoerceAndExpand);
+    AI.CoercionType = CoercionType;
+    return AI;
+  }
+
+  Kind getKind() const { return TheKind; }
+  bool isDirect() const { return TheKind == Direct; }
+  bool isIndirect() const { return TheKind == Indirect; }
+  bool isIgnore() const { return TheKind == Ignore; }
+  bool isExpand() const { return TheKind == Expand; }
+  bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; }
+  bool isInAlloca() const { return TheKind == InAlloca; }
+  bool isInReg() const { return InReg; }
+  bool hasPaddingInReg() const { return PaddingInReg; }
+
+  unsigned getIndirectAlign() const {
+    assert(isIndirect() && "Invalid Kind!");
+    return IndirectAlign;
+  }
+
+  bool getIndirectByVal() const {
+    assert(isIndirect() && "Invalid Kind!");
+    return IndirectByVal;
+  }
+
+  const Type *getCoerceToType() const {
+    assert((isDirect() || isCoerceAndExpand()) && "Invalid Kind!");
+    return CoercionType;
+  }
+
+  ABIArgInfo &setInReg(bool InReg = true) {
+    this->InReg = InReg;
+    return *this;
+  }
+
+  ABIArgInfo &setPaddingInReg(bool HasPadding = true) {
+    this->PaddingInReg = HasPadding;
+    return *this;
+  }
+};
+
+/// Function-level ABI attributes that affect argument/return passing
+struct ABICallAttributes {
+  CallingConv::ID CC = CallingConv::C;
+  CallingConv::ID EffectiveCC = CallingConv::C;
 
-  // Core ABI attributes
-  bool NoReturn = false;
-  bool NoUnwind = false;
   bool HasSRet = false;
-  bool IsVariadic = false;
   bool IsInstanceMethod = false;
-  // Are these ABI Relavent(?)
   bool IsChainCall = false;
   bool IsDelegateCall = false;
 
@@ -41,19 +156,20 @@ struct FunctionABIInfo {
   bool HasRegParm = false;
   unsigned RegParm = 0;
   bool NoCallerSavedRegs = false;
-  // Security/extensions(are they ABI related?)
+
+  // Security extensions
   bool NoCfCheck = false;
   bool CmseNSCall = false;
 
-  // Optimization hints
+  // Memory management
   bool ReturnsRetained = false;
   unsigned MaxVectorWidth = 0;
 
-  FunctionABIInfo() = default;
-  FunctionABIInfo(llvm::CallingConv::ID CC) : CC(CC), EffectiveCC(CC) {}
+  ABICallAttributes() = default;
+  ABICallAttributes(CallingConv::ID CC) : CC(CC), EffectiveCC(CC) {}
 };
 
-// Not an Immediate requirement for BPF
+/// Information about required vs optional arguments for variadic functions
 struct RequiredArgs {
 private:
   unsigned NumRequired;
@@ -72,6 +188,7 @@ struct RequiredArgs {
   }
 
   bool allowsOptionalArgs() const { return NumRequired != All; }
+  bool isVariadic() const { return allowsOptionalArgs(); }
 
   unsigned getNumRequiredArgs() const {
     return allowsOptionalArgs() ? NumRequired : 0;
@@ -82,8 +199,7 @@ struct RequiredArgs {
   }
 };
 
-// Implementation detail of ABIFunctionInfo, factored out so it can be named
-// in the TrailingObjects base class of ABIFunctionInfo.
+/// Argument information for ABIFunctionInfo
 struct ABIFunctionInfoArgInfo {
   const Type *ABIType;
   ABIArgInfo ArgInfo;
@@ -96,17 +212,15 @@ struct ABIFunctionInfoArgInfo {
 };
 
 class ABIFunctionInfo final
-    : public llvm::FoldingSetNode,
-      private TrailingObjects<ABIFunctionInfo, ABIFunctionInfoArgInfo> {
+    : private TrailingObjects<ABIFunctionInfo, ABIFunctionInfoArgInfo> {
   typedef ABIFunctionInfoArgInfo ArgInfo;
 
 private:
   const Type *ReturnType;
   ABIArgInfo ReturnInfo;
   unsigned NumArgs;
-  FunctionABIInfo ABIInfo;
-  RequiredArgs
-      Required; // For Variadic Functions but we can focus on this later
+  ABICallAttributes CallAttrs;
+  RequiredArgs Required;
 
   ABIFunctionInfo(const Type *RetTy, unsigned NumArguments)
       : ReturnType(RetTy), ReturnInfo(ABIArgInfo::getDirect()),
@@ -116,24 +230,25 @@ class ABIFunctionInfo final
 
 public:
   static ABIFunctionInfo *
-  create(llvm::CallingConv::ID CC, const Type *ReturnType,
-         llvm::ArrayRef<const Type *> ArgTypes,
-         const FunctionABIInfo &ABIInfo = FunctionABIInfo(),
+  create(CallingConv::ID CC, const Type *ReturnType,
+         ArrayRef<const Type *> ArgTypes,
+         const ABICallAttributes &CallAttrs = ABICallAttributes(),
          RequiredArgs Required = RequiredArgs());
 
   const Type *getReturnType() const { return ReturnType; }
   ABIArgInfo &getReturnInfo() { return ReturnInfo; }
   const ABIArgInfo &getReturnInfo() const { return ReturnInfo; }
 
-  llvm::CallingConv::ID getCallingConvention() const { return ABIInfo.CC; }
-
-  const FunctionABIInfo &getExtInfo() const { return ABIInfo; }
+  CallingConv::ID getCallingConvention() const { return CallAttrs.CC; }
+  const ABICallAttributes &getCallAttributes() const { return CallAttrs; }
   RequiredArgs getRequiredArgs() const { return Required; }
-  llvm::ArrayRef<ArgInfo> arguments() const {
+  bool isVariadic() const { return Required.isVariadic(); }
+
+  ArrayRef<ArgInfo> arguments() const {
     return {getTrailingObjects<ArgInfo>(), NumArgs};
   }
 
-  llvm::MutableArrayRef<ArgInfo> arguments() {
+  MutableArrayRef<ArgInfo> arguments() {
     return {getTrailingObjects<ArgInfo>(), NumArgs};
   }
 
@@ -146,27 +261,11 @@ class ABIFunctionInfo final
     assert(Index < NumArgs && "Invalid argument index");
     return arguments()[Index];
   }
-  void Profile(llvm::FoldingSetNodeID &ID) const {
-    ID.AddInteger(static_cast<unsigned>(ABIInfo.CC));
-    ID.AddPointer(ReturnType);
-    ID.AddInteger(static_cast<unsigned>(ReturnInfo.getKind()));
-    if (ReturnInfo.getCoerceToType())
-      ID.AddPointer(ReturnInfo.getCoerceToType());
-    ID.AddInteger(NumArgs);
-    for (const auto &ArgInfo : arguments()) {
-      ID.AddPointer(ArgInfo.ABIType);
-      ID.AddInteger(static_cast<unsigned>(ArgInfo.ArgInfo.getKind()));
-      if (ArgInfo.ArgInfo.getCoerceToType())
-        ID.AddPointer(ArgInfo.ArgInfo.getCoerceToType());
-    }
-    ID.AddInteger(Required.getNumRequiredArgs());
-    ID.AddBoolean(Required.allowsOptionalArgs());
-    ID.AddBoolean(ABIInfo.NoReturn);
-    ID.AddBoolean(ABIInfo.IsVariadic);
-    // TODO: Add more flags
-  }
+
+  unsigned getNumArgs() const { return NumArgs; }
 };
+
 } // namespace abi
 } // namespace llvm
 
-#endif // !LLVM_ABI_ABIFUNCTIONINFO_H
+#endif // LLVM_ABI_ABIFUNCTIONINFO_H
diff --git a/llvm/include/llvm/ABI/ABIInfo.h b/llvm/include/llvm/ABI/ABIInfo.h
index aa56dd5e96f2c..48d289331746c 100644
--- a/llvm/include/llvm/ABI/ABIInfo.h
+++ b/llvm/include/llvm/ABI/ABIInfo.h
@@ -14,107 +14,13 @@
 #ifndef LLVM_ABI_ABIINFO_H
 #define LLVM_ABI_ABIINFO_H
 
+#include "llvm/ABI/ABIFunctionInfo.h"
 #include "llvm/ABI/Types.h"
 #include <cassert>
 
 namespace llvm {
 namespace abi {
 
-/// ABIArgInfo - Helper class to encapsulate information about how a
-/// specific C type should be passed to or returned from a function.
-class ABIArgInfo {
-public:
-  enum Kind { Direct, Indirect, Ignore, Expand, CoerceAndExpand, InAlloca };
-
-private:
-  Kind TheKind;
-  const Type *CoercionType;
-
-  bool InReg : 1;
-  bool PaddingInReg : 1;
-
-  unsigned IndirectAlign : 16;
-  bool IndirectByVal : 1;
-
-  ABIArgInfo(Kind K = Direct)
-      : TheKind(K), CoercionType(nullptr), InReg(false), PaddingInReg(false),
-        IndirectAlign(0), IndirectByVal(false) {}
-
-public:
-  static ABIArgInfo getDirect(const Type *T = nullptr) {
-    ABIArgInfo AI(Direct);
-    AI.CoercionType = T;
-    return AI;
-  }
-
-  static ABIArgInfo getDirectInReg(const Type *T = nullptr) {
-    ABIArgInfo AI = getDirect(T);
-    AI.InReg = true;
-    return AI;
-  }
-
-  static ABIArgInfo getIndirect(unsigned Align = 0, bool ByVal = true) {
-    ABIArgInfo AI(Indirect);
-    AI.IndirectAlign = Align;
-    AI.IndirectByVal = ByVal;
-    return AI;
-  }
-
-  static ABIArgInfo getIndirectInReg(unsigned Align = 0, bool ByVal = true) {
-    ABIArgInfo AI = getIndirect(Align, ByVal);
-    AI.InReg = true;
-    return AI;
-  }
-
-  static ABIArgInfo getIgnore() { return ABIArgInfo(Ignore); }
-
-  static ABIArgInfo getExpand() { return ABIArgInfo(Expand); }
-
-  static ABIArgInfo getCoerceAndExpand(const Type *CoercionType) {
-    ABIArgInfo AI(CoerceAndExpand);
-    AI.CoercionType = CoercionType;
-    return AI;
-  }
-
-  Kind getKind() const { return TheKind; }
-
-  bool isDirect() const { return TheKind == Direct; }
-  bool isIndirect() const { return TheKind == Indirect; }
-  bool isIgnore() const { return TheKind == Ignore; }
-  bool isExpand() const { return TheKind == Expand; }
-  bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; }
-  bool isInAlloca() const { return TheKind == InAlloca; }
-
-  bool isInReg() const { return InReg; }
-  bool hasPaddingInReg() const { return PaddingInReg; }
-
-  unsigned getIndirectAlign() const {
-    assert(isIndirect() && "Only indirect arguments have alignment");
-    return IndirectAlign;
-  }
-
-  bool getIndirectByVal() const {
-    assert(isIndirect() && "Only indirect arguments can be ByVal");
-    return IndirectByVal;
-  }
-
-  const Type *getCoerceToType() const {
-    assert((isDirect() || isCoerceAndExpand()) &&
-           "Only Direct and CoerceAndExpand arguments can have coercion types");
-    return CoercionType;
-  }
-
-  ABIArgInfo &setInReg(bool InReg = true) {
-    this->InReg = InReg;
-    return *this;
-  }
-
-  ABIArgInfo &setPaddingInReg(bool HasPadding = true) {
-    this->PaddingInReg = HasPadding;
-    return *this;
-  }
-};
-
 /// Abstract base class for target-specific ABI information.
 class ABIInfo {
 public:
@@ -122,12 +28,8 @@ class ABIInfo {
 
   virtual ABIArgInfo classifyReturnType(const Type *RetTy) const = 0;
   virtual ABIArgInfo classifyArgumentType(const Type *ArgTy) const = 0;
-
+  void computeInfo(ABIFunctionInfo &FI) const;
   virtual bool isPassByRef(const Type *Ty) const { return false; }
-
-  virtual unsigned getTypeAlignment(const Type *Ty) const = 0;
-
-  virtual unsigned getTypeSize(const Type *Ty) const = 0;
 };
 
 } // namespace abi
diff --git a/llvm/include/llvm/ABI/Types.h b/llvm/include/llvm/ABI/Types.h
index e4642142662d3..9395e377522bc 100644
--- a/llvm/include/llvm/ABI/Types.h
+++ b/llvm/include/llvm/ABI/Types.h
@@ -139,15 +139,11 @@ class VectorType : public Type {
 
 public:
   VectorType(const Type *ElemType, ElementCount NumElems, Align Align)
-      : Type(
-            TypeKind::Vector,
-            NumElems.isScalable()
-                ? TypeSize(ElemType->getSizeInBits().getFixedValue() *
-                               NumElems.getKnownMinValue(),
-                           true)
-                : TypeSize::getFixed(ElemType->getSizeInBits().getFixedValue() *
-                                     NumElems.getFixedValue()),
-            Align),
+      : Type(TypeKind::Vector,
+             TypeSize(ElemType->getSizeInBits().getFixedValue() *
+                          NumElems.getKnownMinValue(),
+                      NumElems.isScalable()),
+             Align),
         ElementType(ElemType), NumElements(NumElems) {}
 
   const Type *getElementType() const { return ElementType; }
@@ -243,8 +239,8 @@ class TypeBuilder {
         ArrayType(ElementType, NumElements);
   }
 
-  const VectorType *getVectorType(const Type *ElementType, uint64_t NumElements,
-                                  Align Align) {
+  const VectorType *getVectorType(const Type *ElementType,
+                                  ElementCount NumElements, Align Align) {
     return new (Allocator.Allocate<VectorType>())
         VectorType(ElementType, NumElements, Align);
   }
diff --git a/llvm/lib/ABI/ABIFunctionInfo.cpp b/llvm/lib/ABI/ABIFunctionInfo.cpp
index f0a75fa7f8151..eed444e9837b3 100644
--- a/llvm/lib/ABI/ABIFunctionInfo.cpp
+++ b/llvm/lib/ABI/ABIFunctionInfo.cpp
@@ -11,10 +11,10 @@
 using namespace llvm;
 using namespace llvm::abi;
 
-ABIFunctionInfo *ABIFunctionInfo::create(llvm::CallingConv::ID CC,
+ABIFunctionInfo *ABIFunctionInfo::create(CallingConv::ID CC,
                                          const Type *ReturnType,
-                                         llvm::ArrayRef<const Type *> ArgTypes,
-                                         const FunctionABIInfo &ABIInfo,
+                                         ArrayRef<const Type *> ArgTypes,
+                                         const ABICallAttributes &CallAttrs,
                                          RequiredArgs Required) {
 
   assert(!Required.allowsOptionalArgs() ||
@@ -26,8 +26,8 @@ ABIFunctionInfo *ABIFunctionInfo::create(llvm::CallingConv::ID CC,
   ABIFunctionInfo *FI =
       new (Buffer) ABIFunctionInfo(ReturnType, ArgTypes.size());
 
-  FI->ABIInfo = ABIInfo;
-  FI->ABIInfo.CC = CC;
+  FI->CallAttrs = CallAttrs;
+  FI->CallAttrs.CC = CC;
   FI->Required = Required;
 
   auto Args = FI->arguments();
diff --git a/llvm/lib/ABI/CMakeLists.txt b/llvm/lib/ABI/CMakeLists.txt
new file mode 100644
index 0000000000000..f4b74f551c720
--- /dev/null
+++ b/llvm/lib/ABI/CMakeLists.txt
@@ -0,0 +1,14 @@
+add_llvm_component_library(LLVMABI
+  ABIFunctionInfo.cpp
+  Targets/BPF.cpp
+
+  ADDITIONAL_HEADER_DIRS
+  ${LLVM_MAIN_INCLUDE_DIR}/llvm/ABI
+
+  DEPENDS
+  intrinsics_gen
+
+  LINK_COMPONENTS
+  Core
+  Support
+)
diff --git a/llvm/lib/ABI/Targets/BPF.cpp b/llvm/lib/ABI/Targets/BPF.cpp
index 52aff3ca368bd..ae2752eb0c50d 100644
--- a/llvm/lib/ABI/Targets/BPF.cpp
+++ b/llvm/lib/ABI/Targets/BPF.cpp
@@ -1,4 +1,4 @@
-//===- BPF.cpp ------------------------------------------------------------===//
+//===- BPF.cpp - BPF ABI Implementation ----------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,6 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "llvm/ABI/ABIFunctionInfo.h"
 #include "llvm/ABI/ABIInfo.h"
 #include "llvm/ABI/Types.h"
 #include "llvm/Support/Alignment.h"
@@ -18,18 +19,7 @@ class BPFABIInfo : public ABIInfo {
   TypeBuilder &TB;
 
   bool isAggregateType(const Type *Ty) const {
-    return Ty->isStruct() || Ty->isUnion() || Ty->isArray() ||
-           (Ty->isVector() && !isSimpleVector(dyn_cast<VectorType>(Ty)));
-  }
-
-  bool isSimpleVector(const VectorType *VecTy) const {
-    const Type *ElemTy = VecTy->getElementType();
-
-    if (!ElemTy->isInteger() && !ElemTy->isFloat())
-      return false;
-
-    auto VecSizeInBits = VecTy->getSizeInBits().getFixedValue();
-    return VecSizeInBits <= 128;
+    return Ty->isStruct() || Ty->isUnion() || Ty->isArray();
   }
 
   bool isPromotableIntegerType(const IntegerType *IntTy) const {
@@ -46,10 +36,8 @@ class BPFABIInfo : public ABIInfo {
 
     if (isAggregateType(RetTy)) {
       auto SizeInBits = RetTy->getSizeInBits().getFixedValue();
-
       if (SizeInBits == 0)
         return ABIArgInfo::getIgnore();
-
       return ABIArgInfo::getIndirect(RetTy->getAlignment().value());
     }
 
@@ -65,7 +53,6 @@ class BPFABIInfo : public ABIInfo {
   ABIArgInfo classifyArgumentType(const Type *ArgTy) const override {
     if (isAggregateType(ArgTy)) {
       auto SizeInBits = ArgTy->getSizeInBits().getFixedValue();
-
       if (SizeInBits == 0)
         return ABIArgInfo::getIgnore();
 
@@ -80,6 +67,7 @@ class BPFABIInfo : public ABIInfo {
         }
         return ABIArgInfo::getDirect(CoerceTy);
       }
+
       return ABIArgInfo::getIndirect(ArgTy->getAlignment().value());
     }
 
@@ -87,16 +75,27 @@ class BPFABIInfo : public ABIInfo {
       auto BitWidth = IntTy->getSizeInBits().getFixedValue();
       if (BitWidth > 128)
         return ABIArgInfo::getIndirect(ArgTy->getAlignment().value());
+
       if (isPromotableIntegerType(IntTy)) {
         const Type *PromotedTy =
             TB.getIntegerType(32, Align(4), IntTy->isSigned());
-        return ABIArgInfo::getDirect(
-            PromotedTy); // change to getExtend when implemented
+        auto AI = ABIArgInfo::getExtend(PromotedTy);
+
+        IntTy->isSigned() ? AI.setSignExt() : AI.setZeroExt();
+
+        return AI;
       }
     }
 
     return ABIArgInfo::getDirect();
   }
+
+  void computeInfo(ABIFunctionInfo &FI) {
+    FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+    for (auto &I : FI.arguments()) {
+      I.ArgInfo = classifyArgumentType(I.ABIType);
+    }
+  }
 };
 
 } // namespace llvm::abi
diff --git a/llvm/lib/CMakeLists.txt b/llvm/lib/CMakeLists.txt
index c84690abda028..b888f6637a925 100644
--- a/llvm/lib/CMakeLists.txt
+++ b/llvm/lib/CMakeLists.txt
@@ -3,7 +3,7 @@ include(LLVM-Build)
 # `Demangle', `Support' and `TableGen' libraries are added on the top-level
 # CMakeLists.txt
 
-# add_subdirectory(ABI)
+add_subdirectory(ABI)
 add_subdirectory(IR)
 add_subdirectory(FuzzMutate)
 add_subdirectory(FileCheck)

>From 268c47017b5ea80fa533719c93d0d7b905dd83d0 Mon Sep 17 00:00:00 2001
From: Narayan Sreekumar <nsreekumar6 at gmail.com>
Date: Sat, 21 Jun 2025 19:07:52 +0530
Subject: [PATCH 12/12] [LLVMABI] clang integration

---
 clang/lib/CodeGen/CGCall.cpp              | 134 +++++++++++-
 clang/lib/CodeGen/CMakeLists.txt          |   1 +
 clang/lib/CodeGen/CodeGenModule.cpp       |  13 ++
 clang/lib/CodeGen/QualTypeMapper.cpp      |   3 +-
 llvm/include/llvm/ABI/ABIFunctionInfo.h   |   2 +
 llvm/include/llvm/ABI/ABIInfo.h           |   2 +-
 llvm/include/llvm/ABI/ABITypeMapper.h     |  67 ++++++
 llvm/include/llvm/ABI/TargetCodegenInfo.h |  62 ++++++
 llvm/include/llvm/ABI/Types.h             |   1 +
 llvm/lib/ABI/ABITypeMapper.cpp            | 239 ++++++++++++++++++++++
 llvm/lib/ABI/CMakeLists.txt               |   2 +
 llvm/lib/ABI/TargetCodeGenInfo.cpp        |  24 +++
 llvm/lib/ABI/Targets/BPF.cpp              |  14 +-
 13 files changed, 554 insertions(+), 10 deletions(-)
 create mode 100644 llvm/include/llvm/ABI/ABITypeMapper.h
 create mode 100644 llvm/include/llvm/ABI/TargetCodegenInfo.h
 create mode 100644 llvm/lib/ABI/ABITypeMapper.cpp
 create mode 100644 llvm/lib/ABI/TargetCodeGenInfo.cpp

diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index aa1909443e8cd..ad52dd23a5495 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -22,6 +22,7 @@
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
 #include "TargetInfo.h"
+#include "clang/CodeGen/QualTypeMapper.h"
 #include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
@@ -30,6 +31,9 @@
 #include "clang/Basic/TargetInfo.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
 #include "clang/CodeGen/SwiftCallingConv.h"
+#include "llvm/ABI/ABIFunctionInfo.h"
+#include "llvm/ABI/ABITypeMapper.h"
+#include "llvm/ABI/Types.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Analysis/ValueTracking.h"
 #include "llvm/IR/Assumptions.h"
@@ -41,6 +45,8 @@
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Type.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/TargetParser/Triple.h"
 #include "llvm/Transforms/Utils/Local.h"
 #include <optional>
 using namespace clang;
@@ -826,6 +832,8 @@ void computeSPIRKernelABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI);
 }
 } // namespace clang
 
+
+
 /// Arrange the argument and result information for an abstract value
 /// of a given function type.  This is the method which all of the
 /// above functions ultimately defer to.
@@ -850,6 +858,7 @@ const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo(
 
   void *insertPos = nullptr;
   CGFunctionInfo *FI = FunctionInfos.FindNodeOrInsertPos(ID, insertPos);
+  llvm::abi::ABIFunctionInfo *tempFI;
   if (FI)
     return *FI;
 
@@ -858,12 +867,27 @@ const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo(
   // Construct the function info.  We co-allocate the ArgInfos.
   FI = CGFunctionInfo::create(CC, isInstanceMethod, isChainCall, isDelegateCall,
                               info, paramInfos, resultType, argTypes, required);
+
+  llvm::BumpPtrAllocator Alloc;
+  llvm::abi::TypeBuilder TB(Alloc);
+
+  QualTypeMapper Mapper(CGM.getContext(), Alloc);
+
+  SmallVector<const llvm::abi::Type *, 8> MappedArgTypes;
+for (CanQualType ArgType : argTypes) {
+  MappedArgTypes.push_back(Mapper.convertType(ArgType));
+}
+ArrayRef<const llvm::abi::Type *> ABIArgTypes = MappedArgTypes;
+  tempFI = llvm::abi::ABIFunctionInfo::create(CC, Mapper.convertType(resultType), ABIArgTypes);
   FunctionInfos.InsertNode(FI, insertPos);
 
   bool inserted = FunctionsBeingProcessed.insert(FI).second;
   (void)inserted;
   assert(inserted && "Recursively being processed?");
 
+bool isBPF = CGM.getTriple().getArch() == llvm::Triple::bpfeb || 
+             CGM.getTriple().getArch() == llvm::Triple::bpfel;
+
   // Compute ABI information.
   if (CC == llvm::CallingConv::SPIR_KERNEL) {
     // Force target independent argument handling for the host visible
@@ -872,20 +896,116 @@ const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo(
   } else if (info.getCC() == CC_Swift || info.getCC() == CC_SwiftAsync) {
     swiftcall::computeABIInfo(CGM, *FI);
   } else {
+	if (isBPF) CGM.fetchABIInfo(TB).computeInfo(*tempFI);
+	else
     CGM.getABIInfo().computeInfo(*FI);
   }
 
   // Loop over all of the computed argument and return value info.  If any of
   // them are direct or extend without a specified coerce type, specify the
   // default now.
-  ABIArgInfo &retInfo = FI->getReturnInfo();
-  if (retInfo.canHaveCoerceToType() && retInfo.getCoerceToType() == nullptr)
-    retInfo.setCoerceToType(ConvertType(FI->getReturnType()));
-
-  for (auto &I : FI->arguments())
-    if (I.info.canHaveCoerceToType() && I.info.getCoerceToType() == nullptr)
-      I.info.setCoerceToType(ConvertType(I.type));
+  if (isBPF && tempFI) {
+    llvm::ABITypeMapper ReverseMapper(getLLVMContext());
+    
+    const auto &abiRetInfo = tempFI->getReturnInfo();
+    ABIArgInfo &cgRetInfo = FI->getReturnInfo();
+    
+    if (abiRetInfo.isDirect()) {
+      llvm::Type *CoercedType = nullptr;
+      if (abiRetInfo.getCoerceToType()) {
+        CoercedType = ReverseMapper.convertType(abiRetInfo.getCoerceToType());
+      }
+      if (!CoercedType) {
+        CoercedType = ConvertType(FI->getReturnType());
+      }
+      cgRetInfo = ABIArgInfo::getDirect(CoercedType);
+      if (abiRetInfo.isInReg()) {
+        cgRetInfo.setInReg(true);
+      }
+    } else if (abiRetInfo.isExtend()) {
+      llvm::Type *CoercedType = nullptr;
+      if (abiRetInfo.getCoerceToType()) {
+        CoercedType = ReverseMapper.convertType(abiRetInfo.getCoerceToType());
+      }
+      if (!CoercedType) {
+        CoercedType = ConvertType(FI->getReturnType());
+      }
+      
+      if (abiRetInfo.isSignExt()) {
+        cgRetInfo = ABIArgInfo::getSignExtend(FI->getReturnType(), CoercedType);
+      } else {
+        cgRetInfo = ABIArgInfo::getZeroExtend(FI->getReturnType(), CoercedType);
+      }
+      if (abiRetInfo.isInReg()) {
+        cgRetInfo.setInReg(true);
+      }
+    } else if (abiRetInfo.isIndirect()) {
+      cgRetInfo = ABIArgInfo::getIndirect(CharUnits::fromQuantity(abiRetInfo.getIndirectAlign()),0);
+      if (abiRetInfo.isInReg()) {
+        cgRetInfo.setInReg(true);
+      }
+    } else if (abiRetInfo.isIgnore()) {
+      cgRetInfo = ABIArgInfo::getIgnore();
+    }
+    
+    unsigned numArgs = std::min(FI->arg_size(), tempFI->getNumArgs());
+    unsigned argIndex = 0;
+    
+    for (auto &cgArg : FI->arguments()) {
+      if (argIndex >= numArgs) break;
+      
+      const auto &abiArgInfo = tempFI->getArgInfo(argIndex);
+      ABIArgInfo &cgArgInfo = cgArg.info;
+      
+      if (abiArgInfo.ArgInfo.isDirect()) {
+        llvm::Type *CoercedType = nullptr;
+        if (abiArgInfo.ArgInfo.getCoerceToType()) {
+          CoercedType = ReverseMapper.convertType(abiArgInfo.ArgInfo.getCoerceToType());
+        }
+        if (!CoercedType) {
+          CoercedType = ConvertType(cgArg.type);
+        }
+        
+        cgArgInfo = ABIArgInfo::getDirect(CoercedType);
+      } else if (abiArgInfo.ArgInfo.isExtend()) {
+        llvm::Type *CoercedType = nullptr;
+        if (abiArgInfo.ArgInfo.getCoerceToType()) {
+          CoercedType = ReverseMapper.convertType(abiArgInfo.ArgInfo.getCoerceToType());
+        }
+        if (!CoercedType) {
+          CoercedType = ConvertType(cgArg.type);
+        }
+        
+        if (abiArgInfo.ArgInfo.isSignExt()) {
+          cgArgInfo = ABIArgInfo::getSignExtend(cgArg.type, CoercedType);
+        } else {
+          cgArgInfo = ABIArgInfo::getZeroExtend(cgArg.type, CoercedType);
+        }
+      } else if (abiArgInfo.ArgInfo.isIndirect()) {
+        cgArgInfo = ABIArgInfo::getIndirect(CharUnits::fromQuantity(abiArgInfo.ArgInfo.getIndirectAlign()),0);
+      } else if (abiArgInfo.ArgInfo.isIgnore()) {
+        cgArgInfo = ABIArgInfo::getIgnore();
+      }
+      
+      if (abiArgInfo.ArgInfo.isInReg()) {
+        cgArgInfo.setInReg(true);
+      }
+      
+      argIndex++;
+    }
+  } else {
+    // Non-BPF path: handle coerce types for direct/extend cases
+    ABIArgInfo &retInfo = FI->getReturnInfo();
+    if (retInfo.canHaveCoerceToType() && retInfo.getCoerceToType() == nullptr) {
+      retInfo.setCoerceToType(ConvertType(FI->getReturnType()));
+    }
 
+    for (auto &I : FI->arguments()) {
+      if (I.info.canHaveCoerceToType() && I.info.getCoerceToType() == nullptr) {
+        I.info.setCoerceToType(ConvertType(I.type));
+      }
+    }
+  }
   bool erased = FunctionsBeingProcessed.erase(FI);
   (void)erased;
   assert(erased && "Not in set?");
diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt
index f805819de300f..8f771b4d6d728 100644
--- a/clang/lib/CodeGen/CMakeLists.txt
+++ b/clang/lib/CodeGen/CMakeLists.txt
@@ -167,6 +167,7 @@ add_clang_library(clangCodeGen
 
   LINK_LIBS
   clangAST
+  LLVMABI
   clangAnalysis
   clangBasic
   clangFrontend
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 428a4b8335524..23d4e9b09dc91 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -47,6 +47,7 @@
 #include "clang/CodeGen/BackendUtil.h"
 #include "clang/CodeGen/ConstantInitBuilder.h"
 #include "clang/Frontend/FrontendDiagnostic.h"
+#include "llvm/ABI/TargetCodegenInfo.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -72,6 +73,7 @@
 #include "llvm/TargetParser/Triple.h"
 #include "llvm/TargetParser/X86TargetParser.h"
 #include "llvm/Transforms/Utils/BuildLibCalls.h"
+#include <memory>
 #include <optional>
 #include <set>
 
@@ -104,6 +106,17 @@ static CGCXXABI *createCXXABI(CodeGenModule &CGM) {
   llvm_unreachable("invalid C++ ABI kind");
 }
 
+static std::unique_ptr<llvm::abi::TargetCodeGenInfo>
+makeTargetCodeGenInfo(llvm::abi::TypeBuilder TB) {
+	return llvm::abi::createBPFTargetCodeGenInfo(TB);
+}
+
+const llvm::abi::ABIInfo &CodeGenModule::fetchABIInfo(llvm::abi::TypeBuilder TB) {
+	newTargetCodeGenInfo = makeTargetCodeGenInfo(TB);
+  return newTargetCodeGenInfo->getABIInfo();
+}
+
+
 static std::unique_ptr<TargetCodeGenInfo>
 createTargetCodeGenInfo(CodeGenModule &CGM) {
   const TargetInfo &Target = CGM.getTarget();
diff --git a/clang/lib/CodeGen/QualTypeMapper.cpp b/clang/lib/CodeGen/QualTypeMapper.cpp
index 6d2d4618ac2b4..d4acf404bd4f2 100644
--- a/clang/lib/CodeGen/QualTypeMapper.cpp
+++ b/clang/lib/CodeGen/QualTypeMapper.cpp
@@ -76,7 +76,8 @@ const llvm::abi::Type *QualTypeMapper::convertType(QualType QT) {
         llvm::Align(ASTCtx.getTargetInfo().getPointerAlign(LangAS::Default));
     return Builder.getPointerType(PointerSize, PointerAlign);
   } else {
-    llvm_unreachable("Unsupported type for ABI lowering");
+	QT.dump();
+    llvm::errs() << "[UNHANDLED TYPE]\n";
   }
   TypeCache[QT] = Result;
   return Result;
diff --git a/llvm/include/llvm/ABI/ABIFunctionInfo.h b/llvm/include/llvm/ABI/ABIFunctionInfo.h
index e47015749389b..84871da77687e 100644
--- a/llvm/include/llvm/ABI/ABIFunctionInfo.h
+++ b/llvm/include/llvm/ABI/ABIFunctionInfo.h
@@ -110,10 +110,12 @@ class ABIArgInfo {
   bool isDirect() const { return TheKind == Direct; }
   bool isIndirect() const { return TheKind == Indirect; }
   bool isIgnore() const { return TheKind == Ignore; }
+  bool isExtend() const {return TheKind == Extend;}
   bool isExpand() const { return TheKind == Expand; }
   bool isCoerceAndExpand() const { return TheKind == CoerceAndExpand; }
   bool isInAlloca() const { return TheKind == InAlloca; }
   bool isInReg() const { return InReg; }
+  bool isSignExt() const {return SignExt;}
   bool hasPaddingInReg() const { return PaddingInReg; }
 
   unsigned getIndirectAlign() const {
diff --git a/llvm/include/llvm/ABI/ABIInfo.h b/llvm/include/llvm/ABI/ABIInfo.h
index 48d289331746c..54c6ed70a50e9 100644
--- a/llvm/include/llvm/ABI/ABIInfo.h
+++ b/llvm/include/llvm/ABI/ABIInfo.h
@@ -28,7 +28,7 @@ class ABIInfo {
 
   virtual ABIArgInfo classifyReturnType(const Type *RetTy) const = 0;
   virtual ABIArgInfo classifyArgumentType(const Type *ArgTy) const = 0;
-  void computeInfo(ABIFunctionInfo &FI) const;
+  virtual void computeInfo(ABIFunctionInfo &FI) const;
   virtual bool isPassByRef(const Type *Ty) const { return false; }
 };
 
diff --git a/llvm/include/llvm/ABI/ABITypeMapper.h b/llvm/include/llvm/ABI/ABITypeMapper.h
new file mode 100644
index 0000000000000..b6cd20d4aa843
--- /dev/null
+++ b/llvm/include/llvm/ABI/ABITypeMapper.h
@@ -0,0 +1,67 @@
+//===---- ABITypeMapper.h - Maps LLVM ABI Types to LLVM IR Types --------===//
+//
+// 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
+/// Maps LLVM ABI type representations back to corresponding LLVM IR types.
+/// This reverse mapper translates low-level ABI-specific types back into
+/// LLVM IR types suitable for code generation and optimization passes.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_ABITYPEMAPPER_H
+#define LLVM_CODEGEN_ABITYPEMAPPER_H
+
+#include "llvm/ABI/Types.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Type.h"
+#include "llvm/Support/TypeSize.h"
+
+namespace llvm {
+
+class ABITypeMapper {
+public:
+  explicit ABITypeMapper(LLVMContext &Ctx) : Context(Ctx) {}
+
+  Type *convertType(const abi::Type *ABIType);
+
+  void clearCache() { TypeCache.clear(); }
+
+private:
+  LLVMContext &Context;
+  
+  DenseMap<const abi::Type *, Type *> TypeCache;
+
+  Type *convertIntegerType(const abi::IntegerType *IT);
+
+  Type *convertFloatType(const abi::FloatType *FT);
+
+  Type *convertPointerType(const abi::PointerType *PT);
+
+  Type *convertArrayType(const abi::ArrayType *AT);
+
+  Type *convertVectorType(const abi::VectorType *VT);
+
+  Type *convertStructType(const abi::StructType *ST);
+
+  Type *convertUnionType(const abi::UnionType *UT);
+
+  Type *convertVoidType(const abi::VoidType *VT);
+
+  Type *getFloatTypeForSemantics(const fltSemantics &Semantics);
+
+  StructType *createStructFromFields(ArrayRef<abi::FieldInfo> Fields, uint32_t NumFields,
+                                     TypeSize Size, Align Alignment,
+                                     bool IsUnion = false);
+};
+
+} // namespace llvm
+
+#endif // LLVM_CODEGEN_ABITYPEMAPPER_H
diff --git a/llvm/include/llvm/ABI/TargetCodegenInfo.h b/llvm/include/llvm/ABI/TargetCodegenInfo.h
new file mode 100644
index 0000000000000..23c7c4b2d5825
--- /dev/null
+++ b/llvm/include/llvm/ABI/TargetCodegenInfo.h
@@ -0,0 +1,62 @@
+#include "llvm/ABI/ABIInfo.h"
+#include <memory>
+
+#ifndef LLVM_ABI_TARGETCODEGENINFO_H
+#define LLVM_ABI_TARGETCODEGENINFO_H
+
+namespace llvm::abi {
+
+class TargetCodeGenInfo {
+	std::unique_ptr<llvm::abi::ABIInfo> Info;
+
+	protected:
+
+		template<typename T> const T getABIInfo() const {
+			return static_cast<const T&>(*Info);
+		}
+
+	public:
+		TargetCodeGenInfo(std::unique_ptr<llvm::abi::ABIInfo> Info);
+		virtual ~TargetCodeGenInfo();
+
+		const ABIInfo &getABIInfo() const {return *Info;}
+
+		virtual void computeInfo(ABIFunctionInfo &FI) const;
+	
+};
+
+std::unique_ptr<TargetCodeGenInfo>
+createDefaultTargetCodeGenInfo(TypeBuilder &TB);
+
+std::unique_ptr<TargetCodeGenInfo>
+createBPFTargetCodeGenInfo(TypeBuilder &TB);
+
+std::unique_ptr<TargetCodeGenInfo>
+createX8664TargetCodeGenInfo(TypeBuilder &TB);
+
+std::unique_ptr<TargetCodeGenInfo>
+createAArch64TargetCodeGenInfo(TypeBuilder &TB);
+
+std::unique_ptr<TargetCodeGenInfo>
+createARMTargetCodeGenInfo(TypeBuilder &TB);
+
+std::unique_ptr<TargetCodeGenInfo>
+createRISCVTargetCodeGenInfo(TypeBuilder &TB);
+
+std::unique_ptr<TargetCodeGenInfo>
+createPPC64TargetCodeGenInfo(TypeBuilder &TB);
+
+std::unique_ptr<TargetCodeGenInfo>
+createSystemZTargetCodeGenInfo(TypeBuilder &TB);
+
+std::unique_ptr<TargetCodeGenInfo>
+createWebAssemblyTargetCodeGenInfo(TypeBuilder &TB);
+
+std::unique_ptr<TargetCodeGenInfo>
+createNVPTXTargetCodeGenInfo(TypeBuilder &TB);
+
+std::unique_ptr<TargetCodeGenInfo>
+createAMDGPUTargetCodeGenInfo(TypeBuilder &TB);
+} // namespace llvm::abi
+
+#endif
diff --git a/llvm/include/llvm/ABI/Types.h b/llvm/include/llvm/ABI/Types.h
index 9395e377522bc..fdbf9380c6bc2 100644
--- a/llvm/include/llvm/ABI/Types.h
+++ b/llvm/include/llvm/ABI/Types.h
@@ -102,6 +102,7 @@ class FloatType : public Type {
              TypeSize::getFixed(APFloat::getSizeInBits(FloatSemantics)), Align),
         Semantics(&FloatSemantics) {}
 
+  const fltSemantics *getSemantics() {return Semantics;}
   static bool classof(const Type *T) { return T->getKind() == TypeKind::Float; }
 };
 
diff --git a/llvm/lib/ABI/ABITypeMapper.cpp b/llvm/lib/ABI/ABITypeMapper.cpp
new file mode 100644
index 0000000000000..84b2bee223f9b
--- /dev/null
+++ b/llvm/lib/ABI/ABITypeMapper.cpp
@@ -0,0 +1,239 @@
+//===---- ABITypeMapper.cpp - Maps LLVM ABI Types to LLVM IR Types ------===//
+//
+// 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
+/// Maps LLVM ABI type representations back to corresponding LLVM IR types.
+/// This reverse mapper translates low-level ABI-specific types back into
+/// LLVM IR types suitable for code generation and optimization passes.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ABI/ABITypeMapper.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Type.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/ABI/Types.h"
+
+using namespace llvm;
+
+Type *ABITypeMapper::convertType(const abi::Type *ABIType) {
+  if (!ABIType)
+    return nullptr;
+
+  auto It = TypeCache.find(ABIType);
+  if (It != TypeCache.end())
+    return It->second;
+
+  Type *Result = nullptr;
+
+  switch (ABIType->getKind()) {
+	  case abi::TypeKind::Integer:
+    Result = convertIntegerType(cast<abi::IntegerType>(ABIType));
+    break;
+	  case abi::TypeKind::Float:
+    Result = convertFloatType(cast<abi::FloatType>(ABIType));
+    break;
+	  case abi::TypeKind::Pointer:
+    Result = convertPointerType(cast<abi::PointerType>(ABIType));
+    break;
+	  case abi::TypeKind::Array:
+    Result = convertArrayType(cast<abi::ArrayType>(ABIType));
+    break;
+	  case abi::TypeKind::Vector:
+    Result = convertVectorType(cast<abi::VectorType>(ABIType));
+    break;
+	  case abi::TypeKind::Struct:
+    Result = convertStructType(cast<abi::StructType>(ABIType));
+    break;
+	  case abi::TypeKind::Union:
+    Result = convertUnionType(cast<abi::UnionType>(ABIType));
+    break;
+	  case abi::TypeKind::Void:
+    Result = convertVoidType(cast<abi::VoidType>(ABIType));
+    break;
+  default:
+    llvm_unreachable("Unknown ABI type kind");
+  }
+
+  if (Result)
+    TypeCache[ABIType] = Result;
+  
+  return Result;
+}
+
+Type *ABITypeMapper::convertIntegerType(const abi::IntegerType *IT) {
+  unsigned BitWidth = IT->getSizeInBits();
+  return IntegerType::get(Context, BitWidth);
+}
+
+Type *ABITypeMapper::convertFloatType(const abi::FloatType *FT) {
+  const fltSemantics *Semantics = const_cast<abi::FloatType*>(FT)->getSemantics();
+  return getFloatTypeForSemantics(*Semantics);
+}
+
+Type *ABITypeMapper::convertPointerType(const abi::PointerType *PT) {
+  return PointerType::get(Context, 0);
+}
+
+Type *ABITypeMapper::convertArrayType(const abi::ArrayType *AT) {
+  Type *ElementType = convertType(AT->getElementType());
+  if (!ElementType)
+    return nullptr;
+
+  uint64_t NumElements = AT->getNumElements();
+  
+  return ArrayType::get(ElementType, NumElements);
+}
+
+Type *ABITypeMapper::convertVectorType(const abi::VectorType *VT) {
+  Type *ElementType = convertType(VT->getElementType());
+  if (!ElementType)
+    return nullptr;
+
+  ElementCount EC = VT->getNumElements();
+  
+  if (EC.isScalable())
+    return ScalableVectorType::get(ElementType, EC.getKnownMinValue());
+      return FixedVectorType::get(ElementType, EC.getFixedValue());
+}
+
+Type *ABITypeMapper::convertStructType(const abi::StructType *ST) {
+  return createStructFromFields(*ST->getFields(), ST->getNumFields(), ST->getSizeInBits(),
+                                ST->getAlignment(), false);
+}
+
+Type *ABITypeMapper::convertUnionType(const abi::UnionType *UT) {
+  return createStructFromFields(*UT->getFields(), UT->getNumFields(), UT->getSizeInBits(),
+                                UT->getAlignment(), true);
+}
+
+Type *ABITypeMapper::convertVoidType(const abi::VoidType *VT) {
+  return Type::getVoidTy(Context);
+}
+
+Type *ABITypeMapper::getFloatTypeForSemantics(const fltSemantics &Semantics) {
+  if (&Semantics == &APFloat::IEEEhalf())
+    return Type::getHalfTy(Context);
+  if (&Semantics == &APFloat::BFloat())
+    return Type::getBFloatTy(Context);
+  if (&Semantics == &APFloat::IEEEsingle())
+    return Type::getFloatTy(Context);
+  if (&Semantics == &APFloat::IEEEdouble())
+    return Type::getDoubleTy(Context);
+  if (&Semantics == &APFloat::x87DoubleExtended())
+    return Type::getX86_FP80Ty(Context);
+  if (&Semantics == &APFloat::IEEEquad())
+    return Type::getFP128Ty(Context);
+  if (&Semantics == &APFloat::PPCDoubleDouble())
+    return Type::getPPC_FP128Ty(Context);
+
+  // Fallback
+  return Type::getDoubleTy(Context);
+}
+
+StructType *ABITypeMapper::createStructFromFields(ArrayRef<abi::FieldInfo> Fields,uint32_t NumFields,
+                                                  TypeSize Size, Align Alignment,
+                                                  bool IsUnion) {
+  SmallVector<Type *, 16> FieldTypes;
+  
+  if (IsUnion) {
+    Type *LargestFieldType = nullptr;
+    uint64_t LargestFieldSize = 0;
+    
+    for (const auto &Field : Fields) {
+      Type *FieldType = convertType(Field.FieldType);
+      if (!FieldType)
+        continue;
+        
+      uint64_t FieldSize = 0;
+      if (auto *IntTy = dyn_cast<IntegerType>(FieldType)) {
+        FieldSize = IntTy->getBitWidth();
+      } else if (FieldType->isFloatingPointTy()) {
+        FieldSize = FieldType->getPrimitiveSizeInBits();
+      } else if (FieldType->isPointerTy()) {
+        FieldSize = 64; // Assume 64-bit pointers
+      }
+      
+      if (FieldSize > LargestFieldSize) {
+        LargestFieldSize = FieldSize;
+        LargestFieldType = FieldType;
+      }
+    }
+    
+    if (LargestFieldType) {
+      FieldTypes.push_back(LargestFieldType);
+      
+      uint64_t UnionSizeBits = Size.getFixedValue();
+      if (LargestFieldSize < UnionSizeBits) {
+        uint64_t PaddingBits = UnionSizeBits - LargestFieldSize;
+        if (PaddingBits % 8 == 0) {
+          Type *ByteType = IntegerType::get(Context, 8);
+          Type *PaddingType = ArrayType::get(ByteType, PaddingBits / 8);
+          FieldTypes.push_back(PaddingType);
+        } else {
+          Type *PaddingType = IntegerType::get(Context, PaddingBits);
+          FieldTypes.push_back(PaddingType);
+        }
+      }
+    }
+  } else {
+    uint64_t CurrentOffset = 0;
+    
+    for (const auto &Field : Fields) {
+      if (Field.OffsetInBits > CurrentOffset) {
+        uint64_t PaddingBits = Field.OffsetInBits - CurrentOffset;
+        if (PaddingBits % 8 == 0 && PaddingBits >= 8) {
+          Type *ByteType = IntegerType::get(Context, 8);
+          Type *PaddingType = ArrayType::get(ByteType, PaddingBits / 8);
+          FieldTypes.push_back(PaddingType);
+        } else if (PaddingBits > 0) {
+          Type *PaddingType = IntegerType::get(Context, PaddingBits);
+          FieldTypes.push_back(PaddingType);
+        }
+        CurrentOffset = Field.OffsetInBits;
+      }
+      
+      Type *FieldType = convertType(Field.FieldType);
+      if (!FieldType)
+        continue;
+      
+      if (Field.IsBitField && Field.BitFieldWidth > 0) {
+        FieldType = IntegerType::get(Context, Field.BitFieldWidth);
+        CurrentOffset += Field.BitFieldWidth;
+      } else {
+        FieldTypes.push_back(FieldType);
+        if (auto *IntTy = dyn_cast<IntegerType>(FieldType)) {
+          CurrentOffset += IntTy->getBitWidth();
+        } else if (FieldType->isFloatingPointTy()) {
+          CurrentOffset += FieldType->getPrimitiveSizeInBits();
+        } else if (FieldType->isPointerTy()) {
+          CurrentOffset += 64; // Assume 64-bit pointers
+        } else {
+          CurrentOffset += 64; // Conservative estimate
+        }
+      }
+    }
+    
+    uint64_t TotalSizeBits = Size.getFixedValue();
+    if (CurrentOffset < TotalSizeBits) {
+      uint64_t PaddingBits = TotalSizeBits - CurrentOffset;
+      if (PaddingBits % 8 == 0 && PaddingBits >= 8) {
+        Type *ByteType = IntegerType::get(Context, 8);
+        Type *PaddingType = ArrayType::get(ByteType, PaddingBits / 8);
+        FieldTypes.push_back(PaddingType);
+      } else if (PaddingBits > 0) {
+        Type *PaddingType = IntegerType::get(Context, PaddingBits);
+        FieldTypes.push_back(PaddingType);
+      }
+    }
+  }
+  
+  return StructType::get(Context, FieldTypes, /*isPacked=*/false);
+}
diff --git a/llvm/lib/ABI/CMakeLists.txt b/llvm/lib/ABI/CMakeLists.txt
index f4b74f551c720..33baab6090998 100644
--- a/llvm/lib/ABI/CMakeLists.txt
+++ b/llvm/lib/ABI/CMakeLists.txt
@@ -1,5 +1,7 @@
 add_llvm_component_library(LLVMABI
   ABIFunctionInfo.cpp
+  ABITypeMapper.cpp
+  TargetCodeGenInfo.cpp
   Targets/BPF.cpp
 
   ADDITIONAL_HEADER_DIRS
diff --git a/llvm/lib/ABI/TargetCodeGenInfo.cpp b/llvm/lib/ABI/TargetCodeGenInfo.cpp
new file mode 100644
index 0000000000000..5bc17961c7341
--- /dev/null
+++ b/llvm/lib/ABI/TargetCodeGenInfo.cpp
@@ -0,0 +1,24 @@
+//===- TargetCodeGenInfo.cpp - Target CodeGen Info Implementation -------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ABI/TargetCodegenInfo.h"
+#include "llvm/ABI/ABIFunctionInfo.h"
+
+namespace llvm::abi {
+
+TargetCodeGenInfo::TargetCodeGenInfo(std::unique_ptr<llvm::abi::ABIInfo> Info)
+    : Info(std::move(Info)) {}
+
+TargetCodeGenInfo::~TargetCodeGenInfo() = default;
+
+void TargetCodeGenInfo::computeInfo(ABIFunctionInfo &FI) const {
+    // Default implementation - derived classes should override this
+    // if they need custom behavior beyond what ABIInfo provides
+}
+
+} // namespace llvm::abi
diff --git a/llvm/lib/ABI/Targets/BPF.cpp b/llvm/lib/ABI/Targets/BPF.cpp
index ae2752eb0c50d..ef80e2df855ad 100644
--- a/llvm/lib/ABI/Targets/BPF.cpp
+++ b/llvm/lib/ABI/Targets/BPF.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ABI/ABIFunctionInfo.h"
+#include "llvm/ABI/TargetCodegenInfo.h"
 #include "llvm/ABI/ABIInfo.h"
 #include "llvm/ABI/Types.h"
 #include "llvm/Support/Alignment.h"
@@ -90,7 +91,7 @@ class BPFABIInfo : public ABIInfo {
     return ABIArgInfo::getDirect();
   }
 
-  void computeInfo(ABIFunctionInfo &FI) {
+  void computeInfo(ABIFunctionInfo &FI) const override  {
     FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
     for (auto &I : FI.arguments()) {
       I.ArgInfo = classifyArgumentType(I.ABIType);
@@ -98,4 +99,15 @@ class BPFABIInfo : public ABIInfo {
   }
 };
 
+class BPFTargetCodeGenInfo : public TargetCodeGenInfo {
+	public:
+		BPFTargetCodeGenInfo(TypeBuilder &TB)
+			: TargetCodeGenInfo(std::make_unique<BPFABIInfo>(TB)){}
+};
+
+std::unique_ptr<TargetCodeGenInfo>
+createBPFTargetCodeGenInfo(TypeBuilder &TB) {
+  return std::make_unique<BPFTargetCodeGenInfo>(TB);
+}
+
 } // namespace llvm::abi



More information about the llvm-commits mailing list