llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-codegen

Author: Andy Kaylor (andykaylor)

<details>
<summary>Changes</summary>

This change extends the LLVM ABI library's VectorType to be able to describe 
SVE types and updates Clang's QualTypeMapper to map them.

The AArch64 target info class in the ABI library is still a work in progress. 
It will continue to report "not yet implemented" for function signatures 
involving SVE types. This change is a neceasary prerequisite for correctly 
handling them or correctly deferring handling of these specific types.

Assisted-by: Cursor / claude-opus-5

---

Patch is 27.81 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/221375.diff


8 Files Affected:

- (modified) clang/lib/CodeGen/QualTypeMapper.cpp (+74-4) 
- (modified) clang/lib/CodeGen/QualTypeMapper.h (+1) 
- (modified) clang/unittests/CodeGen/CMakeLists.txt (+3) 
- (added) clang/unittests/CodeGen/QualTypeMapperTest.cpp (+258) 
- (modified) llvm/include/llvm/ABI/Types.h (+71-9) 
- (modified) llvm/lib/ABI/IRTypeMapper.cpp (+10-1) 
- (modified) llvm/unittests/ABI/TypesTest.cpp (+79) 
- (modified) llvm/utils/gn/secondary/clang/unittests/CodeGen/BUILD.gn (+3) 


