[clang] [HLSL] add IsLineVectorLayoutCompatible type trait (PR #113730)
Joshua Batista via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 25 14:01:56 PDT 2024
https://github.com/bob80905 updated https://github.com/llvm/llvm-project/pull/113730
>From a915def0c7cb69d8c910c697aa610fa37278d032 Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Fri, 25 Oct 2024 12:33:05 -0700
Subject: [PATCH 1/2] add type trait
---
.../clang/AST/CXXRecordDeclDefinitionBits.def | 5 +
clang/include/clang/AST/DeclCXX.h | 5 +
clang/include/clang/AST/Type.h | 8 ++
clang/include/clang/Basic/TokenKinds.def | 1 +
clang/include/clang/Sema/SemaHLSL.h | 1 +
clang/lib/AST/DeclCXX.cpp | 6 +-
clang/lib/Sema/SemaExprCXX.cpp | 10 ++
clang/lib/Sema/SemaHLSL.cpp | 43 ++++++++
.../IsLineVectorLayoutCompatibleType.hlsl | 101 ++++++++++++++++++
...IsLineVectorLayoutCompatibleTypeErros.hlsl | 10 ++
10 files changed, 189 insertions(+), 1 deletion(-)
create mode 100644 clang/test/SemaHLSL/Types/Traits/IsLineVectorLayoutCompatibleType.hlsl
create mode 100644 clang/test/SemaHLSL/Types/Traits/IsLineVectorLayoutCompatibleTypeErros.hlsl
diff --git a/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def b/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def
index 6620840df0ced2..0411b244ed5eef 100644
--- a/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def
+++ b/clang/include/clang/AST/CXXRecordDeclDefinitionBits.def
@@ -253,4 +253,9 @@ FIELD(IsAnyDestructorNoReturn, 1, NO_MERGE)
/// type that is intangible). HLSL only.
FIELD(IsHLSLIntangible, 1, NO_MERGE)
+/// Whether the record type is line vector layout compatible (that is,
+/// it has at most 4 elements, does not exceed 16 bytes, is homogenous,
+/// and does not contain any bool or enum types)
+FIELD(IsHLSLLineVectorLayoutCompatible, 1, NO_MERGE)
+
#undef FIELD
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index 2693cc0e95b4b2..e2e4ed78195a81 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -1551,6 +1551,11 @@ class CXXRecordDecl : public RecordDecl {
/// a field or in base class.
bool isHLSLIntangible() const { return data().IsHLSLIntangible; }
+ /// Returns true if the class is line vector layout compatible
+ bool isHLSLLineVectorLayoutCompatible() const {
+ return data().IsHLSLLineVectorLayoutCompatible;
+ }
+
/// If the class is a local class [class.local], returns
/// the enclosing function declaration.
const FunctionDecl *isLocalClass() const {
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 40e617bf8f3b8d..1f2d5cecde4e18 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -2662,6 +2662,8 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
#include "clang/Basic/HLSLIntangibleTypes.def"
bool isHLSLSpecificType() const; // Any HLSL specific type
bool isHLSLIntangibleType() const; // Any HLSL intangible type
+ bool isHLSLLineVectorLayoutCompatibleType()
+ const; // Any HLSL line vector layout compatible type
bool isHLSLAttributedResourceType() const;
/// Determines if this type, which must satisfy
@@ -8457,6 +8459,12 @@ inline bool Type::isHLSLIntangibleType() const {
isHLSLAttributedResourceType();
}
+inline bool Type::isHLSLLineVectorLayoutCompatibleType() const {
+#define HLSL_LINE_VECTOR_LAYOUT_COMPATIBLE_TYPE(Name, Id, SingletonId) \
+ is##Id##Type() ||
+ return isHLSLAttributedResourceType();
+}
+
inline bool Type::isHLSLSpecificType() const {
return isHLSLIntangibleType() || isa<HLSLAttributedResourceType>(this);
}
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index fdfb35de9cf287..0e4e2a8e45b810 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -662,6 +662,7 @@ KEYWORD(out , KEYHLSL)
// HLSL Type traits
TYPE_TRAIT_2(__builtin_hlsl_is_scalarized_layout_compatible, IsScalarizedLayoutCompatible, KEYHLSL)
TYPE_TRAIT_1(__builtin_hlsl_is_intangible, IsIntangibleType, KEYHLSL)
+TYPE_TRAIT_1(__builtin_hlsl_is_line_vector_layout_compatible, IsLineVectorLayoutCompatibleType, KEYHLSL)
// OpenMP Type Traits
UNARY_EXPR_OR_TYPE_TRAIT(__builtin_omp_required_simd_align, OpenMPRequiredSimdAlign, KEYALL)
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index 4f1fc9a31404c6..142f816768de8f 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -133,6 +133,7 @@ class SemaHLSL : public SemaBase {
// HLSL Type trait implementations
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const;
bool IsIntangibleType(QualType T1);
+ bool IsLineVectorLayoutCompatibleType(QualType T1);
bool CheckCompatibleParameterABI(FunctionDecl *New, FunctionDecl *Old);
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 34bb200e43360c..16ff6325d53960 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -109,7 +109,8 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
ImplicitCopyAssignmentHasConstParam(true),
HasDeclaredCopyConstructorWithConstParam(false),
HasDeclaredCopyAssignmentWithConstParam(false),
- IsAnyDestructorNoReturn(false), IsHLSLIntangible(false), IsLambda(false),
+ IsAnyDestructorNoReturn(false), IsHLSLIntangible(false),
+ IsHLSLLineVectorLayoutCompatible(false), IsLambda(false),
IsParsingBaseSpecifiers(false), ComputedVisibleConversions(false),
HasODRHash(false), Definition(D) {}
@@ -434,6 +435,9 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
if (BaseClassDecl->isHLSLIntangible())
data().IsHLSLIntangible = true;
+ if (BaseClassDecl->isHLSLLineVectorLayoutCompatible())
+ data().IsHLSLLineVectorLayoutCompatible = true;
+
// C++11 [class.copy]p18:
// The implicitly-declared copy assignment operator for a class X will
// have the form 'X& X::operator=(const X&)' if each direct base class B
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index e19016ab23abe7..27a731364de379 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -5032,6 +5032,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
case UTT_IsScalar:
case UTT_IsCompound:
case UTT_IsMemberPointer:
+ case UTT_IsLineVectorLayoutCompatibleType:
// Fall-through
// These traits are modeled on type predicates in C++0x [meta.unary.prop]
@@ -5714,6 +5715,15 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
tok::kw___builtin_hlsl_is_intangible))
return false;
return Self.HLSL().IsIntangibleType(T);
+
+ case UTT_IsLineVectorLayoutCompatibleType:
+ assert(Self.getLangOpts().HLSL &&
+ "line vector layout compatible types are HLSL-only feature");
+ if (Self.RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), T,
+ diag::err_incomplete_type))
+ return false;
+
+ return Self.HLSL().IsLineVectorLayoutCompatibleType(T);
}
}
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index c6627b0e993226..e38eb07c567b0f 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -2189,6 +2189,49 @@ static void BuildFlattenedTypeList(QualType BaseTy,
}
}
+bool SemaHLSL::IsLineVectorLayoutCompatibleType(clang::QualType QT) {
+ if (QT.isNull())
+ return false;
+
+ llvm::SmallVector<QualType, 16> QTTypes;
+ BuildFlattenedTypeList(QT, QTTypes);
+
+ QualType FirstQT = QTTypes[0];
+
+ // element count cannot exceed 4
+ if (QTTypes.size() > 4)
+ return false;
+
+ // check if the outer type was an array type
+ if (llvm::isa<clang::ArrayType>(QT.getTypePtr()))
+ return false;
+
+ for (QualType TempQT : QTTypes) {
+ // ensure homogeneity
+ if (TempQT != FirstQT)
+ return false;
+
+ if (const BuiltinType *BT = TempQT->getAs<BuiltinType>()) {
+ if (BT->getKind() == BuiltinType::Bool ||
+ BT->getKind() == BuiltinType::Enum)
+ return false;
+
+ // Check if it is an array type.
+ if (llvm::isa<clang::ArrayType>(TempQT.getTypePtr()))
+ return false;
+ }
+ }
+
+ // if the loop above completes without returning, then
+ // we've guaranteed homogeneity
+ int TotalSizeInBytes =
+ (SemaRef.Context.getTypeSize(FirstQT) / 8) * QTTypes.size();
+ if (TotalSizeInBytes > 16)
+ return false;
+
+ return true;
+}
+
bool SemaHLSL::IsScalarizedLayoutCompatible(QualType T1, QualType T2) const {
if (T1.isNull() || T2.isNull())
return false;
diff --git a/clang/test/SemaHLSL/Types/Traits/IsLineVectorLayoutCompatibleType.hlsl b/clang/test/SemaHLSL/Types/Traits/IsLineVectorLayoutCompatibleType.hlsl
new file mode 100644
index 00000000000000..9c97a5af39a36c
--- /dev/null
+++ b/clang/test/SemaHLSL/Types/Traits/IsLineVectorLayoutCompatibleType.hlsl
@@ -0,0 +1,101 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -verify %s
+// expected-no-diagnostics
+
+struct oneInt {
+ int i;
+};
+
+struct twoInt {
+ int aa;
+ int ab;
+};
+
+struct threeInts {
+ oneInt o;
+ twoInt t;
+};
+
+struct oneFloat {
+ float f;
+};
+struct depthDiff {
+ int i;
+ oneInt o;
+ oneFloat f;
+};
+
+struct notHomogenous{
+ int i;
+ float f;
+};
+
+struct EightElements {
+ twoInt x[2];
+ twoInt y[2];
+};
+
+struct EightHalves {
+half x[8];
+};
+
+struct intVec {
+ int2 i;
+};
+
+struct oneIntWithVec {
+ int i;
+ oneInt i2;
+ int2 i3;
+};
+
+struct weirdStruct {
+ int i;
+ intVec iv;
+};
+
+_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(int), "");
+_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(float), "");
+_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(float4), "");
+_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(double2), "");
+_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(oneInt), "");
+_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(oneFloat), "");
+_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(twoInt), "");
+_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(threeInts), "");
+_Static_assert(!__builtin_hlsl_is_line_vector_layout_compatible(notHomogenous), "");
+_Static_assert(!__builtin_hlsl_is_line_vector_layout_compatible(depthDiff), "");
+_Static_assert(!__builtin_hlsl_is_line_vector_layout_compatible(EightElements), "");
+_Static_assert(!__builtin_hlsl_is_line_vector_layout_compatible(EightHalves), "");
+_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(oneIntWithVec), "");
+_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(weirdStruct), "");
+_Static_assert(!__builtin_hlsl_is_line_vector_layout_compatible(RWBuffer<int>), "");
+
+
+// arrays not allowed
+_Static_assert(!__builtin_hlsl_is_line_vector_layout_compatible(half[4]), "");
+
+template<typename T> struct TemplatedBuffer {
+ T a;
+ __hlsl_resource_t h;
+};
+_Static_assert(!__builtin_hlsl_is_line_vector_layout_compatible(TemplatedBuffer<int>), "");
+
+struct MyStruct1 : TemplatedBuffer<float> {
+ float x;
+};
+_Static_assert(!__builtin_hlsl_is_line_vector_layout_compatible(MyStruct1), "");
+
+struct MyStruct2 {
+ const TemplatedBuffer<float> TB[10];
+};
+_Static_assert(!__builtin_hlsl_is_line_vector_layout_compatible(MyStruct2), "");
+
+template<typename T> struct SimpleTemplate {
+ T a;
+};
+
+// though the element type is incomplete, the type trait should still technically return true
+_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(SimpleTemplate<__hlsl_resource_t>), "");
+
+_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(SimpleTemplate<float>), "");
+
+
diff --git a/clang/test/SemaHLSL/Types/Traits/IsLineVectorLayoutCompatibleTypeErros.hlsl b/clang/test/SemaHLSL/Types/Traits/IsLineVectorLayoutCompatibleTypeErros.hlsl
new file mode 100644
index 00000000000000..ae878202eeac9d
--- /dev/null
+++ b/clang/test/SemaHLSL/Types/Traits/IsLineVectorLayoutCompatibleTypeErros.hlsl
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -verify %s
+
+// expected-note at +1{{forward declaration of 'notComplete'}}
+struct notComplete;
+// expected-error at +1{{incomplete type 'notComplete' where a complete type is required}}
+_Static_assert(!__builtin_hlsl_is_line_vector_layout_compatible(notComplete), "");
+
+
+// types must be complete
+_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(__hlsl_resource_t), "");
>From 1d97b51642d170b7ab15936e5ae540e5600409df Mon Sep 17 00:00:00 2001
From: Joshua Batista <jbatista at microsoft.com>
Date: Fri, 25 Oct 2024 14:01:39 -0700
Subject: [PATCH 2/2] fix bug
---
clang/include/clang/Sema/SemaHLSL.h | 1 -
clang/include/clang/Serialization/ASTBitCodes.h | 2 +-
.../Types/Traits/IsLineVectorLayoutCompatibleTypeErros.hlsl | 6 +++---
3 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index ef3c54cbd88eae..4c92b6170078b7 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -134,7 +134,6 @@ class SemaHLSL : public SemaBase {
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const;
bool IsLineVectorLayoutCompatibleType(QualType T1);
-
bool CheckCompatibleParameterABI(FunctionDecl *New, FunctionDecl *Old);
ExprResult ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg);
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 99232fd2135790..3ddbc5fcd26c44 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -1149,7 +1149,7 @@ enum PredefinedTypeIDs {
///
/// Type IDs for non-predefined types will start at
/// NUM_PREDEF_TYPE_IDs.
-const unsigned NUM_PREDEF_TYPE_IDS = 512;
+const unsigned NUM_PREDEF_TYPE_IDS = 513;
// Ensure we do not overrun the predefined types we reserved
// in the enum PredefinedTypeIDs above.
diff --git a/clang/test/SemaHLSL/Types/Traits/IsLineVectorLayoutCompatibleTypeErros.hlsl b/clang/test/SemaHLSL/Types/Traits/IsLineVectorLayoutCompatibleTypeErros.hlsl
index ae878202eeac9d..2277649df54f79 100644
--- a/clang/test/SemaHLSL/Types/Traits/IsLineVectorLayoutCompatibleTypeErros.hlsl
+++ b/clang/test/SemaHLSL/Types/Traits/IsLineVectorLayoutCompatibleTypeErros.hlsl
@@ -1,10 +1,10 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -verify %s
+// types must be complete
+_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(__hlsl_resource_t), "");
+
// expected-note at +1{{forward declaration of 'notComplete'}}
struct notComplete;
// expected-error at +1{{incomplete type 'notComplete' where a complete type is required}}
_Static_assert(!__builtin_hlsl_is_line_vector_layout_compatible(notComplete), "");
-
-// types must be complete
-_Static_assert(__builtin_hlsl_is_line_vector_layout_compatible(__hlsl_resource_t), "");
More information about the cfe-commits
mailing list