[llvm] [llvm] Introduce TargetInfo (PR #190730)

via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 14 11:57:27 PDT 2026


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

>From b7b3f347cf33bca48bf02a046d28089a25253deb 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 | 89 ++++++++++++++++++++++++++++++
 llvm/include/llvm/ABI/Types.h      | 46 +++++++++++++++
 llvm/lib/ABI/CMakeLists.txt        |  1 +
 llvm/lib/ABI/TargetInfo.cpp        | 46 +++++++++++++++
 4 files changed, 182 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..8c42fc8c4de01
--- /dev/null
+++ b/llvm/include/llvm/ABI/TargetInfo.h
@@ -0,0 +1,89 @@
+//===----- 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>
+
+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;
+
+  /// Populate FI with the target's ABI-lowering decisions for each argument
+  /// and return value.
+  virtual void computeInfo(FunctionInfo &FI) const = 0;
+  virtual bool isPassByRef(const Type *Ty) const { return false; }
+  const ABICompatInfo &getABICompatInfo() const { return CompatInfo; }
+
+protected:
+  RecordArgABI getRecordArgABI(const RecordType *RT) const;
+  RecordArgABI getRecordArgABI(const Type *Ty) const;
+  bool isPromotableInteger(const IntegerType *IT) const;
+  ArgInfo getNaturalAlignIndirect(const Type *Ty, bool ByVal = true) const;
+  bool isAggregateTypeForABI(const Type *Ty) const;
+};
+
+// TODO: Add factory functions for supported targets here.
+
+} // namespace abi
+} // namespace llvm
+
+#endif // LLVM_ABI_TARGETINFO_H
diff --git a/llvm/include/llvm/ABI/Types.h b/llvm/include/llvm/ABI/Types.h
index e3c9419b6bdee..a69dc5ceadfa1 100644
--- a/llvm/include/llvm/ABI/Types.h
+++ b/llvm/include/llvm/ABI/Types.h
@@ -82,6 +82,7 @@ class Type {
   bool isRecord() const { return Kind == TypeKind::Record; }
   bool isMemberPointer() const { return Kind == TypeKind::MemberPointer; }
   bool isComplex() const { return Kind == TypeKind::Complex; }
+  bool isZeroSize() const { return getSizeInBits().getFixedValue() == 0; }
 };
 
 class VoidType : public Type {
@@ -244,6 +245,8 @@ struct FieldInfo {
       : FieldType(FieldType), OffsetInBits(OffsetInBits),
         BitFieldWidth(BitFieldWidth), IsBitField(IsBitField),
         IsUnnamedBitfield(IsUnnamedBitField) {}
+
+  bool isEmpty() const;
 };
 
 enum class StructPacking { Default, Packed, ExplicitPacking };
@@ -306,6 +309,12 @@ class RecordType : public Type {
   ArrayRef<FieldInfo> getVirtualBaseClasses() const {
     return VirtualBaseClasses;
   }
+
+  bool isEmpty() const;
+
+  static bool classof(const Type *T) {
+    return T->getKind() == TypeKind::Record;
+  }
 };
 
 /// TypeBuilder manages the lifecycle of ABI types using bump pointer
@@ -425,6 +434,43 @@ class TypeBuilder {
   }
 };
 
+inline bool RecordType::isEmpty() const {
+  if (hasFlexibleArrayMember() || isPolymorphic() ||
+      getNumVirtualBaseClasses() != 0)
+    return false;
+
+  for (const FieldInfo &Base : getBaseClasses()) {
+    const auto *BaseRT = dyn_cast<RecordType>(Base.FieldType);
+    if (!BaseRT || !BaseRT->isEmpty())
+      return false;
+  }
+
+  for (const FieldInfo &FI : getFields()) {
+    if (!FI.isEmpty())
+      return false;
+  }
+  return true;
+}
+
+inline bool FieldInfo::isEmpty() const {
+  if (IsUnnamedBitfield)
+    return true;
+  if (IsBitField && BitFieldWidth == 0)
+    return true;
+
+  const Type *Ty = FieldType;
+  while (const auto *AT = dyn_cast<ArrayType>(Ty)) {
+    if (AT->getNumElements() != 1)
+      break;
+    Ty = AT->getElementType();
+  }
+
+  if (const auto *RT = dyn_cast<RecordType>(Ty))
+    return RT->isEmpty();
+
+  return Ty->isZeroSize();
+}
+
 } // namespace abi
 } // namespace llvm
 
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..046c3843ca2a9
--- /dev/null
+++ b/llvm/lib/ABI/TargetInfo.cpp
@@ -0,0 +1,46 @@
+//===- 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 Type *Ty) const {
+  // TODO: When Microsoft ABI is supported, CXX records may need different
+  // handling here (see MicrosoftCXXABI::getRecordArgABI in Clang).
+  const RecordType *RT = dyn_cast<RecordType>(Ty);
+  if (!RT)
+    return RAA_Default;
+  return getRecordArgABI(RT);
+}



More information about the llvm-commits mailing list