[clang] b509eb7 - [HLSL] add IsTypedResourceElementCompatible type trait (#114864)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 5 10:05:10 PST 2024
Author: Joshua Batista
Date: 2024-11-05T10:05:02-08:00
New Revision: b509eb7740b3300b79b90f8a43c374e28d13dc48
URL: https://github.com/llvm/llvm-project/commit/b509eb7740b3300b79b90f8a43c374e28d13dc48
DIFF: https://github.com/llvm/llvm-project/commit/b509eb7740b3300b79b90f8a43c374e28d13dc48.diff
LOG: [HLSL] add IsTypedResourceElementCompatible type trait (#114864)
This PR implements a new type trait as a builtin,
__builtin_hlsl_is_typed_resource_element_compatible
This type traits verifies that the given input type is suitable as a
typed resource element type.
It checks that the given input type is homogeneous, has no more than 4
sub elements, does not exceed 16 bytes, and does not contain any arrays,
booleans, or enums.
Fixes an issue in https://github.com/llvm/llvm-project/pull/113730 that
needed to cause that PR to be reverted.
Fixes https://github.com/llvm/llvm-project/issues/113223
Added:
clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatible.hlsl
clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl
Modified:
clang/include/clang/Basic/TokenKinds.def
clang/include/clang/Sema/SemaHLSL.h
clang/lib/Sema/SemaExprCXX.cpp
clang/lib/Sema/SemaHLSL.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index fdfb35de9cf2877..2c692c999bdff53 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_typed_resource_element_compatible, IsTypedResourceElementCompatible, 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 e30acd87f77218c..06c541dec08cc8b 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -132,6 +132,7 @@ class SemaHLSL : public SemaBase {
// HLSL Type trait implementations
bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const;
+ bool IsTypedResourceElementCompatible(QualType T1);
bool CheckCompatibleParameterABI(FunctionDecl *New, FunctionDecl *Old);
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 50c1b24fce6da7d..ab9367f911cc51b 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_IsTypedResourceElementCompatible:
// 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 T->isHLSLIntangibleType();
+
+ case UTT_IsTypedResourceElementCompatible:
+ assert(Self.getLangOpts().HLSL &&
+ "typed resource element compatible types are an HLSL-only feature");
+ if (Self.RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), T,
+ diag::err_incomplete_type))
+ return false;
+
+ return Self.HLSL().IsTypedResourceElementCompatible(T);
}
}
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index a472538236e2d91..298b7ad4f9e6872 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -2199,6 +2199,50 @@ static void BuildFlattenedTypeList(QualType BaseTy,
}
}
+bool SemaHLSL::IsTypedResourceElementCompatible(clang::QualType QT) {
+ if (QT.isNull())
+ return false;
+
+ // check if the outer type was an array type
+ if (QT->isArrayType())
+ return false;
+
+ llvm::SmallVector<QualType, 4> QTTypes;
+ BuildFlattenedTypeList(QT, QTTypes);
+
+ assert(QTTypes.size() > 0 &&
+ "expected at least one constituent type from non-null type");
+ QualType FirstQT = SemaRef.Context.getCanonicalType(QTTypes[0]);
+
+ // element count cannot exceed 4
+ if (QTTypes.size() > 4)
+ return false;
+
+ for (QualType TempQT : QTTypes) {
+ // ensure homogeneity
+ if (!getASTContext().hasSameUnqualifiedType(FirstQT, TempQT))
+ return false;
+ }
+
+ if (const BuiltinType *BT = FirstQT->getAs<BuiltinType>()) {
+ if (BT->isBooleanType() || BT->isEnumeralType())
+ return false;
+
+ // Check if it is an array type.
+ if (FirstQT->isArrayType())
+ 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/IsTypedResourceElementCompatible.hlsl b/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatible.hlsl
new file mode 100644
index 000000000000000..acc1f281daddfc8
--- /dev/null
+++ b/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatible.hlsl
@@ -0,0 +1,109 @@
+// 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_typed_resource_element_compatible(int), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(float), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(float4), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(double2), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(oneInt), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(oneFloat), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(twoInt), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(threeInts), "");
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(notHomogenous), "");
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(depthDiff), "");
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(EightElements), "");
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(EightHalves), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(oneIntWithVec), "");
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(weirdStruct), "");
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(RWBuffer<int>), "");
+
+
+// arrays not allowed
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(half[4]), "");
+
+template<typename T> struct TemplatedBuffer {
+ T a;
+ __hlsl_resource_t h;
+};
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(TemplatedBuffer<int>), "");
+
+struct MyStruct1 : TemplatedBuffer<float> {
+ float x;
+};
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(MyStruct1), "");
+
+struct MyStruct2 {
+ const TemplatedBuffer<float> TB[10];
+};
+_Static_assert(!__builtin_hlsl_is_typed_resource_element_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_typed_resource_element_compatible(SimpleTemplate<__hlsl_resource_t>), "");
+
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(SimpleTemplate<float>), "");
+
+
+typedef int myInt;
+
+struct TypeDefTest {
+ int x;
+ myInt y;
+};
+
+_Static_assert(__builtin_hlsl_is_typed_resource_element_compatible(TypeDefTest), "");
diff --git a/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl b/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl
new file mode 100644
index 000000000000000..cb3e9ae7a61509a
--- /dev/null
+++ b/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl
@@ -0,0 +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_typed_resource_element_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_typed_resource_element_compatible(notComplete), "");
+
More information about the cfe-commits
mailing list