Skip to content

Commit

Permalink
[Clang] Create opaque type for AArch64 SVE2p1/SME2 svcount_t.
Browse files Browse the repository at this point in the history
This patch adds the builtin type __SVCount_t to Clang, which is an opaque
scalable type defined in the SME2 C and C++ Language Extensions.

The type maps to the `target("aarch64.svcount")` LLVM IR type.

Reviewed By: paulwalker-arm

Differential Revision: https://reviews.llvm.org/D136864
  • Loading branch information
sdesmalen-arm committed Mar 7, 2023
1 parent f04a859 commit 07158c5
Show file tree
Hide file tree
Showing 12 changed files with 96 additions and 15 deletions.
2 changes: 2 additions & 0 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -2700,6 +2700,8 @@ class BuiltinType : public Type {

bool isSVEBool() const { return getKind() == Kind::SveBool; }

bool isSVECount() const { return getKind() == Kind::SveCount; }

/// Determines whether the given kind corresponds to a placeholder type.
static bool isPlaceholderTypeKind(Kind K) {
return K >= Overload;
Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/Basic/AArch64SVEACLETypes.def
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@
SVE_TYPE(Name, Id, SingletonId)
#endif

#ifndef SVE_OPAQUE_TYPE
#define SVE_OPAQUE_TYPE(Name, MangledName, Id, SingletonId) \
SVE_TYPE(Name, Id, SingletonId)
#endif

//===- Vector point types -----------------------------------------------===//


Expand Down Expand Up @@ -125,6 +130,9 @@ SVE_VECTOR_TYPE("__clang_svbfloat16x4_t", "svbfloat16x4_t", SveBFloat16x4, SveBF

SVE_PREDICATE_TYPE("__SVBool_t", "__SVBool_t", SveBool, SveBoolTy, 16)

SVE_OPAQUE_TYPE("__SVCount_t", "__SVCount_t", SveCount, SveCountTy)

#undef SVE_VECTOR_TYPE
#undef SVE_PREDICATE_TYPE
#undef SVE_OPAQUE_TYPE
#undef SVE_TYPE
13 changes: 10 additions & 3 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2322,6 +2322,11 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
Width = 0; \
Align = 16; \
break;
#define SVE_OPAQUE_TYPE(Name, MangledName, Id, SingletonId) \
case BuiltinType::Id: \
Width = 0; \
Align = 16; \
break;
#include "clang/Basic/AArch64SVEACLETypes.def"
#define PPC_VECTOR_TYPE(Name, Id, Size) \
case BuiltinType::Id: \
Expand Down Expand Up @@ -4119,6 +4124,7 @@ QualType ASTContext::getScalableVectorType(QualType EltTy,
#define SVE_PREDICATE_TYPE(Name, MangledName, Id, SingletonId, NumEls) \
if (EltTy->isBooleanType() && NumElts == NumEls) \
return SingletonId;
#define SVE_OPAQUE_TYPE(Name, MangledName, Id, SingleTonId)
#include "clang/Basic/AArch64SVEACLETypes.def"
} else if (Target->hasRISCVVTypes()) {
uint64_t EltTySize = getTypeSize(EltTy);
Expand Down Expand Up @@ -9549,9 +9555,10 @@ bool ASTContext::areCompatibleVectorTypes(QualType FirstVec,
/// getSVETypeSize - Return SVE vector or predicate register size.
static uint64_t getSVETypeSize(ASTContext &Context, const BuiltinType *Ty) {
assert(Ty->isVLSTBuiltinType() && "Invalid SVE Type");
return Ty->getKind() == BuiltinType::SveBool
? (Context.getLangOpts().VScaleMin * 128) / Context.getCharWidth()
: Context.getLangOpts().VScaleMin * 128;
if (Ty->getKind() == BuiltinType::SveBool ||
Ty->getKind() == BuiltinType::SveCount)
return (Context.getLangOpts().VScaleMin * 128) / Context.getCharWidth();
return Context.getLangOpts().VScaleMin * 128;
}

bool ASTContext::areCompatibleSveTypes(QualType FirstType,
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3217,6 +3217,12 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
Out << (type_name == InternalName ? "u" : "") << type_name.size() \
<< type_name; \
break;
#define SVE_OPAQUE_TYPE(InternalName, MangledName, Id, SingletonId) \
case BuiltinType::Id: \
type_name = MangledName; \
Out << (type_name == InternalName ? "u" : "") << type_name.size() \
<< type_name; \
break;
#include "clang/Basic/AArch64SVEACLETypes.def"
#define PPC_VECTOR_TYPE(Name, Id, Size) \
case BuiltinType::Id: \
Expand Down
41 changes: 29 additions & 12 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -727,24 +727,41 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
#include "clang/Basic/AArch64SVEACLETypes.def"
{
ASTContext::BuiltinVectorTypeInfo Info =
CGM.getContext().getBuiltinVectorTypeInfo(BT);
unsigned NumElemsPerVG = (Info.EC.getKnownMinValue() * Info.NumVectors) / 2;
// For svcount_t, only the lower 2 bytes are relevant.
BT->getKind() == BuiltinType::SveCount
? ASTContext::BuiltinVectorTypeInfo(
CGM.getContext().BoolTy, llvm::ElementCount::getFixed(16),
1)
: CGM.getContext().getBuiltinVectorTypeInfo(BT);

// A single vector of bytes may not suffice as the representation of
// svcount_t tuples because of the gap between the active 16bits of
// successive tuple members. Currently no such tuples are defined for
// svcount_t, so assert that NumVectors is 1.
assert((BT->getKind() != BuiltinType::SveCount || Info.NumVectors == 1) &&
"Unsupported number of vectors for svcount_t");

// Debuggers can't extract 1bit from a vector, so will display a
// bitpattern for svbool_t instead.
// bitpattern for predicates instead.
unsigned NumElems = Info.EC.getKnownMinValue() * Info.NumVectors;
if (Info.ElementType == CGM.getContext().BoolTy) {
NumElemsPerVG /= 8;
NumElems /= 8;
Info.ElementType = CGM.getContext().UnsignedCharTy;
}

auto *LowerBound =
llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned(
llvm::Type::getInt64Ty(CGM.getLLVMContext()), 0));
SmallVector<uint64_t, 9> Expr(
{llvm::dwarf::DW_OP_constu, NumElemsPerVG, llvm::dwarf::DW_OP_bregx,
/* AArch64::VG */ 46, 0, llvm::dwarf::DW_OP_mul,
llvm::dwarf::DW_OP_constu, 1, llvm::dwarf::DW_OP_minus});
auto *UpperBound = DBuilder.createExpression(Expr);
llvm::Metadata *LowerBound, *UpperBound;
LowerBound = llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned(
llvm::Type::getInt64Ty(CGM.getLLVMContext()), 0));
if (Info.EC.isScalable()) {
unsigned NumElemsPerVG = NumElems / 2;
SmallVector<uint64_t, 9> Expr(
{llvm::dwarf::DW_OP_constu, NumElemsPerVG, llvm::dwarf::DW_OP_bregx,
/* AArch64::VG */ 46, 0, llvm::dwarf::DW_OP_mul,
llvm::dwarf::DW_OP_constu, 1, llvm::dwarf::DW_OP_minus});
UpperBound = DBuilder.createExpression(Expr);
} else
UpperBound = llvm::ConstantAsMetadata::get(llvm::ConstantInt::getSigned(
llvm::Type::getInt64Ty(CGM.getLLVMContext()), NumElems - 1));

llvm::Metadata *Subscript = DBuilder.getOrCreateSubrange(
/*count*/ nullptr, LowerBound, UpperBound, /*stride*/ nullptr);
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/CodeGen/CodeGenTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,8 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
Info.EC.getKnownMinValue() *
Info.NumVectors);
}
case BuiltinType::SveCount:
return llvm::TargetExtType::get(getLLVMContext(), "aarch64.svcount");
#define PPC_VECTOR_TYPE(Name, Id, Size) \
case BuiltinType::Id: \
ResultType = \
Expand Down
3 changes: 3 additions & 0 deletions clang/test/AST/ast-dump-aarch64-sve-types.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,6 @@

// CHECK: TypedefDecl {{.*}} implicit __SVBool_t '__SVBool_t'
// CHECK-NEXT: -BuiltinType {{.*}} '__SVBool_t'

// CHECK: TypedefDecl {{.*}} implicit __SVCount_t '__SVCount_t'
// CHECK-NEXT: -BuiltinType {{.*}} '__SVCount_t'
6 changes: 6 additions & 0 deletions clang/test/CodeGen/aarch64-debug-sve-vector-types.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ void test_locals(void) {
// CHECK-DAG: ![[REALELTS1_64]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 1, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus))
__SVBool_t b8;

// CHECK-DAG: name: "__SVCount_t",{{.*}}, baseType: ![[CT1_2:[0-9]+]]
// CHECK-DAG: ![[CT1_2]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTYU8]], flags: DIFlagVector, elements: ![[ELTS0_to_1:[0-9]+]])
// CHECK-DAG: ![[ELTS0_to_1]] = !{![[REALELTS0_to_1:[0-9]+]]}
// CHECK-DAG: ![[REALELTS0_to_1]] = !DISubrange(lowerBound: 0, upperBound: 1)
__SVCount_t c8;

// CHECK-DAG: name: "__SVInt8_t",{{.*}}, baseType: ![[CT8:[0-9]+]]
// CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTYS8:[0-9]+]], flags: DIFlagVector, elements: ![[ELTS8:[0-9]+]])
// CHECK-DAG: ![[ELTTYS8]] = !DIBasicType(name: "signed char", size: 8, encoding: DW_ATE_signed_char)
Expand Down
12 changes: 12 additions & 0 deletions clang/test/CodeGen/aarch64-sve-inline-asm-crash.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,17 @@ __SVBool_t funcB1(__SVBool_t in)
return ret ;
}

__SVCount_t funcB1(__SVCount_t in)
{
__SVCount_t ret ;
asm volatile (
"mov %[ret].b, %[in].b \n"
: [ret] "=w" (ret)
: [in] "w" (in)
:);

return ret ;
}

// CHECK: funcB1
// CHECK-ERROR: fatal error: error in backend: Cannot select
2 changes: 2 additions & 0 deletions clang/test/CodeGenCXX/aarch64-mangle-sve-vectors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ void f11(S<__SVFloat64_t>) {}
void f12(S<__SVBFloat16_t>) {}
// CHECK: _Z3f131SIu10__SVBool_tE
void f13(S<__SVBool_t>) {}
// CHECK: _Z3f141SIu11__SVCount_tE
void f14(S<__SVCount_t>) {}

// The tuple types don't use the internal name for mangling.

Expand Down
4 changes: 4 additions & 0 deletions clang/test/CodeGenCXX/aarch64-sve-typeinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ auto &f64 = typeid(__SVFloat64_t);
auto &bf16 = typeid(__SVBFloat16_t);

auto &b8 = typeid(__SVBool_t);
auto &c8 = typeid(__SVCount_t);

// CHECK-DAG: @_ZTSu10__SVInt8_t = {{.*}} c"u10__SVInt8_t\00"
// CHECK-DAG: @_ZTIu10__SVInt8_t = {{.*}} @_ZTVN10__cxxabiv123__fundamental_type_infoE, {{.*}} @_ZTSu10__SVInt8_t
Expand Down Expand Up @@ -61,3 +62,6 @@ auto &b8 = typeid(__SVBool_t);

// CHECK-DAG: @_ZTSu10__SVBool_t = {{.*}} c"u10__SVBool_t\00"
// CHECK-DAG: @_ZTIu10__SVBool_t = {{.*}} @_ZTVN10__cxxabiv123__fundamental_type_infoE, {{.*}} @_ZTSu10__SVBool_t

// CHECK-DAG: @_ZTSu11__SVCount_t = {{.*}} c"u11__SVCount_t\00"
// CHECK-DAG: @_ZTIu11__SVCount_t = {{.*}} @_ZTVN10__cxxabiv123__fundamental_type_infoE, {{.*}} @_ZTSu11__SVCount_t
12 changes: 12 additions & 0 deletions clang/unittests/AST/SizelessTypesTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ TEST_F(SizelessTypeTester, TestSizelessBuiltin) {
ASSERT_TRUE(Ctx.SveBFloat16Ty->isSizelessBuiltinType());

ASSERT_TRUE(Ctx.SveBoolTy->isSizelessBuiltinType());
ASSERT_TRUE(Ctx.SveCountTy->isSizelessBuiltinType());

ASSERT_FALSE(Ctx.VoidTy->isSizelessBuiltinType());
ASSERT_FALSE(Ctx.PseudoObjectTy->isSizelessBuiltinType());
Expand All @@ -55,6 +56,12 @@ TEST_F(SizelessTypeTester, TestSizelessBuiltin) {
Ctx.getLValueReferenceType(Ctx.SveBoolTy)->isSizelessBuiltinType());
ASSERT_FALSE(
Ctx.getRValueReferenceType(Ctx.SveBoolTy)->isSizelessBuiltinType());

ASSERT_FALSE(Ctx.getPointerType(Ctx.SveCountTy)->isSizelessBuiltinType());
ASSERT_FALSE(
Ctx.getLValueReferenceType(Ctx.SveCountTy)->isSizelessBuiltinType());
ASSERT_FALSE(
Ctx.getRValueReferenceType(Ctx.SveCountTy)->isSizelessBuiltinType());
}

TEST_F(SizelessTypeTester, TestSizeless) {
Expand All @@ -75,6 +82,7 @@ TEST_F(SizelessTypeTester, TestSizeless) {
ASSERT_TRUE(Ctx.SveBFloat16Ty->isSizelessType());

ASSERT_TRUE(Ctx.SveBoolTy->isSizelessType());
ASSERT_TRUE(Ctx.SveCountTy->isSizelessType());

ASSERT_FALSE(Ctx.VoidTy->isSizelessType());
ASSERT_FALSE(Ctx.PseudoObjectTy->isSizelessType());
Expand All @@ -83,4 +91,8 @@ TEST_F(SizelessTypeTester, TestSizeless) {
ASSERT_FALSE(Ctx.getPointerType(Ctx.SveBoolTy)->isSizelessType());
ASSERT_FALSE(Ctx.getLValueReferenceType(Ctx.SveBoolTy)->isSizelessType());
ASSERT_FALSE(Ctx.getRValueReferenceType(Ctx.SveBoolTy)->isSizelessType());

ASSERT_FALSE(Ctx.getPointerType(Ctx.SveCountTy)->isSizelessType());
ASSERT_FALSE(Ctx.getLValueReferenceType(Ctx.SveCountTy)->isSizelessType());
ASSERT_FALSE(Ctx.getRValueReferenceType(Ctx.SveCountTy)->isSizelessType());
}

2 comments on commit 07158c5

@kazutakahirata
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This patch seems to trigger:

lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp:4832:13: error: enumeration value 'SveCount' not handled in switch [-Werror,-Wswitch]
    switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.

with clang-14.0.6 as the host compiler. How should I go about fixing the problem? Should I treat the missing case value SveCount the same way as clang::BuiltinType::SveBool is treated? Thanks!

@kazutakahirata
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5195e14 has fixed the problem.

Please sign in to comment.