``````````diff
diff --git a/clang/lib/CodeGen/QualTypeMapper.cpp 
b/clang/lib/CodeGen/QualTypeMapper.cpp
index c095b9394f8e5..fadb0d41a1756 100644
--- a/clang/lib/CodeGen/QualTypeMapper.cpp
+++ b/clang/lib/CodeGen/QualTypeMapper.cpp
@@ -34,6 +34,31 @@
 namespace clang {
 namespace CodeGen {
 
+/// Returns true if \p BT is one of the AArch64 SVE predicate types, i.e.
+/// svbool_t or one of its tuples.
+static bool isSVEPredicateBuiltinType(const BuiltinType *BT) {
+  switch (BT->getKind()) {
+#define SVE_PREDICATE_TYPE(Name, MangledName, Id, SingletonId)                 
\
+  case BuiltinType::Id:                                                        
\
+    return true;
+#include "clang/Basic/AArch64ACLETypes.def"
+  default:
+    return false;
+  }
+}
+
+/// Maps a Clang vector kind onto the ABI library's notion of a vector flavor.
+static llvm::abi::VectorKind getABIVectorKind(clang::VectorKind Kind) {
+  switch (Kind) {
+  case clang::VectorKind::SveFixedLengthData:
+    return llvm::abi::VectorKind::SVEData;
+  case clang::VectorKind::SveFixedLengthPredicate:
+    return llvm::abi::VectorKind::SVEPredicate;
+  default:
+    return llvm::abi::VectorKind::Generic;
+  }
+}
+
 /// 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.
@@ -242,11 +267,27 @@ QualTypeMapper::convertBuiltinType(const BuiltinType *BT) 
{
   case BuiltinType::ObjCSel:
     return createPointerTypeForPointee(QT);
 
-    // Target-specific vector/matrix types — not yet implemented.
-#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
+    // AArch64 SVE data and predicate types, including the x2/x3/x4 tuples.
+#define SVE_VECTOR_TYPE(Name, MangledName, Id, SingletonId)                    
\
+  case BuiltinType::Id:
+#define SVE_PREDICATE_TYPE(Name, MangledName, Id, SingletonId)                 
\
+  case BuiltinType::Id:
 #include "clang/Basic/AArch64ACLETypes.def"
+    return convertSVEBuiltinType(BT);
+
+  case BuiltinType::SveCount:
+    return Builder.getSVECountType(getTypeAlign(QT));
+
+  // TODO: __mfp8 has no floating-point semantics of its own, so representing
+  // it needs a decision about how the ABI library should model opaque
+  // floating-point data. As an mfloat8 vector element it is treated as an
+  // 8-bit integer, but that is not right for the scalar type, which is passed
+  // in a floating-point register.
+  case BuiltinType::MFloat8:
     llvm::reportFatalInternalError(
-        "AArch64 SVE types not yet supported in ABI lowering library");
+        "__mfp8 is not yet supported in the ABI lowering library");
+
+    // Target-specific vector/matrix types — not yet implemented.
 #define PPC_VECTOR_TYPE(Name, Id, Size) case BuiltinType::Id:
 #include "clang/Basic/PPCTypes.def"
     llvm::reportFatalInternalError(
@@ -318,7 +359,36 @@ const llvm::abi::Type 
*QualTypeMapper::convertVectorType(const VectorType *VT) {
   llvm::ElementCount NumElements = llvm::ElementCount::getFixed(NElems);
   llvm::Align VectorAlign = getTypeAlign(VectorQualType);
 
-  return Builder.getVectorType(ElementType, NumElements, VectorAlign);
+  return Builder.getVectorType(ElementType, NumElements, VectorAlign,
+                               getABIVectorKind(VT->getVectorKind()));
+}
+
+/// Converts the sizeless AArch64 SVE data and predicate builtin types,
+/// including the x2/x3/x4 tuples, to scalable LLVM ABI vector types.
+///
+/// \param BT The SVE BuiltinType to convert
+/// \return LLVM ABI VectorType with a scalable element count
+const llvm::abi::Type *
+QualTypeMapper::convertSVEBuiltinType(const BuiltinType *BT) {
+  ASTContext::BuiltinVectorTypeInfo Info = ASTCtx.getBuiltinVectorTypeInfo(BT);
+  assert(Info.NumVectors > 0 && Info.NumVectors <= 4 &&
+         "Expected 1, 2, 3 or 4 vectors!");
+
+  // __mfp8 carries no floating-point semantics, so mfloat8 vectors use an
+  // 8-bit integer element type, which is also how they are represented in
+  // LLVM IR.
+  const llvm::abi::Type *ElementType =
+      Info.ElementType->isMFloat8Type()
+          ? Builder.getIntegerType(8, llvm::Align(1), /*Signed=*/false)
+          : convertType(Info.ElementType);
+
+  llvm::abi::VectorKind VecKind = isSVEPredicateBuiltinType(BT)
+                                      ? llvm::abi::VectorKind::SVEPredicate
+                                      : llvm::abi::VectorKind::SVEData;
+
+  return Builder.getVectorType(ElementType, Info.EC,
+                               getTypeAlign(QualType(BT, 0)), VecKind,
+                               Info.NumVectors);
 }
 
 /// Converts complex types to LLVM ABI complex representations.
diff --git a/clang/lib/CodeGen/QualTypeMapper.h 
b/clang/lib/CodeGen/QualTypeMapper.h
index 35876f44f3aba..f6bb43482c705 100644
--- a/clang/lib/CodeGen/QualTypeMapper.h
+++ b/clang/lib/CodeGen/QualTypeMapper.h
@@ -41,6 +41,7 @@ class QualTypeMapper {
   const llvm::abi::Type *convertBuiltinType(const clang::BuiltinType *BT);
   const llvm::abi::Type *convertArrayType(const clang::ArrayType *AT);
   const llvm::abi::Type *convertVectorType(const clang::VectorType *VT);
+  const llvm::abi::Type *convertSVEBuiltinType(const clang::BuiltinType *BT);
   const llvm::abi::Type *convertRecordType(const clang::RecordType *RT);
   const llvm::abi::Type *convertEnumType(const clang::EnumType *ET);
   const llvm::abi::Type *convertComplexType(const ComplexType *CT);
diff --git a/clang/unittests/CodeGen/CMakeLists.txt 
b/clang/unittests/CodeGen/CMakeLists.txt
index d4efb2230a054..7e2782e09117c 100644
--- a/clang/unittests/CodeGen/CMakeLists.txt
+++ b/clang/unittests/CodeGen/CMakeLists.txt
@@ -4,6 +4,7 @@ add_clang_unittest(ClangCodeGenTests
   DemangleTrapReasonInDebugInfo.cpp
   TBAAMetadataTest.cpp
   CheckTargetFeaturesTest.cpp
+  QualTypeMapperTest.cpp
   CLANG_LIBS
   clangAST
   clangBasic
@@ -12,7 +13,9 @@ add_clang_unittest(ClangCodeGenTests
   clangLex
   clangParse
   clangSerialization
+  clangTesting
   LLVM_COMPONENTS
+  ABI
   Core
   Support
   TargetParser
diff --git a/clang/unittests/CodeGen/QualTypeMapperTest.cpp 
b/clang/unittests/CodeGen/QualTypeMapperTest.cpp
new file mode 100644
index 0000000000000..4e354ab641e05
--- /dev/null
+++ b/clang/unittests/CodeGen/QualTypeMapperTest.cpp
@@ -0,0 +1,258 @@
+//===- QualTypeMapperTest.cpp - Tests for QualType to ABI type 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Tests that QualTypeMapper maps the AArch64 SVE types onto the expected
+/// LLVM ABI type representations.
+///
+//===----------------------------------------------------------------------===//
+
+#include "../../lib/CodeGen/QualTypeMapper.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Type.h"
+#include "clang/Testing/CommandLineArgs.h"
+#include "clang/Testing/TestAST.h"
+#include "llvm/ABI/Types.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/Support/Alignment.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/TypeSize.h"
+#include "gtest/gtest.h"
+
+using namespace clang;
+
+namespace {
+
+/// Parses a translation unit for an AArch64 target, which makes the SVE
+/// builtin types available on the ASTContext, and exposes a QualTypeMapper
+/// over the resulting ASTContext.
+class QualTypeMapperSVETest : public ::testing::Test {
+protected:
+  QualTypeMapperSVETest()
+      : AST(makeInputs()), Mapper(AST.context(), DL, Alloc) {}
+
+  ASTContext &context() { return AST.context(); }
+
+  /// Maps \p QT and returns it as an ABI vector type, or null if it did not
+  /// map to a vector.
+  const llvm::abi::VectorType *mapToVector(QualType QT) {
+    return dyn_cast<llvm::abi::VectorType>(Mapper.convertType(QT));
+  }
+
+  /// Returns the underlying type of the file-scope typedef named \p Name.
+  QualType lookupTypedef(StringRef Name) {
+    for (Decl *D : context().getTranslationUnitDecl()->decls())
+      if (const auto *TD = dyn_cast<TypedefNameDecl>(D))
+        if (TD->getName() == Name)
+          return TD->getUnderlyingType();
+    ADD_FAILURE() << "no typedef named " << Name;
+    return QualType();
+  }
+
+  /// Checks an SVE data vector of \p NF vectors of \p NumEls elements, each
+  /// \p ElBits wide. \p IsFP selects whether the element is expected to be a
+  /// floating-point or an integer type.
+  void checkDataVector(StringRef Name, QualType QT, unsigned NumEls,
+                       unsigned ElBits, unsigned NF, bool IsFP) {
+    SCOPED_TRACE(Name);
+    const llvm::abi::VectorType *VT = mapToVector(QT);
+    ASSERT_NE(VT, nullptr) << "did not map to a vector type";
+
+    EXPECT_EQ(VT->getVectorKind(), llvm::abi::VectorKind::SVEData);
+    EXPECT_TRUE(VT->isScalable());
+    EXPECT_EQ(VT->getNumElements(), llvm::ElementCount::getScalable(NumEls));
+    EXPECT_EQ(VT->getNumVectors(), NF);
+    EXPECT_EQ(VT->isTuple(), NF > 1);
+    EXPECT_EQ(VT->getSizeInBits(),
+              llvm::TypeSize::getScalable(NumEls * ElBits * NF));
+    // AAPCS64 aligns every SVE data vector, including the tuples, to 16 bytes.
+    EXPECT_EQ(VT->getAlignment(), llvm::Align(16));
+
+    const llvm::abi::Type *Elt = VT->getElementType();
+    EXPECT_EQ(Elt->getSizeInBits(), llvm::TypeSize::getFixed(ElBits));
+    EXPECT_EQ(Elt->isFloat(), IsFP);
+    EXPECT_EQ(Elt->isInteger(), !IsFP);
+  }
+
+  /// Checks an SVE predicate vector of \p NF vectors of \p NumEls elements.
+  void checkPredicateVector(StringRef Name, QualType QT, unsigned NumEls,
+                            unsigned NF) {
+    SCOPED_TRACE(Name);
+    const llvm::abi::VectorType *VT = mapToVector(QT);
+    ASSERT_NE(VT, nullptr) << "did not map to a vector type";
+
+    EXPECT_EQ(VT->getVectorKind(), llvm::abi::VectorKind::SVEPredicate);
+    EXPECT_TRUE(VT->isScalable());
+    EXPECT_EQ(VT->getNumElements(), llvm::ElementCount::getScalable(NumEls));
+    EXPECT_EQ(VT->getNumVectors(), NF);
+    EXPECT_EQ(VT->getSizeInBits(), llvm::TypeSize::getScalable(NumEls * NF));
+    EXPECT_EQ(VT->getAlignment(), llvm::Align(2));
+
+    const llvm::abi::Type *Elt = VT->getElementType();
+    ASSERT_TRUE(Elt->isInteger());
+    EXPECT_EQ(Elt->getSizeInBits(), llvm::TypeSize::getFixed(1));
+  }
+
+private:
+  static TestInputs makeInputs() {
+    TestInputs Inputs(R"c(
+typedef __SVInt32_t fixed_int32_t __attribute__((arm_sve_vector_bits(256)));
+typedef __SVBool_t fixed_bool_t __attribute__((arm_sve_vector_bits(256)));
+typedef int generic_int32x4_t __attribute__((vector_size(16)));
+)c");
+    Inputs.Language = TestLanguage::Lang_C99;
+    // The fixed-length SVE typedefs require a known vector length, which must
+    // agree with the width in the attribute.
+    Inputs.ExtraArgs = {"-triple",         "aarch64-unknown-linux-gnu",
+                        "-target-feature", "+sve",
+                        "-mvscale-min=2",  "-mvscale-max=2"};
+    return Inputs;
+  }
+
+  TestAST AST;
+  llvm::DataLayout DL;
+  llvm::BumpPtrAllocator Alloc;
+  CodeGen::QualTypeMapper Mapper;
+};
+
+// Every SVE data vector, including the x2/x3/x4 tuples, maps to a scalable
+// vector tagged as SVE data.
+TEST_F(QualTypeMapperSVETest, DataVectors) {
+#define SVE_VECTOR_TYPE_INT(Name, MangledName, Id, SingletonId, NumEls,        
\
+                            ElBits, NF, IsSigned)                              
\
+  checkDataVector(#Name, context().SingletonId, NumEls, ElBits, NF,            
\
+                  /*IsFP=*/false);
+#define SVE_VECTOR_TYPE_FLOAT(Name, MangledName, Id, SingletonId, NumEls,      
\
+                              ElBits, NF)                                      
\
+  checkDataVector(#Name, context().SingletonId, NumEls, ElBits, NF,            
\
+                  /*IsFP=*/true);
+#define SVE_VECTOR_TYPE_BFLOAT(Name, MangledName, Id, SingletonId, NumEls,     
\
+                               ElBits, NF)                                     
\
+  checkDataVector(#Name, context().SingletonId, NumEls, ElBits, NF,            
\
+                  /*IsFP=*/true);
+  // mfloat8 vectors use an integer element, since __mfp8 has no
+  // floating-point semantics of its own.
+#define SVE_VECTOR_TYPE_MFLOAT(Name, MangledName, Id, SingletonId, NumEls,     
\
+                               ElBits, NF)                                     
\
+  checkDataVector(#Name, context().SingletonId, NumEls, ElBits, NF,            
\
+                  /*IsFP=*/false);
+#include "clang/Basic/AArch64ACLETypes.def"
+}
+
+// Every SVE predicate, including the x2/x4 tuples, maps to a scalable vector
+// of one-bit elements tagged as an SVE predicate.
+TEST_F(QualTypeMapperSVETest, PredicateVectors) {
+#define SVE_PREDICATE_TYPE_ALL(Name, MangledName, Id, SingletonId, NumEls, NF) 
\
+  checkPredicateVector(#Name, context().SingletonId, NumEls, NF);
+#include "clang/Basic/AArch64ACLETypes.def"
+}
+
+// Spot-check a few representative types against their IR spellings, so that
+// the macro-driven tests above are anchored to concrete expectations.
+TEST_F(QualTypeMapperSVETest, RepresentativeTypes) {
+  // svint8_t is <vscale x 16 x i8>.
+  const llvm::abi::VectorType *SVInt8 = mapToVector(context().SveInt8Ty);
+  ASSERT_NE(SVInt8, nullptr);
+  EXPECT_EQ(SVInt8->getNumElements(), llvm::ElementCount::getScalable(16));
+  EXPECT_EQ(SVInt8->getSizeInBits(), llvm::TypeSize::getScalable(128));
+  EXPECT_TRUE(
+      cast<llvm::abi::IntegerType>(SVInt8->getElementType())->isSigned());
+
+  // svuint8_t has the same shape but an unsigned element.
+  const llvm::abi::VectorType *SVUint8 = mapToVector(context().SveUint8Ty);
+  ASSERT_NE(SVUint8, nullptr);
+  EXPECT_FALSE(
+      cast<llvm::abi::IntegerType>(SVUint8->getElementType())->isSigned());
+
+  // svfloat64x2_t is two <vscale x 2 x double> vectors.
+  const llvm::abi::VectorType *SVFloat64x2 =
+      mapToVector(context().SveFloat64x2Ty);
+  ASSERT_NE(SVFloat64x2, nullptr);
+  EXPECT_EQ(SVFloat64x2->getNumVectors(), 2u);
+  EXPECT_EQ(SVFloat64x2->getNumElements(), llvm::ElementCount::getScalable(2));
+  EXPECT_EQ(SVFloat64x2->getSizeInBits(), llvm::TypeSize::getScalable(256));
+
+  // svbool_t is <vscale x 16 x i1>.
+  const llvm::abi::VectorType *SVBool = mapToVector(context().SveBoolTy);
+  ASSERT_NE(SVBool, nullptr);
+  EXPECT_EQ(SVBool->getNumElements(), llvm::ElementCount::getScalable(16));
+  EXPECT_EQ(SVBool->getSizeInBits(), llvm::TypeSize::getScalable(16));
+}
+
+// __mfp8 has no floating-point semantics, so mfloat8 vectors use an 8-bit
+// integer element. That makes svmfloat8_t share a representation with
+// svuint8_t, which is also how the two are represented in LLVM IR.
+TEST_F(QualTypeMapperSVETest, MFloat8VectorUsesIntegerElement) {
+  const llvm::abi::VectorType *SVMFloat8 = mapToVector(context().SveMFloat8Ty);
+  ASSERT_NE(SVMFloat8, nullptr);
+
+  EXPECT_EQ(SVMFloat8->getVectorKind(), llvm::abi::VectorKind::SVEData);
+  EXPECT_EQ(SVMFloat8->getNumElements(), llvm::ElementCount::getScalable(16));
+
+  const auto *Elt =
+      dyn_cast<llvm::abi::IntegerType>(SVMFloat8->getElementType());
+  ASSERT_NE(Elt, nullptr);
+  EXPECT_EQ(Elt->getSizeInBits(), llvm::TypeSize::getFixed(8));
+  EXPECT_FALSE(Elt->isSigned());
+}
+
+// __SVCount_t is opaque, and is given the shape of svbool_t because it
+// occupies a predicate register.
+TEST_F(QualTypeMapperSVETest, SVECount) {
+  const llvm::abi::VectorType *SVCount = mapToVector(context().SveCountTy);
+  ASSERT_NE(SVCount, nullptr);
+
+  EXPECT_EQ(SVCount->getVectorKind(), llvm::abi::VectorKind::SVECount);
+  EXPECT_TRUE(SVCount->isSVEType());
+  EXPECT_FALSE(SVCount->isSVEPredicate());
+  EXPECT_TRUE(SVCount->isScalable());
+  EXPECT_FALSE(SVCount->isTuple());
+  EXPECT_EQ(SVCount->getNumElements(), llvm::ElementCount::getScalable(16));
+  EXPECT_EQ(SVCount->getSizeInBits(), llvm::TypeSize::getScalable(16));
+  EXPECT_EQ(SVCount->getAlignment(), llvm::Align(2));
+}
+
+// The arm_sve_vector_bits types are fixed-length, but they still have to be
+// distinguishable from an ordinary vector of the same shape.
+TEST_F(QualTypeMapperSVETest, FixedLengthSVEVectors) {
+  const llvm::abi::VectorType *FixedInt32 =
+      mapToVector(lookupTypedef("fixed_int32_t"));
+  ASSERT_NE(FixedInt32, nullptr);
+  EXPECT_EQ(FixedInt32->getVectorKind(), llvm::abi::VectorKind::SVEData);
+  EXPECT_FALSE(FixedInt32->isScalable());
+  EXPECT_FALSE(FixedInt32->isTuple());
+  EXPECT_EQ(FixedInt32->getNumElements(), llvm::ElementCount::getFixed(8));
+  EXPECT_EQ(FixedInt32->getSizeInBits(), llvm::TypeSize::getFixed(256));
+
+  // Clang derives the element count of a fixed-length predicate by dividing
+  // the vector length in bits by the square of the char width, so a 256-bit
+  // vector length gives 4 elements.
+  const llvm::abi::VectorType *FixedBool =
+      mapToVector(lookupTypedef("fixed_bool_t"));
+  ASSERT_NE(FixedBool, nullptr);
+  EXPECT_EQ(FixedBool->getVectorKind(), llvm::abi::VectorKind::SVEPredicate);
+  EXPECT_FALSE(FixedBool->isScalable());
+  EXPECT_EQ(FixedBool->getNumElements(), llvm::ElementCount::getFixed(4));
+}
+
+// An ordinary vector must not be mistaken for an SVE type.
+TEST_F(QualTypeMapperSVETest, PlainVectorIsGeneric) {
+  const llvm::abi::VectorType *Int32x4 =
+      mapToVector(lookupTypedef("generic_int32x4_t"));
+  ASSERT_NE(Int32x4, nullptr);
+
+  EXPECT_EQ(Int32x4->getVectorKind(), llvm::abi::VectorKind::Generic);
+  EXPECT_FALSE(Int32x4->isSVEType());
+  EXPECT_FALSE(Int32x4->isScalable());
+  EXPECT_EQ(Int32x4->getNumElements(), llvm::ElementCount::getFixed(4));
+  EXPECT_EQ(Int32x4->getSizeInBits(), llvm::TypeSize::getFixed(128));
+}
+
+} // namespace
diff --git a/llvm/include/llvm/ABI/Types.h b/llvm/include/llvm/ABI/Types.h
index 88b99e9e095d3..d04bd765ab5e6 100644
--- a/llvm/include/llvm/ABI/Types.h
+++ b/llvm/include/llvm/ABI/Types.h
@@ -81,7 +81,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; }
+  bool isZeroSize() const { return getSizeInBits().isZero(); }
 };
 
 class VoidType : public Type {
@@ -209,23 +209,73 @@ class ArrayType : public Type {
   static bool classof(const Type *T) { return T->getKind() == TypeKind::Array; 
}
 };
 
+/// Distinguishes the vector flavors that ABIs have to treat differently.
+/// Scalability is not part of the kind. It is tracked by the vector's
+/// ElementCount, because some flavors have both a scalable and a
+/// fixed-length spelling.
+enum class VectorKind {
+  /// A plain vector, such as a Neon vector or a GCC vector_size vector.
+  Generic,
+
+  /// An AArch64 SVE data vector, such as svint32_t or svfloat64x2_t. Data
+  /// vectors are passed in Z registers.
+  SVEData,
+
+  /// An AArch64 SVE predicate vector, such as svbool_t or svboolx4_t.
+  /// Predicate vectors have one-bit elements and are passed in P registers.
+  SVEPredicate,
+
+  /// The AArch64 __SVCount_t type. It is opaque rather than a real vector,
+  /// but it occupies a predicate register, so it is given the same shape as
+  /// svbool_t.
+  SVECount,
+};
+
 class VectorType : public Type {
 private:
   const Type *ElementType;
   ElementCount NumElements;
+  VectorKind VecKind;
+  unsigned NumVectors;
+
+  static TypeSize computeSizeInBits(const Type *ElementType,
+                                    ElementCount NumElements,
+                                    unsigned NumVectors) {
+    return TypeSize(ElementType->getSizeInBits().getFixedValue() *
+                        NumElements.getKnownMinValue() * NumVectors,
+                    NumElements.isScalable());
+  }
 
 public:
-  VectorType(const Type *ElementType, ElementCount NumElements, Align ABIAlign)
+  VectorType(const Type *ElementType, ElementCount NumElements, Align ABIAlign,
+             VectorKind VecKind = VectorKind::Generic, unsigned NumVectors = 1)
       : Type(TypeKind::Vector,
-             TypeSize(ElementType->getSizeInBits().getFixedValue() *
-                          NumElements.getKnownMinValue(),
-               ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/221375
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to