[clang] [llvm] [clang] Integrate LLVMABI for function call ABI lowering (PR #194460)

via cfe-commits cfe-commits at lists.llvm.org
Sun May 3 12:17:13 PDT 2026


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

>From 213d855db0c71993ffac30939adbc808690811e9 Mon Sep 17 00:00:00 2001
From: Narayan Sreekumar <nsreekumar6 at gmail.com>
Date: Sat, 25 Apr 2026 00:47:08 +0530
Subject: [PATCH 1/3] [clang] Integrate LLVMABI for function call ABI lowering

---
 clang/include/clang/Basic/CodeGenOptions.def |   5 +
 clang/include/clang/Options/Options.td       |   7 +
 clang/lib/CodeGen/CGCall.cpp                 |  69 +++++++
 clang/lib/CodeGen/CMakeLists.txt             |   1 +
 clang/lib/CodeGen/CodeGenModule.cpp          |  19 ++
 clang/lib/CodeGen/CodeGenModule.h            |  19 ++
 clang/lib/CodeGen/CodeGenTypes.cpp           |   5 +-
 clang/lib/CodeGen/CodeGenTypes.h             |  19 ++
 clang/lib/CodeGen/QualTypeMapper.h           |   2 +-
 clang/lib/Driver/ToolChains/Clang.cpp        |   2 +
 llvm/include/llvm/ABI/ABITypeMapper.h        |  61 +++++++
 llvm/lib/ABI/ABITypeMapper.cpp               | 178 +++++++++++++++++++
 llvm/lib/ABI/CMakeLists.txt                  |   1 +
 13 files changed, 386 insertions(+), 2 deletions(-)
 create mode 100644 llvm/include/llvm/ABI/ABITypeMapper.h
 create mode 100644 llvm/lib/ABI/ABITypeMapper.cpp

diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index 0d1bf83eaec9f..f8c7209bdc65e 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -28,6 +28,11 @@ CODEGENOPT(Name, Bits, Default, Compatibility)
 #endif
 
 CODEGENOPT(DisableIntegratedAS, 1, 0, Benign) ///< -no-integrated-as
+CODEGENOPT(ExperimentalABILowering, 1, 0, Benign) ///< -fexperimental-abi-lowering:
+                                                  ///< route function ABI lowering
+                                                  ///< through the in-tree LLVMABI
+                                                  ///< library where supported
+                                                  ///< (currently BPF only).
 CODEGENOPT(Crel, 1, 0, Benign) ///< -Wa,--crel
 ENUM_CODEGENOPT(RelocSectionSym, RelocSectionSymType, 2,
                 RelocSectionSymType::All, Benign) ///< -Wa,--reloc-section-sym=
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index c16c41ad4057d..6e46e1060b305 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -3588,6 +3588,13 @@ defm modules_reduced_bmi : BoolOption<"f", "modules-reduced-bmi",
 def experimental_modules_reduced_bmi : Flag<["-"], "fexperimental-modules-reduced-bmi">,
   Group<f_Group>, Visibility<[ClangOption, CC1Option]>, Alias<fmodules_reduced_bmi>;
 
+def fexperimental_abi_lowering : Flag<["-"], "fexperimental-abi-lowering">,
+  Group<f_Group>, Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Use the in-tree LLVMABI library to lower function call ABIs "
+           "instead of the legacy clang lowering. Currently only effective "
+           "for BPF targets.">,
+  MarshallingInfoFlag<CodeGenOpts<"ExperimentalABILowering">>;
+
 def fmodules_embed_all_files : Joined<["-"], "fmodules-embed-all-files">,
   Visibility<[ClangOption, CC1Option, CLOption]>,
   HelpText<"Embed the contents of all files read by this compilation into "
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 3f1ece5fe5347..34afec78290c0 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -32,6 +32,9 @@
 #include "clang/Basic/TargetInfo.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
 #include "clang/CodeGen/SwiftCallingConv.h"
+#include "llvm/ABI/FunctionInfo.h"
+#include "llvm/ABI/TargetInfo.h"
+#include "llvm/ABI/Types.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Analysis/ValueTracking.h"
@@ -830,6 +833,42 @@ void computeSPIRKernelABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI);
 /// 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.
