[clang] [llvm] [clang] Integrate LLVMABI for function call ABI lowering (PR #194460)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 27 13:48:06 PDT 2026
https://github.com/vortex73 created https://github.com/llvm/llvm-project/pull/194460
None
>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] [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
More information about the cfe-commits
mailing list