[clang] [HLSL] add IsTypedResourceElementCompatible type trait (PR #114864)

via cfe-commits cfe-commits at lists.llvm.org
Mon Nov 4 12:26:50 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Joshua Batista (bob80905)

<details>
<summary>Changes</summary>

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 https://github.com/llvm/llvm-project/issues/113223

---
Full diff: https://github.com/llvm/llvm-project/pull/114864.diff


6 Files Affected:

- (modified) clang/include/clang/Basic/TokenKinds.def (+1) 
- (modified) clang/include/clang/Sema/SemaHLSL.h (+1) 
- (modified) clang/lib/Sema/SemaExprCXX.cpp (+10) 
- (modified) clang/lib/Sema/SemaHLSL.cpp (+44) 
- (added) clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatible.hlsl (+101) 
- (added) clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl (+10) 


``````````diff
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index fdfb35de9cf287..2c692c999bdff5 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 e30acd87f77218..06c541dec08cc8 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 50c1b24fce6da7..0001e343da84be 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 &&
+           "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().IsTypedResourceElementCompatible(T);
   }
 }
 
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 1f6c5b8d4561bc..b4cd4aa9c85afd 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -2163,6 +2163,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 = QTTypes[0];
+
+  // element count cannot exceed 4
+  if (QTTypes.size() > 4)
+    return false;
+
+  for (QualType TempQT : QTTypes) {
+    // ensure homogeneity
+    if (TempQT != FirstQT)
+      return false;
+
+    if (const BuiltinType *BT = TempQT->getAs<BuiltinType>()) {
+      if (BT->isBooleanType() || BT->isEnumeralType())
+        return false;
+
+      // Check if it is an array type.
+      if (TempQT->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 00000000000000..669c03ea39c8f7
--- /dev/null
+++ b/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatible.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_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>), "");
+
+
diff --git a/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl b/clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatibleErrors.hlsl
new file mode 100644
index 00000000000000..167a5be6e93843
--- /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), "");
+

``````````

</details>


https://github.com/llvm/llvm-project/pull/114864


More information about the cfe-commits mailing list