+ABIArgInfo CodeGenTypes::convertABIArgInfo(const llvm::abi::ArgInfo &AbiInfo,
+                                           QualType Type) {
+  switch (AbiInfo.getKind()) {
+  case llvm::abi::ArgInfo::Direct: {
+    llvm::Type *CoercedType = nullptr;
+    if (AbiInfo.getCoerceToType())
+      CoercedType = AbiReverseMapper.convertType(AbiInfo.getCoerceToType());
+    if (!CoercedType)
+      CoercedType = ConvertType(Type);
+    return ABIArgInfo::getDirect(CoercedType, AbiInfo.getDirectOffset());
+  }
+  case llvm::abi::ArgInfo::Extend: {
+    llvm::Type *CoercedType = nullptr;
+    if (AbiInfo.getCoerceToType())
+      CoercedType = AbiReverseMapper.convertType(AbiInfo.getCoerceToType());
+    if (!CoercedType)
+      CoercedType = ConvertType(Type);
+    if (AbiInfo.isSignExt())
+      return ABIArgInfo::getSignExtend(Type, CoercedType);
+    if (AbiInfo.isZeroExt())
+      return ABIArgInfo::getZeroExtend(Type, CoercedType);
+    return ABIArgInfo::getExtend(Type, CoercedType);
+  }
+  case llvm::abi::ArgInfo::Indirect: {
+    CharUnits Alignment =
+        CharUnits::fromQuantity(AbiInfo.getIndirectAlign().value());
+    return ABIArgInfo::getIndirect(Alignment, AbiInfo.getIndirectAddrSpace(),
+                                   AbiInfo.getIndirectByVal(),
+                                   AbiInfo.getIndirectRealign());
+  }
+  case llvm::abi::ArgInfo::Ignore:
+    return ABIArgInfo::getIgnore();
+  }
+  llvm_unreachable("Unexpected llvm::abi::ArgInfo kind");
+}
+
 const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo(
     CanQualType resultType, FnInfoOpts opts, ArrayRef<CanQualType> argTypes,
     FunctionType::ExtInfo info,
@@ -866,6 +905,11 @@ const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo(
   assert(inserted && "Recursively being processed?");
 
   // Compute ABI information.
+  bool UseLLVMABI =
+      CGM.shouldUseLLVMABILowering() && info.getCC() != CC_Swift &&
+      info.getCC() != CC_SwiftAsync &&
+      !(info.getCC() == CC_DeviceKernel &&
+        (CC == llvm::CallingConv::SPIR_KERNEL || CC == llvm::CallingConv::C));
   if (info.getCC() == CC_DeviceKernel &&
       (CC == llvm::CallingConv::SPIR_KERNEL || CC == llvm::CallingConv::C)) {
     // Force target independent argument handling for the host visible
@@ -876,6 +920,31 @@ const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo(
     computeSPIRKernelABIInfo(CGM, *FI);
   } else if (info.getCC() == CC_Swift || info.getCC() == CC_SwiftAsync) {
     swiftcall::computeABIInfo(CGM, *FI);
+  } else if (UseLLVMABI) {
+    SmallVector<const llvm::abi::Type *, 8> MappedArgTypes;
+    MappedArgTypes.reserve(argTypes.size());
+    for (CanQualType ArgType : argTypes)
+      MappedArgTypes.push_back(AbiMapper.convertType(ArgType));
+
+    std::optional<unsigned> NumRequired;
+    if (required.allowsOptionalArgs())
+      NumRequired = required.getNumRequiredArgs();
+
+    llvm::abi::FunctionInfo *AbiFI = llvm::abi::FunctionInfo::create(
+        CC, AbiMapper.convertType(resultType), MappedArgTypes, NumRequired);
+
+    CGM.getLLVMABITargetInfo(AbiMapper.getTypeBuilder()).computeInfo(*AbiFI);
+
+    FI->getReturnInfo() =
+        convertABIArgInfo(AbiFI->getReturnInfo(), FI->getReturnType());
+
+    auto AbiArgs = AbiFI->arguments();
+    unsigned ArgIdx = 0;
+    for (auto &CGArg : FI->arguments()) {
+      assert(ArgIdx < AbiArgs.size() && "ABI arg count mismatch");
+      CGArg.info = convertABIArgInfo(AbiArgs[ArgIdx].Info, CGArg.type);
+      ++ArgIdx;
+    }
   } else {
     CGM.getABIInfo().computeInfo(*FI);
   }
diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt
index 434781b3c4f02..117438c616ab5 100644
--- a/clang/lib/CodeGen/CMakeLists.txt
+++ b/clang/lib/CodeGen/CMakeLists.txt
@@ -1,4 +1,5 @@
 set(LLVM_LINK_COMPONENTS
+  ABI
   AggressiveInstCombine
   Analysis
   BitReader
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index ba51e7a3ff678..75d1f8c888e51 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -47,6 +47,7 @@
 #include "clang/Basic/Version.h"
 #include "clang/CodeGen/BackendUtil.h"
 #include "clang/CodeGen/ConstantInitBuilder.h"
+#include "llvm/ABI/TargetInfo.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -336,6 +337,24 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
   return *TheTargetCodeGenInfo;
 }
 
+bool CodeGenModule::shouldUseLLVMABILowering() const {
+  if (!CodeGenOpts.ExperimentalABILowering)
+    return false;
+  // BPF is the only target wired to the LLVMABI library at the moment.
+  return getTriple().isBPF();
+}
+
+const llvm::abi::TargetInfo &
+CodeGenModule::getLLVMABITargetInfo(llvm::abi::TypeBuilder &TB) {
+  if (TheLLVMABITargetInfo)
+    return *TheLLVMABITargetInfo;
+
+  assert(getTriple().isBPF() &&
+         "LLVMABI lowering requested for an unsupported target");
+  TheLLVMABITargetInfo = llvm::abi::createBPFTargetInfo(TB);
+  return *TheLLVMABITargetInfo;
+}
+
 static void checkDataLayoutConsistency(const TargetInfo &Target,
                                        llvm::LLVMContext &Context,
                                        const LangOptions &Opts) {
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index d62707a3355c9..3286e0ad5f641 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -55,6 +55,11 @@ class IndexedInstrProfReader;
 namespace vfs {
 class FileSystem;
 }
+
+namespace abi {
+class TargetInfo;
+class TypeBuilder;
+} // namespace abi
 }
 
 namespace clang {
@@ -363,6 +368,10 @@ class CodeGenModule : public CodeGenTypeCache {
 
   mutable std::unique_ptr<TargetCodeGenInfo> TheTargetCodeGenInfo;
 
+  /// Cached LLVMABI target lowering info, lazily constructed when the
+  /// experimental ABI lowering path is taken.
+  mutable std::unique_ptr<llvm::abi::TargetInfo> TheLLVMABITargetInfo;
+
   // This should not be moved earlier, since its initialization depends on some
   // of the previous reference members being already initialized and also checks
   // if TheTargetCodeGenInfo is NULL
@@ -877,6 +886,16 @@ class CodeGenModule : public CodeGenTypeCache {
   void maybeSetTrivialComdat(const Decl &D, llvm::GlobalObject &GO);
 
   const ABIInfo &getABIInfo();
+
+  /// Lazily build and return the LLVMABI library's TargetInfo for the current
+  /// target. Used by the experimental ABI lowering path
+  /// (-fexperimental-abi-lowering); only BPF is wired up today.
+  const llvm::abi::TargetInfo &getLLVMABITargetInfo(llvm::abi::TypeBuilder &TB);
+
+  /// True when -fexperimental-abi-lowering is in effect AND the active target
+  /// has an LLVMABI implementation we can route to.
+  bool shouldUseLLVMABILowering() const;
+
   CGCXXABI &getCXXABI() const { return *ABI; }
   llvm::LLVMContext &getLLVMContext() { return VMContext; }
 
diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp
index e76b1e8608d33..6009316861738 100644
--- a/clang/lib/CodeGen/CodeGenTypes.cpp
+++ b/clang/lib/CodeGen/CodeGenTypes.cpp
@@ -33,7 +33,10 @@ using namespace CodeGen;
 
 CodeGenTypes::CodeGenTypes(CodeGenModule &cgm)
     : CGM(cgm), Context(cgm.getContext()), TheModule(cgm.getModule()),
-      Target(cgm.getTarget()) {
+      Target(cgm.getTarget()),
+      AbiMapper(cgm.getContext(), cgm.getModule().getDataLayout(), AbiAlloc),
+      AbiReverseMapper(cgm.getModule().getContext(),
+                       cgm.getModule().getDataLayout()) {
   SkippedLayout = false;
   LongDoubleReferenced = false;
 }
diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h
index 9de7e0a83579d..8a32e27a229b9 100644
--- a/clang/lib/CodeGen/CodeGenTypes.h
+++ b/clang/lib/CodeGen/CodeGenTypes.h
@@ -14,10 +14,15 @@
 #define LLVM_CLANG_LIB_CODEGEN_CODEGENTYPES_H
 
 #include "CGCall.h"
+#include "QualTypeMapper.h"
 #include "clang/Basic/ABI.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
+#include "llvm/ABI/ABITypeMapper.h"
+#include "llvm/ABI/FunctionInfo.h"
+#include "llvm/ABI/Types.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Support/Allocator.h"
 
 namespace llvm {
 class FunctionType;
@@ -92,6 +97,14 @@ class CodeGenTypes {
   /// Helper for ConvertType.
   llvm::Type *ConvertFunctionTypeInternal(QualType FT);
 
+  /// Allocator and mappers used by the experimental LLVMABI-based lowering
+  /// path (gated on -fexperimental-abi-lowering). Constructed unconditionally
+  /// so the path can be entered without re-checking initialization, but the
+  /// caches stay empty when the flag is off.
+  mutable llvm::BumpPtrAllocator AbiAlloc;
+  mutable QualTypeMapper AbiMapper;
+  llvm::abi::ABITypeMapper AbiReverseMapper;
+
 public:
   CodeGenTypes(CodeGenModule &cgm);
   ~CodeGenTypes();
@@ -273,6 +286,12 @@ class CodeGenTypes {
                                              const FunctionProtoType *FTP,
                                              const CXXMethodDecl *MD);
 
+  /// Translate an llvm::abi::ArgInfo (computed by the LLVMABI library) into
+  /// the clang ABIArgInfo consumed by the rest of CodeGen. Used by the
+  /// experimental ABI lowering path.
+  ABIArgInfo convertABIArgInfo(const llvm::abi::ArgInfo &AbiInfo,
+                               QualType Type);
+
   /// "Arrange" the LLVM information for a call or type with the given
   /// signature.  This is largely an internal method; other clients
   /// should use one of the above routines, which ultimately defer to
diff --git a/clang/lib/CodeGen/QualTypeMapper.h b/clang/lib/CodeGen/QualTypeMapper.h
index 11e8ba86cfcdf..35876f44f3aba 100644
--- a/clang/lib/CodeGen/QualTypeMapper.h
+++ b/clang/lib/CodeGen/QualTypeMapper.h
@@ -71,7 +71,7 @@ class QualTypeMapper {
 
   void clearCache() { TypeCache.clear(); }
 
-  llvm::abi::TypeBuilder getTypeBuilder() { return Builder; }
+  llvm::abi::TypeBuilder &getTypeBuilder() { return Builder; }
 };
 
 } // namespace CodeGen
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index cf5a29f19aaff..37cd5fb162681 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6596,6 +6596,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
 
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
 
+  Args.AddLastArg(CmdArgs, options::OPT_fexperimental_abi_lowering);
+
   if (Args.hasArg(options::OPT_fexperimental_new_constant_interpreter))
     CmdArgs.push_back("-fexperimental-new-constant-interpreter");
 
diff --git a/llvm/include/llvm/ABI/ABITypeMapper.h b/llvm/include/llvm/ABI/ABITypeMapper.h
new file mode 100644
index 0000000000000..0f909f3ea9dec
--- /dev/null
+++ b/llvm/include/llvm/ABI/ABITypeMapper.h
@@ -0,0 +1,61 @@
+//===---- 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.
+/// Used by frontends after the ABI library has computed argument/return
+/// classification: coerce-to types in the ABI representation must be
+/// translated to llvm::Type before being handed back to the IR builder.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ABI_ABITYPEMAPPER_H
+#define LLVM_ABI_ABITYPEMAPPER_H
+
+#include "llvm/ABI/Types.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace llvm {
+class LLVMContext;
+class Type;
+class StructType;
+class DataLayout;
+
+namespace abi {
+
+class ABITypeMapper {
+public:
+  ABITypeMapper(LLVMContext &Ctx, const DataLayout &DL)
+      : Context(Ctx), DL(DL) {}
+
+  llvm::Type *convertType(const abi::Type *ABIType);
+
+  void clearCache() { TypeCache.clear(); }
+
+private:
+  LLVMContext &Context;
+  const DataLayout &DL;
+
+  llvm::DenseMap<const abi::Type *, llvm::Type *> TypeCache;
+
+  llvm::Type *convertArrayType(const abi::ArrayType *AT);
+  llvm::Type *convertVectorType(const abi::VectorType *VT);
+  llvm::Type *convertRecordType(const abi::RecordType *RT);
+  llvm::Type *convertComplexType(const abi::ComplexType *CT);
+  llvm::Type *convertMemberPointerType(const abi::MemberPointerType *MPT);
+
+  llvm::StructType *createStructFromFields(ArrayRef<abi::FieldInfo> Fields,
+                                           TypeSize Size, Align Alignment,
+                                           bool IsUnion);
+  llvm::Type *createPaddingType(uint64_t PaddingBits);
+};
+
+} // namespace abi
+} // namespace llvm
+
+#endif // LLVM_ABI_ABITYPEMAPPER_H
diff --git a/llvm/lib/ABI/ABITypeMapper.cpp b/llvm/lib/ABI/ABITypeMapper.cpp
new file mode 100644
index 0000000000000..83e613e70d8a2
--- /dev/null
+++ b/llvm/lib/ABI/ABITypeMapper.cpp
@@ -0,0 +1,178 @@
+//===---- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ABI/ABITypeMapper.h"
+#include "llvm/ABI/Types.h"
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Type.h"
+
+using namespace llvm::abi;
+
+llvm::Type *ABITypeMapper::convertType(const abi::Type *ABIType) {
+  if (!ABIType)
+    return nullptr;
+
+  auto It = TypeCache.find(ABIType);
+  if (It != TypeCache.end())
+    return It->second;
+
+  llvm::Type *Result = nullptr;
+
+  switch (ABIType->getKind()) {
+  case abi::TypeKind::Void:
+    Result = llvm::Type::getVoidTy(Context);
+    break;
+  case abi::TypeKind::Integer: {
+    const auto *IT = cast<abi::IntegerType>(ABIType);
+    Result =
+        llvm::IntegerType::get(Context, IT->getSizeInBits().getFixedValue());
+    break;
+  }
+  case abi::TypeKind::Float: {
+    const llvm::fltSemantics *Semantics =
+        cast<abi::FloatType>(ABIType)->getSemantics();
+    Result = llvm::Type::getFloatingPointTy(Context, *Semantics);
+    break;
+  }
+  case abi::TypeKind::Pointer:
+    Result = llvm::PointerType::get(
+        Context, cast<abi::PointerType>(ABIType)->getAddrSpace());
+    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::Record:
+    Result = convertRecordType(cast<abi::RecordType>(ABIType));
+    break;
+  case abi::TypeKind::Complex:
+    Result = convertComplexType(cast<abi::ComplexType>(ABIType));
+    break;
+  case abi::TypeKind::MemberPointer:
+    Result = convertMemberPointerType(cast<abi::MemberPointerType>(ABIType));
+    break;
+  }
+
+  if (Result)
+    TypeCache[ABIType] = Result;
+  return Result;
+}
+
+llvm::Type *ABITypeMapper::convertArrayType(const abi::ArrayType *AT) {
+  llvm::Type *ElementType = convertType(AT->getElementType());
+  if (!ElementType)
+    return nullptr;
+  uint64_t NumElements = AT->getNumElements();
+  if (AT->isMatrixType())
+    return llvm::VectorType::get(ElementType,
+                                 ElementCount::getFixed(NumElements));
+  return llvm::ArrayType::get(ElementType, NumElements);
+}
+
+llvm::Type *ABITypeMapper::convertVectorType(const abi::VectorType *VT) {
+  llvm::Type *ElementType = convertType(VT->getElementType());
+  if (!ElementType)
+    return nullptr;
+  return llvm::VectorType::get(ElementType, VT->getNumElements());
+}
+
+llvm::Type *ABITypeMapper::convertRecordType(const abi::RecordType *RT) {
+  return createStructFromFields(RT->getFields(), RT->getSizeInBits(),
+                                RT->getAlignment(), RT->isUnion());
+}
+
+llvm::Type *ABITypeMapper::convertComplexType(const abi::ComplexType *CT) {
+  llvm::Type *ElementType = convertType(CT->getElementType());
+  if (!ElementType)
+    return nullptr;
+  llvm::Type *Fields[] = {ElementType, ElementType};
+  return llvm::StructType::get(Context, Fields, /*isPacked=*/false);
+}
+
+llvm::Type *
+ABITypeMapper::convertMemberPointerType(const abi::MemberPointerType *MPT) {
+  llvm::Type *IntPtrTy = DL.getIntPtrType(Context);
+  if (MPT->isFunctionPointer()) {
+    llvm::Type *Fields[] = {IntPtrTy, IntPtrTy};
+    return llvm::StructType::get(Context, Fields, /*isPacked=*/false);
+  }
+  return IntPtrTy;
+}
+
+llvm::Type *ABITypeMapper::createPaddingType(uint64_t PaddingBits) {
+  if (PaddingBits == 0)
+    return nullptr;
+  if (PaddingBits % 8 == 0)
+    return llvm::ArrayType::get(llvm::IntegerType::get(Context, 8),
+                                PaddingBits / 8);
+  return llvm::IntegerType::get(Context, PaddingBits);
+}
+
+llvm::StructType *
+ABITypeMapper::createStructFromFields(ArrayRef<abi::FieldInfo> Fields,
+                                      TypeSize Size, Align Alignment,
+                                      bool IsUnion) {
+  SmallVector<llvm::Type *, 16> FieldTypes;
+
+  if (IsUnion) {
+    llvm::Type *LargestFieldType = nullptr;
+    uint64_t LargestFieldSize = 0;
+    for (const auto &Field : Fields) {
+      llvm::Type *FieldType = convertType(Field.FieldType);
+      if (!FieldType)
+        continue;
+      uint64_t FieldSize = DL.getTypeSizeInBits(FieldType);
+      if (FieldSize > LargestFieldSize) {
+        LargestFieldSize = FieldSize;
+        LargestFieldType = FieldType;
+      }
+    }
+    if (LargestFieldType) {
+      FieldTypes.push_back(LargestFieldType);
+      uint64_t UnionSizeBits = Size.getFixedValue();
+      if (LargestFieldSize < UnionSizeBits) {
+        if (llvm::Type *PaddingType =
+                createPaddingType(UnionSizeBits - LargestFieldSize))
+          FieldTypes.push_back(PaddingType);
+      }
+    }
+  } else {
+    uint64_t CurrentOffset = 0;
+    for (const auto &Field : Fields) {
+      if (Field.OffsetInBits > CurrentOffset) {
+        if (llvm::Type *PaddingType =
+                createPaddingType(Field.OffsetInBits - CurrentOffset))
+          FieldTypes.push_back(PaddingType);
+        CurrentOffset = Field.OffsetInBits;
+      }
+      llvm::Type *FieldType = convertType(Field.FieldType);
+      if (!FieldType)
+        continue;
+      if (Field.IsBitField && Field.BitFieldWidth > 0) {
+        FieldType = llvm::IntegerType::get(Context, Field.BitFieldWidth);
+        CurrentOffset += Field.BitFieldWidth;
+      } else {
+        FieldTypes.push_back(FieldType);
+        CurrentOffset += DL.getTypeSizeInBits(FieldType);
+      }
+    }
+    uint64_t TotalSizeBits = Size.getFixedValue();
+    if (CurrentOffset < TotalSizeBits) {
+      if (llvm::Type *PaddingType =
+              createPaddingType(TotalSizeBits - CurrentOffset))
+        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 eb1d6042a25cd..53f3fa5c335fd 100644
--- a/llvm/lib/ABI/CMakeLists.txt
+++ b/llvm/lib/ABI/CMakeLists.txt
@@ -2,6 +2,7 @@ add_llvm_component_library(LLVMABI
   Types.cpp
   FunctionInfo.cpp
   TargetInfo.cpp
+  ABITypeMapper.cpp
   Targets/BPF.cpp
 
   ADDITIONAL_HEADER_DIRS

>From 100b05803928d8673bbea2c89340d9c4189dfb31 Mon Sep 17 00:00:00 2001
From: Narayan Sreekumar <nsreekumar6 at gmail.com>
Date: Wed, 29 Apr 2026 20:10:04 +0530
Subject: [PATCH 2/3] address review

---
 clang/include/clang/Basic/CodeGenOptions.def  |  3 +-
 clang/include/clang/Options/Options.td        |  5 +-
 clang/lib/CodeGen/CGCall.cpp                  | 25 +++------
 clang/lib/CodeGen/CodeGenModule.cpp           |  3 +-
 clang/lib/CodeGen/CodeGenModule.h             |  2 +-
 clang/lib/CodeGen/CodeGenTypes.h              |  4 +-
 clang/lib/Driver/ToolChains/Clang.cpp         |  2 -
 .../ABI/{ABITypeMapper.h => IRTypeMapper.h}   | 11 ++--
 llvm/lib/ABI/CMakeLists.txt                   |  2 +-
 .../{ABITypeMapper.cpp => IRTypeMapper.cpp}   | 52 +++++++------------
 10 files changed, 41 insertions(+), 68 deletions(-)
 rename llvm/include/llvm/ABI/{ABITypeMapper.h => IRTypeMapper.h} (87%)
 rename llvm/lib/ABI/{ABITypeMapper.cpp => IRTypeMapper.cpp} (76%)

diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index f8c7209bdc65e..fd0b6d9096f50 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -31,8 +31,7 @@ CODEGENOPT(DisableIntegratedAS, 1, 0, Benign) ///< -no-integrated-as
 CODEGENOPT(ExperimentalABILowering, 1, 0, Benign) ///< -fexperimental-abi-lowering:
                                                   ///< route function ABI lowering
                                                   ///< through the in-tree LLVMABI
-                                                  ///< library where supported
-                                                  ///< (currently BPF only).
+                                                  ///< library where supported.
 CODEGENOPT(Crel, 1, 0, Benign) ///< -Wa,--crel
 ENUM_CODEGENOPT(RelocSectionSym, RelocSectionSymType, 2,
                 RelocSectionSymType::All, Benign) ///< -Wa,--reloc-section-sym=
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 6e46e1060b305..a642c5e201932 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -3589,10 +3589,7 @@ def experimental_modules_reduced_bmi : Flag<["-"], "fexperimental-modules-reduce
   Group<f_Group>, Visibility<[ClangOption, CC1Option]>, Alias<fmodules_reduced_bmi>;
 
 def fexperimental_abi_lowering : Flag<["-"], "fexperimental-abi-lowering">,
-  Group<f_Group>, Visibility<[ClangOption, CC1Option]>,
-  HelpText<"Use the in-tree LLVMABI library to lower function call ABIs "
-           "instead of the legacy clang lowering. Currently only effective "
-           "for BPF targets.">,
+  Group<f_Group>, Visibility<[CC1Option]>,
   MarshallingInfoFlag<CodeGenOpts<"ExperimentalABILowering">>;
 
 def fmodules_embed_all_files : Joined<["-"], "fmodules-embed-all-files">,
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 34afec78290c0..64c30dfb1e2d4 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -827,12 +827,9 @@ const CGFunctionInfo &CodeGenTypes::arrangeCall(const CGFunctionInfo &signature,
 namespace clang {
 namespace CodeGen {
 void computeSPIRKernelABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI);
-}
+} // namespace CodeGen
 } // 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.
 ABIArgInfo CodeGenTypes::convertABIArgInfo(const llvm::abi::ArgInfo &AbiInfo,
                                            QualType Type) {
   switch (AbiInfo.getKind()) {
@@ -869,6 +866,9 @@ ABIArgInfo CodeGenTypes::convertABIArgInfo(const llvm::abi::ArgInfo &AbiInfo,
   llvm_unreachable("Unexpected llvm::abi::ArgInfo kind");
 }
 
+/// 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.
 const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo(
     CanQualType resultType, FnInfoOpts opts, ArrayRef<CanQualType> argTypes,
     FunctionType::ExtInfo info,
@@ -905,11 +905,6 @@ const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo(
   assert(inserted && "Recursively being processed?");
 
   // Compute ABI information.
-  bool UseLLVMABI =
-      CGM.shouldUseLLVMABILowering() && info.getCC() != CC_Swift &&
-      info.getCC() != CC_SwiftAsync &&
-      !(info.getCC() == CC_DeviceKernel &&
-        (CC == llvm::CallingConv::SPIR_KERNEL || CC == llvm::CallingConv::C));
   if (info.getCC() == CC_DeviceKernel &&
       (CC == llvm::CallingConv::SPIR_KERNEL || CC == llvm::CallingConv::C)) {
     // Force target independent argument handling for the host visible
@@ -920,7 +915,7 @@ const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo(
     computeSPIRKernelABIInfo(CGM, *FI);
   } else if (info.getCC() == CC_Swift || info.getCC() == CC_SwiftAsync) {
     swiftcall::computeABIInfo(CGM, *FI);
-  } else if (UseLLVMABI) {
+  } else if (CGM.shouldUseLLVMABILowering()) {
     SmallVector<const llvm::abi::Type *, 8> MappedArgTypes;
     MappedArgTypes.reserve(argTypes.size());
     for (CanQualType ArgType : argTypes)
@@ -938,13 +933,9 @@ const CGFunctionInfo &CodeGenTypes::arrangeLLVMFunctionInfo(
     FI->getReturnInfo() =
         convertABIArgInfo(AbiFI->getReturnInfo(), FI->getReturnType());
 
-    auto AbiArgs = AbiFI->arguments();
-    unsigned ArgIdx = 0;
-    for (auto &CGArg : FI->arguments()) {
-      assert(ArgIdx < AbiArgs.size() && "ABI arg count mismatch");
-      CGArg.info = convertABIArgInfo(AbiArgs[ArgIdx].Info, CGArg.type);
-      ++ArgIdx;
-    }
+    for (auto [CGArg, AbiArg] :
+         llvm::zip_equal(FI->arguments(), AbiFI->arguments()))
+      CGArg.info = convertABIArgInfo(AbiArg.Info, CGArg.type);
   } else {
     CGM.getABIInfo().computeInfo(*FI);
   }
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 75d1f8c888e51..37f4d8a6e08f2 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -340,7 +340,8 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
 bool CodeGenModule::shouldUseLLVMABILowering() const {
   if (!CodeGenOpts.ExperimentalABILowering)
     return false;
-  // BPF is the only target wired to the LLVMABI library at the moment.
+  // Only opt in for targets that have an LLVMABI implementation; others
+  // continue through the legacy ABIInfo path.
   return getTriple().isBPF();
 }
 
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 3286e0ad5f641..b90a32f614b5d 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -889,7 +889,7 @@ class CodeGenModule : public CodeGenTypeCache {
 
   /// Lazily build and return the LLVMABI library's TargetInfo for the current
   /// target. Used by the experimental ABI lowering path
-  /// (-fexperimental-abi-lowering); only BPF is wired up today.
+  /// (-fexperimental-abi-lowering).
   const llvm::abi::TargetInfo &getLLVMABITargetInfo(llvm::abi::TypeBuilder &TB);
 
   /// True when -fexperimental-abi-lowering is in effect AND the active target
diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h
index 8a32e27a229b9..e5e39f7061d64 100644
--- a/clang/lib/CodeGen/CodeGenTypes.h
+++ b/clang/lib/CodeGen/CodeGenTypes.h
@@ -17,8 +17,8 @@
 #include "QualTypeMapper.h"
 #include "clang/Basic/ABI.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
-#include "llvm/ABI/ABITypeMapper.h"
 #include "llvm/ABI/FunctionInfo.h"
+#include "llvm/ABI/IRTypeMapper.h"
 #include "llvm/ABI/Types.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/IR/Module.h"
@@ -103,7 +103,7 @@ class CodeGenTypes {
   /// caches stay empty when the flag is off.
   mutable llvm::BumpPtrAllocator AbiAlloc;
   mutable QualTypeMapper AbiMapper;
-  llvm::abi::ABITypeMapper AbiReverseMapper;
+  llvm::abi::IRTypeMapper AbiReverseMapper;
 
 public:
   CodeGenTypes(CodeGenModule &cgm);
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 37cd5fb162681..cf5a29f19aaff 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6596,8 +6596,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
 
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
 
-  Args.AddLastArg(CmdArgs, options::OPT_fexperimental_abi_lowering);
-
   if (Args.hasArg(options::OPT_fexperimental_new_constant_interpreter))
     CmdArgs.push_back("-fexperimental-new-constant-interpreter");
 
diff --git a/llvm/include/llvm/ABI/ABITypeMapper.h b/llvm/include/llvm/ABI/IRTypeMapper.h
similarity index 87%
rename from llvm/include/llvm/ABI/ABITypeMapper.h
rename to llvm/include/llvm/ABI/IRTypeMapper.h
index 0f909f3ea9dec..1a77cfd91bca9 100644
--- a/llvm/include/llvm/ABI/ABITypeMapper.h
+++ b/llvm/include/llvm/ABI/IRTypeMapper.h
@@ -1,4 +1,4 @@
-//===---- ABITypeMapper.h - Maps LLVM ABI Types to LLVM IR Types --------===//
+//===---- IRTypeMapper.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.
@@ -14,8 +14,8 @@
 ///
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_ABI_ABITYPEMAPPER_H
-#define LLVM_ABI_ABITYPEMAPPER_H
+#ifndef LLVM_ABI_IRTYPEMAPPER_H
+#define LLVM_ABI_IRTYPEMAPPER_H
 
 #include "llvm/ABI/Types.h"
 #include "llvm/ADT/DenseMap.h"
@@ -28,10 +28,9 @@ class DataLayout;
 
 namespace abi {
 
-class ABITypeMapper {
+class IRTypeMapper {
 public:
-  ABITypeMapper(LLVMContext &Ctx, const DataLayout &DL)
-      : Context(Ctx), DL(DL) {}
+  IRTypeMapper(LLVMContext &Ctx, const DataLayout &DL) : Context(Ctx), DL(DL) {}
 
   llvm::Type *convertType(const abi::Type *ABIType);
 
diff --git a/llvm/lib/ABI/CMakeLists.txt b/llvm/lib/ABI/CMakeLists.txt
index 53f3fa5c335fd..a5c102b57d074 100644
--- a/llvm/lib/ABI/CMakeLists.txt
+++ b/llvm/lib/ABI/CMakeLists.txt
@@ -2,7 +2,7 @@ add_llvm_component_library(LLVMABI
   Types.cpp
   FunctionInfo.cpp
   TargetInfo.cpp
-  ABITypeMapper.cpp
+  IRTypeMapper.cpp
   Targets/BPF.cpp
 
   ADDITIONAL_HEADER_DIRS
diff --git a/llvm/lib/ABI/ABITypeMapper.cpp b/llvm/lib/ABI/IRTypeMapper.cpp
similarity index 76%
rename from llvm/lib/ABI/ABITypeMapper.cpp
rename to llvm/lib/ABI/IRTypeMapper.cpp
index 83e613e70d8a2..6a9e43c0957ac 100644
--- a/llvm/lib/ABI/ABITypeMapper.cpp
+++ b/llvm/lib/ABI/IRTypeMapper.cpp
@@ -1,4 +1,4 @@
-//===---- ABITypeMapper.cpp - Maps LLVM ABI Types to LLVM IR Types ------===//
+//===---- IRTypeMapper.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.
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/ABI/ABITypeMapper.h"
+#include "llvm/ABI/IRTypeMapper.h"
 #include "llvm/ABI/Types.h"
 #include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/SmallVector.h"
@@ -16,9 +16,8 @@
 
 using namespace llvm::abi;
 
-llvm::Type *ABITypeMapper::convertType(const abi::Type *ABIType) {
-  if (!ABIType)
-    return nullptr;
+llvm::Type *IRTypeMapper::convertType(const abi::Type *ABIType) {
+  assert(ABIType && "convertType requires a non-null ABI type");
 
   auto It = TypeCache.find(ABIType);
   if (It != TypeCache.end())
@@ -63,15 +62,12 @@ llvm::Type *ABITypeMapper::convertType(const abi::Type *ABIType) {
     break;
   }
 
-  if (Result)
-    TypeCache[ABIType] = Result;
+  TypeCache[ABIType] = Result;
   return Result;
 }
 
-llvm::Type *ABITypeMapper::convertArrayType(const abi::ArrayType *AT) {
+llvm::Type *IRTypeMapper::convertArrayType(const abi::ArrayType *AT) {
   llvm::Type *ElementType = convertType(AT->getElementType());
-  if (!ElementType)
-    return nullptr;
   uint64_t NumElements = AT->getNumElements();
   if (AT->isMatrixType())
     return llvm::VectorType::get(ElementType,
@@ -79,28 +75,24 @@ llvm::Type *ABITypeMapper::convertArrayType(const abi::ArrayType *AT) {
   return llvm::ArrayType::get(ElementType, NumElements);
 }
 
-llvm::Type *ABITypeMapper::convertVectorType(const abi::VectorType *VT) {
+llvm::Type *IRTypeMapper::convertVectorType(const abi::VectorType *VT) {
   llvm::Type *ElementType = convertType(VT->getElementType());
-  if (!ElementType)
-    return nullptr;
   return llvm::VectorType::get(ElementType, VT->getNumElements());
 }
 
-llvm::Type *ABITypeMapper::convertRecordType(const abi::RecordType *RT) {
+llvm::Type *IRTypeMapper::convertRecordType(const abi::RecordType *RT) {
   return createStructFromFields(RT->getFields(), RT->getSizeInBits(),
                                 RT->getAlignment(), RT->isUnion());
 }
 
-llvm::Type *ABITypeMapper::convertComplexType(const abi::ComplexType *CT) {
+llvm::Type *IRTypeMapper::convertComplexType(const abi::ComplexType *CT) {
   llvm::Type *ElementType = convertType(CT->getElementType());
-  if (!ElementType)
-    return nullptr;
   llvm::Type *Fields[] = {ElementType, ElementType};
   return llvm::StructType::get(Context, Fields, /*isPacked=*/false);
 }
 
 llvm::Type *
-ABITypeMapper::convertMemberPointerType(const abi::MemberPointerType *MPT) {
+IRTypeMapper::convertMemberPointerType(const abi::MemberPointerType *MPT) {
   llvm::Type *IntPtrTy = DL.getIntPtrType(Context);
   if (MPT->isFunctionPointer()) {
     llvm::Type *Fields[] = {IntPtrTy, IntPtrTy};
@@ -109,19 +101,19 @@ ABITypeMapper::convertMemberPointerType(const abi::MemberPointerType *MPT) {
   return IntPtrTy;
 }
 
-llvm::Type *ABITypeMapper::createPaddingType(uint64_t PaddingBits) {
+llvm::Type *IRTypeMapper::createPaddingType(uint64_t PaddingBits) {
   if (PaddingBits == 0)
     return nullptr;
-  if (PaddingBits % 8 == 0)
-    return llvm::ArrayType::get(llvm::IntegerType::get(Context, 8),
-                                PaddingBits / 8);
-  return llvm::IntegerType::get(Context, PaddingBits);
+  assert(PaddingBits % 8 == 0 &&
+         "sub-byte padding cannot be expressed as an llvm::Type");
+  return llvm::ArrayType::get(llvm::IntegerType::get(Context, 8),
+                              PaddingBits / 8);
 }
 
 llvm::StructType *
-ABITypeMapper::createStructFromFields(ArrayRef<abi::FieldInfo> Fields,
-                                      TypeSize Size, Align Alignment,
-                                      bool IsUnion) {
+IRTypeMapper::createStructFromFields(ArrayRef<abi::FieldInfo> Fields,
+                                     TypeSize Size, Align Alignment,
+                                     bool IsUnion) {
   SmallVector<llvm::Type *, 16> FieldTypes;
 
   if (IsUnion) {
@@ -129,9 +121,7 @@ ABITypeMapper::createStructFromFields(ArrayRef<abi::FieldInfo> Fields,
     uint64_t LargestFieldSize = 0;
     for (const auto &Field : Fields) {
       llvm::Type *FieldType = convertType(Field.FieldType);
-      if (!FieldType)
-        continue;
-      uint64_t FieldSize = DL.getTypeSizeInBits(FieldType);
+      uint64_t FieldSize = Field.FieldType->getSizeInBits().getFixedValue();
       if (FieldSize > LargestFieldSize) {
         LargestFieldSize = FieldSize;
         LargestFieldType = FieldType;
@@ -156,14 +146,12 @@ ABITypeMapper::createStructFromFields(ArrayRef<abi::FieldInfo> Fields,
         CurrentOffset = Field.OffsetInBits;
       }
       llvm::Type *FieldType = convertType(Field.FieldType);
-      if (!FieldType)
-        continue;
       if (Field.IsBitField && Field.BitFieldWidth > 0) {
         FieldType = llvm::IntegerType::get(Context, Field.BitFieldWidth);
         CurrentOffset += Field.BitFieldWidth;
       } else {
         FieldTypes.push_back(FieldType);
-        CurrentOffset += DL.getTypeSizeInBits(FieldType);
+        CurrentOffset += Field.FieldType->getSizeInBits().getFixedValue();
       }
     }
     uint64_t TotalSizeBits = Size.getFixedValue();

>From aa40a748cd475efcb64238f3b3b69f63b4003adf Mon Sep 17 00:00:00 2001
From: Narayan Sreekumar <nsreekumar6 at gmail.com>
Date: Mon, 4 May 2026 00:46:37 +0530
Subject: [PATCH 3/3] tests for bpf

---
 clang/test/CodeGen/bpf-abiinfo.c         | 1 +
 clang/test/CodeGen/bpf-struct-argument.c | 1 +
 clang/test/CodeGen/bpf-union-argument.c  | 1 +
 3 files changed, 3 insertions(+)

diff --git a/clang/test/CodeGen/bpf-abiinfo.c b/clang/test/CodeGen/bpf-abiinfo.c
index 366e8003f4557..f3f421fcde520 100644
--- a/clang/test/CodeGen/bpf-abiinfo.c
+++ b/clang/test/CodeGen/bpf-abiinfo.c
@@ -1,5 +1,6 @@
 // REQUIRES: bpf-registered-target
 // RUN: %clang_cc1 -triple bpf -O2 -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple bpf -O2 -emit-llvm -disable-llvm-passes -fexperimental-abi-lowering %s -o - | FileCheck %s
 
 _Bool bar_bool(void);
 unsigned char bar_char(void);
diff --git a/clang/test/CodeGen/bpf-struct-argument.c b/clang/test/CodeGen/bpf-struct-argument.c
index d4fcf16af2e28..bdfdbbb61770f 100644
--- a/clang/test/CodeGen/bpf-struct-argument.c
+++ b/clang/test/CodeGen/bpf-struct-argument.c
@@ -1,5 +1,6 @@
 // REQUIRES: bpf-registered-target
 // RUN: %clang_cc1 -triple bpf -O2 -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple bpf -O2 -emit-llvm -disable-llvm-passes -fexperimental-abi-lowering %s -o - | FileCheck %s
 
 struct t1 {};
 struct t2 {
diff --git a/clang/test/CodeGen/bpf-union-argument.c b/clang/test/CodeGen/bpf-union-argument.c
index 5f3a0bc5a9261..7020f2f999d44 100644
--- a/clang/test/CodeGen/bpf-union-argument.c
+++ b/clang/test/CodeGen/bpf-union-argument.c
@@ -1,5 +1,6 @@
 // REQUIRES: bpf-registered-target
 // RUN: %clang_cc1 -triple bpf -O2 -emit-llvm -disable-llvm-passes %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple bpf -O2 -emit-llvm -disable-llvm-passes -fexperimental-abi-lowering %s -o - | FileCheck %s
 
 union t1 {};
 union t2 {



More information about the cfe-commits mailing list