[llvm] [llvm] ABIInfo and TargetCodegenInfo (PR #190730)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 8 12:17:50 PDT 2026
https://github.com/vortex73 updated https://github.com/llvm/llvm-project/pull/190730
>From 86f7f3f53fe975bf13194e421777c0de3ef39460 Mon Sep 17 00:00:00 2001
From: Narayan Sreekumar <nsreekumar6 at gmail.com>
Date: Sun, 22 Mar 2026 00:30:10 +0530
Subject: [PATCH] ABIInfo and TargetCodegenInfo
---
llvm/include/llvm/ABI/TargetInfo.h | 93 ++++++++++++++++++++++++++
llvm/lib/ABI/CMakeLists.txt | 1 +
llvm/lib/ABI/TargetInfo.cpp | 102 +++++++++++++++++++++++++++++
3 files changed, 196 insertions(+)
create mode 100644 llvm/include/llvm/ABI/TargetInfo.h
create mode 100644 llvm/lib/ABI/TargetInfo.cpp
diff --git a/llvm/include/llvm/ABI/TargetInfo.h b/llvm/include/llvm/ABI/TargetInfo.h
new file mode 100644
index 0000000000000..9cc221b07317e
--- /dev/null
+++ b/llvm/include/llvm/ABI/TargetInfo.h
@@ -0,0 +1,93 @@
+//===----- TargetInfo.h - Target ABI 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Target-specific ABI information and factory functions.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ABI_TARGETINFO_H
+#define LLVM_ABI_TARGETINFO_H
+
+#include "llvm/ABI/FunctionInfo.h"
+#include "llvm/ABI/Types.h"
+#include <cassert>
+#include <memory>
+
+namespace llvm {
+namespace abi {
+
+enum RecordArgABI {
+ /// Pass it using the normal C aggregate rules for the ABI, potentially
+ /// introducing extra copies and passing some or all of it in registers.
+ RAA_Default = 0,
+
+ /// Pass it on the stack using its defined layout. The argument must be
+ /// evaluated directly into the correct stack position in the arguments area,
+ /// and the call machinery must not move it or introduce extra copies.
+ RAA_DirectInMemory,
+
+ /// Pass it as a pointer to temporary memory.
+ RAA_Indirect
+};
+
+/// Flags controlling target-specific ABI compatibility behaviour.
+/// Construct with the default constructor for the current ABI, or use
+/// fromVersion() to get the flags that match a specific Clang version.
+struct ABICompatInfo {
+ bool PassInt128VectorsInMem : 1;
+ bool ReturnCXXRecordGreaterThan128InMem : 1;
+ bool ClassifyIntegerMMXAsSSE : 1;
+ bool HonorsRevision98 : 1;
+ bool Clang11Compat : 1;
+
+ ABICompatInfo()
+ : PassInt128VectorsInMem(true),
+ ReturnCXXRecordGreaterThan128InMem(true),
+ ClassifyIntegerMMXAsSSE(true), HonorsRevision98(true),
+ Clang11Compat(true) {}
+
+ /// Return flags matching the ABI emitted by the given Clang major version.
+ // TODO: fill in per-version flag overrides.
+ static ABICompatInfo fromVersion(unsigned /*ClangMajor*/) {
+ return ABICompatInfo();
+ }
+};
+
+class TargetInfo {
+private:
+ ABICompatInfo CompatInfo;
+
+public:
+ TargetInfo() : CompatInfo() {}
+ explicit TargetInfo(const ABICompatInfo &Info) : CompatInfo(Info) {}
+
+ virtual ~TargetInfo() = default;
+
+ RecordArgABI getRecordArgABI(const RecordType *RT) const;
+ RecordArgABI getRecordArgABI(const Type *Ty) const;
+ RecordArgABI getRecordArgABI(const RecordType *RT, bool IsCxxRecord) const;
+ bool isPromotableInteger(const IntegerType *IT) const;
+ virtual void computeInfo(FunctionInfo &FI) const = 0;
+ virtual bool isPassByRef(const Type *Ty) const { return false; }
+ const ABICompatInfo &getABICompatInfo() const { return CompatInfo; }
+ ArgInfo getNaturalAlignIndirect(const Type *Ty, bool ByVal = true) const;
+ bool isAggregateTypeForABI(const Type *Ty) const;
+ bool isZeroSizedType(const Type *Ty) const;
+ bool isEmptyRecord(const RecordType *RT) const;
+ bool isEmptyField(const FieldInfo &FI) const;
+};
+
+std::unique_ptr<TargetInfo> createBPFTargetInfo(TypeBuilder &TB);
+
+// TODO: Add factory functions for further targets here.
+
+} // namespace abi
+} // namespace llvm
+
+#endif // LLVM_ABI_TARGETINFO_H
diff --git a/llvm/lib/ABI/CMakeLists.txt b/llvm/lib/ABI/CMakeLists.txt
index 8ece1803b8aa1..ef4f1df07f69c 100644
--- a/llvm/lib/ABI/CMakeLists.txt
+++ b/llvm/lib/ABI/CMakeLists.txt
@@ -1,6 +1,7 @@
add_llvm_component_library(LLVMABI
Types.cpp
FunctionInfo.cpp
+ TargetInfo.cpp
ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/ABI
diff --git a/llvm/lib/ABI/TargetInfo.cpp b/llvm/lib/ABI/TargetInfo.cpp
new file mode 100644
index 0000000000000..2ebc68d8cc848
--- /dev/null
+++ b/llvm/lib/ABI/TargetInfo.cpp
@@ -0,0 +1,102 @@
+//===- TargetInfo.cpp - Target ABI information ----------------------------===//
+//
+// 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/TargetInfo.h"
+
+using namespace llvm::abi;
+
+bool TargetInfo::isAggregateTypeForABI(const Type *Ty) const {
+ // Check for fundamental scalar types.
+ if (Ty->isInteger() || Ty->isFloat() || Ty->isPointer() || Ty->isVector())
+ return false;
+
+ // Everything else is treated as aggregate.
+ return true;
+}
+
+bool TargetInfo::isPromotableInteger(const IntegerType *IT) const {
+ // TODO: The threshold should be the target's int size rather than a hardcoded 32.
+ unsigned BitWidth = IT->getSizeInBits().getFixedValue();
+ return BitWidth < 32;
+}
+
+ArgInfo TargetInfo::getNaturalAlignIndirect(const Type *Ty, bool ByVal) const {
+ return ArgInfo::getIndirect(Ty->getAlignment(), ByVal);
+}
+
+RecordArgABI TargetInfo::getRecordArgABI(const RecordType *RT) const {
+ if (RT && !RT->canPassInRegisters())
+ return RAA_Indirect;
+ return RAA_Default;
+}
+
+RecordArgABI TargetInfo::getRecordArgABI(const RecordType *RT,
+ bool IsCxxRecord) const {
+ if (!IsCxxRecord) {
+ if (!RT->canPassInRegisters())
+ return RAA_Indirect;
+ return RAA_Default;
+ }
+ return getRecordArgABI(RT);
+}
+
+RecordArgABI TargetInfo::getRecordArgABI(const Type *Ty) const {
+ const RecordType *RT = dyn_cast<RecordType>(Ty);
+ if (!RT)
+ return RAA_Default;
+ return getRecordArgABI(RT, RT->isCXXRecord());
+}
+
+bool TargetInfo::isZeroSizedType(const Type *Ty) const {
+ return Ty->getSizeInBits().getFixedValue() == 0;
+}
+
+bool TargetInfo::isEmptyRecord(const RecordType *RT) const {
+ if (RT->hasFlexibleArrayMember() || RT->isPolymorphic() ||
+ RT->getNumVirtualBaseClasses() != 0)
+ return false;
+
+ for (unsigned I = 0; I < RT->getNumBaseClasses(); ++I) {
+ const Type *BaseTy = RT->getBaseClasses()[I].FieldType;
+ auto *BaseRT = dyn_cast<RecordType>(BaseTy);
+ if (!BaseRT || !isEmptyRecord(BaseRT))
+ return false;
+ }
+
+ for (unsigned I = 0; I < RT->getNumFields(); ++I) {
+ const FieldInfo &FI = RT->getFields()[I];
+
+ if (FI.IsBitField && FI.BitFieldWidth == 0)
+ continue;
+ if (FI.IsUnnamedBitfield)
+ continue;
+
+ if (!isZeroSizedType(FI.FieldType))
+ return false;
+ }
+ return true;
+}
+
+bool TargetInfo::isEmptyField(const FieldInfo &FI) const {
+ if (FI.IsUnnamedBitfield)
+ return true;
+ if (FI.IsBitField && FI.BitFieldWidth == 0)
+ return true;
+
+ const Type *Ty = FI.FieldType;
+ while (auto *AT = dyn_cast<ArrayType>(Ty)) {
+ if (AT->getNumElements() != 1)
+ break;
+ Ty = AT->getElementType();
+ }
+
+ if (auto *RT = dyn_cast<RecordType>(Ty))
+ return isEmptyRecord(RT);
+
+ return isZeroSizedType(Ty);
+}
More information about the llvm-commits
mailing list