https://github.com/hekota updated https://github.com/llvm/llvm-project/pull/104544
>From 6d5f8991a4ef9e79bc1bed30addf7b29b7ed0d2e Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Thu, 15 Aug 2024 19:03:29 -0700 Subject: [PATCH 01/10] Implement `__builtin_is_intangible` --- clang/include/clang/Basic/TokenKinds.def | 3 ++ clang/include/clang/Sema/SemaHLSL.h | 3 ++ clang/lib/Sema/SemaExprCXX.cpp | 8 ++++ clang/lib/Sema/SemaHLSL.cpp | 49 ++++++++++++++++++++++++ 4 files changed, 63 insertions(+) diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index d683106bb0e298..f4fc7c321d9c5a 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -660,6 +660,9 @@ KEYWORD(out , KEYHLSL) #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) KEYWORD(Name, KEYHLSL) #include "clang/Basic/HLSLIntangibleTypes.def" +// HLSL Type traits +TYPE_TRAIT_1(__builtin_is_intangible, IsIntangibleType, 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 d60cb2a57d4918..13e75a79ec6bf0 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -62,6 +62,9 @@ class SemaHLSL : public SemaBase { void handleParamModifierAttr(Decl *D, const ParsedAttr &AL); bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + + // HLSL Type trait implementations + bool IsIntangibleType(QualType T1) const; }; } // namespace clang diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 5356bcf172f752..f3f8d511a6e568 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -39,6 +39,7 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaCUDA.h" +#include "clang/Sema/SemaHLSL.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaLambda.h" #include "clang/Sema/SemaObjC.h" @@ -5683,6 +5684,13 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, return true; return false; } + case UTT_IsIntangibleType: + if (!T->isVoidType() && !T->isIncompleteArrayType()) + if (Self.RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), T, + diag::err_incomplete_type)) + return true; + DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___builtin_is_intangible); + return Self.HLSL().IsIntangibleType(T); } } diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index e3e926465e799e..5978c14399ba32 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -12,6 +12,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/Type.h" #include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/TargetInfo.h" @@ -1154,3 +1155,51 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { } return false; } + +bool SemaHLSL::IsIntangibleType(QualType Ty) const { + if (Ty.isNull()) + return false; + + Ty = Ty.getCanonicalType().getUnqualifiedType(); + if (Ty->isBuiltinType()) + return Ty->isHLSLSpecificType(); + + llvm::SmallVector<QualType, 8> TypesToScan; + TypesToScan.push_back(Ty); + while (!TypesToScan.empty()) { + QualType T = TypesToScan.pop_back_val(); + assert(T == T.getCanonicalType().getUnqualifiedType() && "expected sugar-free type"); + assert(!isa<MatrixType>(T) && "Matrix types not yet supported in HLSL"); + + if (const auto *AT = dyn_cast<ConstantArrayType>(T)) { + QualType ElTy = AT->getElementType().getCanonicalType().getUnqualifiedType(); + if (ElTy->isBuiltinType()) + return ElTy->isHLSLSpecificType(); + TypesToScan.push_back(ElTy); + continue; + } + + if (const auto *VT = dyn_cast<VectorType>(T)) { + QualType ElTy = VT->getElementType().getCanonicalType().getUnqualifiedType(); + assert(ElTy->isBuiltinType() && "vectors can only contain builtin types"); + if (ElTy->isHLSLSpecificType()) + return true; + continue; + } + + if (const auto *RT = dyn_cast<RecordType>(T)) { + const RecordDecl *RD = RT->getDecl(); + for (const auto *FD : RD->fields()) { + QualType FieldTy = FD->getType().getCanonicalType().getUnqualifiedType(); + if (FieldTy->isBuiltinType()) { + if (FieldTy->isHLSLSpecificType()) + return true; + } else { + TypesToScan.push_back(FieldTy); + } + } + continue; + } + } + return false; +} >From d21ca2e2891acbd6c89864b57d864d881a8a8b96 Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Thu, 15 Aug 2024 20:52:24 -0700 Subject: [PATCH 02/10] add caching --- clang/include/clang/Sema/SemaHLSL.h | 5 ++++- clang/lib/Sema/SemaExprCXX.cpp | 1 + clang/lib/Sema/SemaHLSL.cpp | 22 +++++++++++++++++----- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index 13e75a79ec6bf0..663dea12880d1b 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -64,7 +64,10 @@ class SemaHLSL : public SemaBase { bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); // HLSL Type trait implementations - bool IsIntangibleType(QualType T1) const; + bool IsIntangibleType(const QualType T1); + +private: + llvm::DenseMap<const Type *, bool> IsIntangibleTypeCache; }; } // namespace clang diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index f3f8d511a6e568..d3964f5da01e00 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -5099,6 +5099,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT, case UTT_IsDestructible: case UTT_IsNothrowDestructible: case UTT_IsTriviallyDestructible: + case UTT_IsIntangibleType: if (ArgTy->isIncompleteArrayType() || ArgTy->isVoidType()) return true; diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 5978c14399ba32..e23240a380528d 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -28,7 +28,7 @@ using namespace clang; -SemaHLSL::SemaHLSL(Sema &S) : SemaBase(S) {} +SemaHLSL::SemaHLSL(Sema &S) : SemaBase(S), IsIntangibleTypeCache(8) {} Decl *SemaHLSL::ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *Ident, @@ -1156,10 +1156,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { return false; } -bool SemaHLSL::IsIntangibleType(QualType Ty) const { - if (Ty.isNull()) - return false; - +static bool calculateIsIntangibleType(QualType Ty) { Ty = Ty.getCanonicalType().getUnqualifiedType(); if (Ty->isBuiltinType()) return Ty->isHLSLSpecificType(); @@ -1203,3 +1200,18 @@ bool SemaHLSL::IsIntangibleType(QualType Ty) const { } return false; } + +bool SemaHLSL::IsIntangibleType(const clang::QualType Ty) { + if (Ty.isNull()) + return false; + + const auto CachedEntry = IsIntangibleTypeCache.find(Ty.getTypePtr()); + if (CachedEntry != IsIntangibleTypeCache.end()) { + assert(CachedEntry->second == calculateIsIntangibleType(Ty) && "IsIntangibleType mismatch"); + return CachedEntry->second; + } + + bool IsIntangible = calculateIsIntangibleType(Ty); + IsIntangibleTypeCache[Ty.getTypePtr()] = IsIntangible; + return IsIntangible; +} >From d7e8bce2e27f894196691435d2379edfdd6cd906 Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Thu, 15 Aug 2024 20:56:40 -0700 Subject: [PATCH 03/10] clang-format --- clang/lib/Sema/SemaHLSL.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index e23240a380528d..5e5917c40bc1cc 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -1165,19 +1165,22 @@ static bool calculateIsIntangibleType(QualType Ty) { TypesToScan.push_back(Ty); while (!TypesToScan.empty()) { QualType T = TypesToScan.pop_back_val(); - assert(T == T.getCanonicalType().getUnqualifiedType() && "expected sugar-free type"); + assert(T == T.getCanonicalType().getUnqualifiedType() && + "expected sugar-free type"); assert(!isa<MatrixType>(T) && "Matrix types not yet supported in HLSL"); if (const auto *AT = dyn_cast<ConstantArrayType>(T)) { - QualType ElTy = AT->getElementType().getCanonicalType().getUnqualifiedType(); + QualType ElTy = + AT->getElementType().getCanonicalType().getUnqualifiedType(); if (ElTy->isBuiltinType()) return ElTy->isHLSLSpecificType(); TypesToScan.push_back(ElTy); - continue; + continue; } if (const auto *VT = dyn_cast<VectorType>(T)) { - QualType ElTy = VT->getElementType().getCanonicalType().getUnqualifiedType(); + QualType ElTy = + VT->getElementType().getCanonicalType().getUnqualifiedType(); assert(ElTy->isBuiltinType() && "vectors can only contain builtin types"); if (ElTy->isHLSLSpecificType()) return true; @@ -1187,12 +1190,13 @@ static bool calculateIsIntangibleType(QualType Ty) { if (const auto *RT = dyn_cast<RecordType>(T)) { const RecordDecl *RD = RT->getDecl(); for (const auto *FD : RD->fields()) { - QualType FieldTy = FD->getType().getCanonicalType().getUnqualifiedType(); + QualType FieldTy = + FD->getType().getCanonicalType().getUnqualifiedType(); if (FieldTy->isBuiltinType()) { if (FieldTy->isHLSLSpecificType()) return true; } else { - TypesToScan.push_back(FieldTy); + TypesToScan.push_back(FieldTy); } } continue; @@ -1207,7 +1211,8 @@ bool SemaHLSL::IsIntangibleType(const clang::QualType Ty) { const auto CachedEntry = IsIntangibleTypeCache.find(Ty.getTypePtr()); if (CachedEntry != IsIntangibleTypeCache.end()) { - assert(CachedEntry->second == calculateIsIntangibleType(Ty) && "IsIntangibleType mismatch"); + assert(CachedEntry->second == calculateIsIntangibleType(Ty) && + "IsIntangibleType mismatch"); return CachedEntry->second; } >From 481c118d7d94f16c9cc9babbaaa794f951883088 Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Thu, 15 Aug 2024 21:16:19 -0700 Subject: [PATCH 04/10] add tests --- .../Types/Traits/IsIntangibleType.hlsl | 52 +++++++++++++++++++ .../Types/Traits/IsIntangibleTypeErrors.hlsl | 11 ++++ 2 files changed, 63 insertions(+) create mode 100644 clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl create mode 100644 clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl diff --git a/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl b/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl new file mode 100644 index 00000000000000..ae6da681d5100e --- /dev/null +++ b/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -verify %s +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -verify %s +// expected-no-diagnostics + +_Static_assert(__builtin_is_intangible(__hlsl_resource_t), ""); +// no need to check array of __hlsl_resource_t, arrays of sizeless types are not supported + +_Static_assert(!__builtin_is_intangible(int), ""); +_Static_assert(!__builtin_is_intangible(float3), ""); +_Static_assert(!__builtin_is_intangible(half[4]), ""); + +typedef __hlsl_resource_t Res; +_Static_assert(__builtin_is_intangible(const Res), ""); +// no need to check array of Res, arrays of sizeless types are not supported + +struct ABuffer { + const int i[10]; + __hlsl_resource_t h; +}; +_Static_assert(__builtin_is_intangible(ABuffer), ""); +_Static_assert(__builtin_is_intangible(ABuffer[10]), ""); + +struct MyStruct { + half2 h2; + int3 i3; +}; +_Static_assert(!__builtin_is_intangible(MyStruct), ""); +_Static_assert(!__builtin_is_intangible(MyStruct[10]), ""); + +class MyClass { + int3 ivec; + float farray[12]; + MyStruct ms; + ABuffer buf; +}; +_Static_assert(__builtin_is_intangible(MyClass), ""); +_Static_assert(__builtin_is_intangible(MyClass[2]), ""); + +union U { + double d[4]; + Res buf; +}; +_Static_assert(__builtin_is_intangible(U), ""); +_Static_assert(__builtin_is_intangible(U[100]), ""); + +class MyClass2 { + int3 ivec; + float farray[12]; + U u; +}; +_Static_assert(__builtin_is_intangible(MyClass2), ""); +_Static_assert(__builtin_is_intangible(MyClass2[5]), ""); diff --git a/clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl b/clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl new file mode 100644 index 00000000000000..bfb654de0dcfca --- /dev/null +++ b/clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -verify %s + +struct Undefined; // expected-note {{forward declaration of 'Undefined'}} +_Static_assert(!__builtin_is_intangible(Undefined), ""); // expected-error{{incomplete type 'Undefined' used in type trait expression}} + +void fn(int X) { + // expected-error@#vla {{variable length arrays are not supported for the current target}} + // expected-error@#vla {{variable length arrays are not supported in '__builtin_is_intangible'}} + // expected-warning@#vla {{variable length arrays in C++ are a Clang extension}} + _Static_assert(!__builtin_is_intangible(int[X]), ""); // #vla +} \ No newline at end of file >From 2df05761de1df378cedec49430c327a21f8ee089 Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Thu, 15 Aug 2024 21:56:28 -0700 Subject: [PATCH 05/10] base classes! --- clang/lib/Sema/SemaHLSL.cpp | 21 +++++++++++-------- .../Types/Traits/IsIntangibleType.hlsl | 9 ++++++++ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 5e5917c40bc1cc..09d4d6e7f13c72 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -10,6 +10,7 @@ #include "clang/Sema/SemaHLSL.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/Type.h" @@ -1157,7 +1158,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { } static bool calculateIsIntangibleType(QualType Ty) { - Ty = Ty.getCanonicalType().getUnqualifiedType(); + Ty = Ty->getCanonicalTypeUnqualified(); if (Ty->isBuiltinType()) return Ty->isHLSLSpecificType(); @@ -1165,13 +1166,11 @@ static bool calculateIsIntangibleType(QualType Ty) { TypesToScan.push_back(Ty); while (!TypesToScan.empty()) { QualType T = TypesToScan.pop_back_val(); - assert(T == T.getCanonicalType().getUnqualifiedType() && - "expected sugar-free type"); + assert(T == T->getCanonicalTypeUnqualified() && "expected sugar-free type"); assert(!isa<MatrixType>(T) && "Matrix types not yet supported in HLSL"); if (const auto *AT = dyn_cast<ConstantArrayType>(T)) { - QualType ElTy = - AT->getElementType().getCanonicalType().getUnqualifiedType(); + QualType ElTy = AT->getElementType()->getCanonicalTypeUnqualified(); if (ElTy->isBuiltinType()) return ElTy->isHLSLSpecificType(); TypesToScan.push_back(ElTy); @@ -1179,8 +1178,7 @@ static bool calculateIsIntangibleType(QualType Ty) { } if (const auto *VT = dyn_cast<VectorType>(T)) { - QualType ElTy = - VT->getElementType().getCanonicalType().getUnqualifiedType(); + QualType ElTy = VT->getElementType()->getCanonicalTypeUnqualified(); assert(ElTy->isBuiltinType() && "vectors can only contain builtin types"); if (ElTy->isHLSLSpecificType()) return true; @@ -1190,8 +1188,7 @@ static bool calculateIsIntangibleType(QualType Ty) { if (const auto *RT = dyn_cast<RecordType>(T)) { const RecordDecl *RD = RT->getDecl(); for (const auto *FD : RD->fields()) { - QualType FieldTy = - FD->getType().getCanonicalType().getUnqualifiedType(); + QualType FieldTy = FD->getType()->getCanonicalTypeUnqualified(); if (FieldTy->isBuiltinType()) { if (FieldTy->isHLSLSpecificType()) return true; @@ -1199,6 +1196,12 @@ static bool calculateIsIntangibleType(QualType Ty) { TypesToScan.push_back(FieldTy); } } + + if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) { + for (const CXXBaseSpecifier &B : CXXRD->bases()) { + TypesToScan.push_back(B.getType()->getCanonicalTypeUnqualified()); + } + } continue; } } diff --git a/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl b/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl index ae6da681d5100e..f7ef7f543bfb5e 100644 --- a/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl +++ b/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl @@ -50,3 +50,12 @@ class MyClass2 { }; _Static_assert(__builtin_is_intangible(MyClass2), ""); _Static_assert(__builtin_is_intangible(MyClass2[5]), ""); + +class Simple { + int a; +}; + +class MyClass3 : MyClass2, Simple { + half h; +}; +_Static_assert(__builtin_is_intangible(MyClass3), ""); >From 227befd3ecff7899ef0088045176cead79aa8adc Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Thu, 15 Aug 2024 22:26:44 -0700 Subject: [PATCH 06/10] Update default for incomplete type --- clang/lib/Sema/SemaExprCXX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index d3964f5da01e00..94132a4823e305 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -5689,7 +5689,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, if (!T->isVoidType() && !T->isIncompleteArrayType()) if (Self.RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), T, diag::err_incomplete_type)) - return true; + return false; DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___builtin_is_intangible); return Self.HLSL().IsIntangibleType(T); } >From 4bbf083bd75de42c82e4b2068b541241fcd492fd Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Mon, 19 Aug 2024 15:04:58 -0700 Subject: [PATCH 07/10] Rename to `__builtin_hlsl_is_intangible` --- clang/include/clang/Basic/TokenKinds.def | 2 +- clang/lib/Sema/SemaExprCXX.cpp | 2 +- .../Types/Traits/IsIntangibleType.hlsl | 32 +++++++++---------- .../Types/Traits/IsIntangibleTypeErrors.hlsl | 6 ++-- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index f4fc7c321d9c5a..1b36d799f13f46 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -661,7 +661,7 @@ KEYWORD(out , KEYHLSL) #include "clang/Basic/HLSLIntangibleTypes.def" // HLSL Type traits -TYPE_TRAIT_1(__builtin_is_intangible, IsIntangibleType, KEYHLSL) +TYPE_TRAIT_1(__builtin_hlsl_is_intangible, IsIntangibleType, KEYHLSL) // OpenMP Type Traits UNARY_EXPR_OR_TYPE_TRAIT(__builtin_omp_required_simd_align, OpenMPRequiredSimdAlign, KEYALL) diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 94132a4823e305..55366bfd20b100 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -5690,7 +5690,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, if (Self.RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), T, diag::err_incomplete_type)) return false; - DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___builtin_is_intangible); + DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___builtin_hlsl_is_intangible); return Self.HLSL().IsIntangibleType(T); } } diff --git a/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl b/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl index f7ef7f543bfb5e..39a912f99d3896 100644 --- a/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl +++ b/clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl @@ -2,30 +2,30 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -verify %s // expected-no-diagnostics -_Static_assert(__builtin_is_intangible(__hlsl_resource_t), ""); +_Static_assert(__builtin_hlsl_is_intangible(__hlsl_resource_t), ""); // no need to check array of __hlsl_resource_t, arrays of sizeless types are not supported -_Static_assert(!__builtin_is_intangible(int), ""); -_Static_assert(!__builtin_is_intangible(float3), ""); -_Static_assert(!__builtin_is_intangible(half[4]), ""); +_Static_assert(!__builtin_hlsl_is_intangible(int), ""); +_Static_assert(!__builtin_hlsl_is_intangible(float3), ""); +_Static_assert(!__builtin_hlsl_is_intangible(half[4]), ""); typedef __hlsl_resource_t Res; -_Static_assert(__builtin_is_intangible(const Res), ""); +_Static_assert(__builtin_hlsl_is_intangible(const Res), ""); // no need to check array of Res, arrays of sizeless types are not supported struct ABuffer { const int i[10]; __hlsl_resource_t h; }; -_Static_assert(__builtin_is_intangible(ABuffer), ""); -_Static_assert(__builtin_is_intangible(ABuffer[10]), ""); +_Static_assert(__builtin_hlsl_is_intangible(ABuffer), ""); +_Static_assert(__builtin_hlsl_is_intangible(ABuffer[10]), ""); struct MyStruct { half2 h2; int3 i3; }; -_Static_assert(!__builtin_is_intangible(MyStruct), ""); -_Static_assert(!__builtin_is_intangible(MyStruct[10]), ""); +_Static_assert(!__builtin_hlsl_is_intangible(MyStruct), ""); +_Static_assert(!__builtin_hlsl_is_intangible(MyStruct[10]), ""); class MyClass { int3 ivec; @@ -33,23 +33,23 @@ class MyClass { MyStruct ms; ABuffer buf; }; -_Static_assert(__builtin_is_intangible(MyClass), ""); -_Static_assert(__builtin_is_intangible(MyClass[2]), ""); +_Static_assert(__builtin_hlsl_is_intangible(MyClass), ""); +_Static_assert(__builtin_hlsl_is_intangible(MyClass[2]), ""); union U { double d[4]; Res buf; }; -_Static_assert(__builtin_is_intangible(U), ""); -_Static_assert(__builtin_is_intangible(U[100]), ""); +_Static_assert(__builtin_hlsl_is_intangible(U), ""); +_Static_assert(__builtin_hlsl_is_intangible(U[100]), ""); class MyClass2 { int3 ivec; float farray[12]; U u; }; -_Static_assert(__builtin_is_intangible(MyClass2), ""); -_Static_assert(__builtin_is_intangible(MyClass2[5]), ""); +_Static_assert(__builtin_hlsl_is_intangible(MyClass2), ""); +_Static_assert(__builtin_hlsl_is_intangible(MyClass2[5]), ""); class Simple { int a; @@ -58,4 +58,4 @@ class Simple { class MyClass3 : MyClass2, Simple { half h; }; -_Static_assert(__builtin_is_intangible(MyClass3), ""); +_Static_assert(__builtin_hlsl_is_intangible(MyClass3), ""); diff --git a/clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl b/clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl index bfb654de0dcfca..bbf2a1682e3f05 100644 --- a/clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl +++ b/clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl @@ -1,11 +1,11 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -verify %s struct Undefined; // expected-note {{forward declaration of 'Undefined'}} -_Static_assert(!__builtin_is_intangible(Undefined), ""); // expected-error{{incomplete type 'Undefined' used in type trait expression}} +_Static_assert(!__builtin_hlsl_is_intangible(Undefined), ""); // expected-error{{incomplete type 'Undefined' used in type trait expression}} void fn(int X) { // expected-error@#vla {{variable length arrays are not supported for the current target}} - // expected-error@#vla {{variable length arrays are not supported in '__builtin_is_intangible'}} + // expected-error@#vla {{variable length arrays are not supported in '__builtin_hlsl_is_intangible'}} // expected-warning@#vla {{variable length arrays in C++ are a Clang extension}} - _Static_assert(!__builtin_is_intangible(int[X]), ""); // #vla + _Static_assert(!__builtin_hlsl_is_intangible(int[X]), ""); // #vla } \ No newline at end of file >From 6fd1bf74d532160338bf8b091a15e06369c37027 Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Mon, 19 Aug 2024 17:52:07 -0700 Subject: [PATCH 08/10] clang-format --- clang/lib/Sema/SemaExprCXX.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 55366bfd20b100..49942944c37806 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -5690,7 +5690,8 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, if (Self.RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), T, diag::err_incomplete_type)) return false; - DiagnoseVLAInCXXTypeTrait(Self, TInfo, tok::kw___builtin_hlsl_is_intangible); + DiagnoseVLAInCXXTypeTrait(Self, TInfo, + tok::kw___builtin_hlsl_is_intangible); return Self.HLSL().IsIntangibleType(T); } } >From 7f29d6fe8f7ca5fac9dfb475fc256b82b3b64048 Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Tue, 27 Aug 2024 12:29:29 -0700 Subject: [PATCH 09/10] Address code review feedback --- clang/include/clang/AST/Type.h | 7 ++ clang/include/clang/Sema/SemaHLSL.h | 6 +- clang/lib/Sema/SemaExprCXX.cpp | 1 + clang/lib/Sema/SemaHLSL.cpp | 19 ++-- particle_life.hlsl | 147 ++++++++++++++++++++++++++++ 5 files changed, 171 insertions(+), 9 deletions(-) create mode 100644 particle_life.hlsl diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 575f3c17a3f691..d19e353967fa8b 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -2656,6 +2656,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) bool is##Id##Type() const; #include "clang/Basic/HLSLIntangibleTypes.def" bool isHLSLSpecificType() const; // Any HLSL specific type + bool isHLSLIntangibleType() const; // Any HLSL intangible type /// Determines if this type, which must satisfy /// isObjCLifetimeType(), is implicitly __unsafe_unretained rather @@ -8286,6 +8287,12 @@ inline bool Type::isHLSLSpecificType() const { false; // end boolean or operation } +inline bool Type::isHLSLIntangibleType() const { + // All HLSL specific types are currently intangible type as well, but that + // might change in the future. + return isHLSLSpecificType(); +} + inline bool Type::isTemplateTypeParmType() const { return isa<TemplateTypeParmType>(CanonicalType); } diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index e923df60b91458..cae3a502c73cf0 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -62,12 +62,12 @@ class SemaHLSL : public SemaBase { bool CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); -private: - llvm::DenseMap<const Type *, bool> IsIntangibleTypeCache; - // HLSL Type trait implementations bool IsScalarizedLayoutCompatible(QualType T1, QualType T2) const; bool IsIntangibleType(const QualType T1); + +private: + llvm::DenseMap<const Type *, bool> IsIntangibleTypeCache; }; } // namespace clang diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 7e179bc9939cdd..4c7c6bfdb2db9d 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -5697,6 +5697,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT, return false; } case UTT_IsIntangibleType: + assert(Self.getLangOpts().HLSL && "intangible types are HLSL-only feature"); if (!T->isVoidType() && !T->isIncompleteArrayType()) if (Self.RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), T, diag::err_incomplete_type)) diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index e939fca1411a5d..f7cf18be195f3f 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -29,7 +29,7 @@ using namespace clang; -SemaHLSL::SemaHLSL(Sema &S) : SemaBase(S), IsIntangibleTypeCache(8) {} +SemaHLSL::SemaHLSL(Sema &S) : SemaBase(S), IsIntangibleTypeCache() {} Decl *SemaHLSL::ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *Ident, @@ -1528,11 +1528,10 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { } static bool calculateIsIntangibleType(QualType Ty) { - Ty = Ty->getCanonicalTypeUnqualified(); - if (Ty->isBuiltinType()) - return Ty->isHLSLSpecificType(); + assert(!Ty.getCanonicalType().getUnqualifiedType()->isBuiltinType() && + "builtin types should be taken care of in IsIntangibleType"); - llvm::SmallVector<QualType, 8> TypesToScan; + llvm::SmallVector<QualType> TypesToScan; TypesToScan.push_back(Ty); while (!TypesToScan.empty()) { QualType T = TypesToScan.pop_back_val(); @@ -1582,6 +1581,12 @@ bool SemaHLSL::IsIntangibleType(const clang::QualType Ty) { if (Ty.isNull()) return false; + // check if it's a builtin type first (simple check, no need to cache it) + QualType CT = Ty->getCanonicalTypeUnqualified(); + if (CT->isBuiltinType()) + return CT->isHLSLIntangibleType(); + + // more complex type -> check if we already have it in the cache const auto CachedEntry = IsIntangibleTypeCache.find(Ty.getTypePtr()); if (CachedEntry != IsIntangibleTypeCache.end()) { assert(CachedEntry->second == calculateIsIntangibleType(Ty) && @@ -1589,9 +1594,12 @@ bool SemaHLSL::IsIntangibleType(const clang::QualType Ty) { return CachedEntry->second; } + // calculate and add to cache bool IsIntangible = calculateIsIntangibleType(Ty); IsIntangibleTypeCache[Ty.getTypePtr()] = IsIntangible; return IsIntangible; +} + static void BuildFlattenedTypeList(QualType BaseTy, llvm::SmallVectorImpl<QualType> &List) { llvm::SmallVector<QualType, 16> WorkList; @@ -1673,4 +1681,3 @@ bool SemaHLSL::IsScalarizedLayoutCompatible(QualType T1, QualType T2) const { return SemaRef.IsLayoutCompatible(LHS, RHS); }); } -} diff --git a/particle_life.hlsl b/particle_life.hlsl new file mode 100644 index 00000000000000..4cffbdb04e1b60 --- /dev/null +++ b/particle_life.hlsl @@ -0,0 +1,147 @@ +#define ROOT_SIGNATURE \ + "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT)," \ + "CBV(b0)," \ + "SRV(t0)," \ + "SRV(t1)," \ + "UAV(u0)," \ + "UAV(u1)" + + +cbuffer CONSTANTS : register(b0) { + uint ParticleTypeMax; + uint NumParticles; + float2 WorldSize; + float Friction; + float ForceMultipler; +} + +struct Rule { + float force; + float min_distance; + float max_distance; +}; + +struct Particle { + float2 position; + float2 velocity; + uint type; +}; + +struct Vertex { + float2 position; + uint color; +}; + +StructuredBuffer<Rule> Rules : register(t0); +StructuredBuffer<Particle> OldParticles : register(t1); +RWStructuredBuffer<Particle> NewParticles : register(u0); +RWStructuredBuffer<Vertex> Vertices : register(u1); + + +float3 particle_type_to_color(uint type); +uint float_to_abgr(float3 rgb); + + +[numthreads(32, 1, 1)] +void main(uint3 dispatch_thread_id : SV_DispatchThreadID) { + uint particle_id = dispatch_thread_id.x; + + Particle particle = OldParticles[particle_id]; + + // Accumulate forces + float2 force = float2(0,0); + float hit = 0; + + for (uint i = 0; i < NumParticles; ++i) { + if (i == particle_id) + continue; + + Particle other_particle = OldParticles[i]; + + Rule rule = Rules[particle.type * ParticleTypeMax + other_particle.type]; + + float2 direction = other_particle.position - particle.position; + + // wrapping + if (direction.x > WorldSize.x * 0.5f) + direction.x -= WorldSize.x; + if (direction.x < WorldSize.x * -0.5f) + direction.x += WorldSize.x; + if (direction.y > WorldSize.y * 0.5f) + direction.y -= WorldSize.y; + if (direction.y < WorldSize.y * -0.5f) + direction.y += WorldSize.y; + + // apply rule + float distance = length(direction); + direction = normalize(direction); + + if (distance < rule.min_distance) { + float repulsive_amount = abs(rule.force) * (1.0f - (distance / rule.min_distance)) * -3.0f; + force += direction * repulsive_amount; + } + + if (distance < rule.max_distance) { + float attract_amount = rule.force * (1.0f - (distance / rule.max_distance)); + force += direction * attract_amount; + hit += 0.01f; + } + } + + float2 velocity = particle.velocity; + velocity += force * ForceMultipler; + velocity *= Friction; + + particle.position = particle.position + velocity; + + if (particle.position.x < 0) + particle.position.x += WorldSize.x; + + if (particle.position.x > WorldSize.x) + particle.position.x -= WorldSize.x; + + if (particle.position.y < 0) + particle.position.y += WorldSize.y; + + if (particle.position.y > WorldSize.y) + particle.position.y -= WorldSize.y; + + + particle.velocity = velocity; + + Vertices[particle_id].position = particle.position; + + float3 color = particle_type_to_color(particle.type); + + color = lerp(color, color * 0.1f, 1-saturate(hit)); + + Vertices[particle_id].color = float_to_abgr(color); + + NewParticles[particle_id] = particle; +} + + + +// from https://chilliant.com/rgb2hsv.html +float3 hue2rgb(float H) { + float R = abs(H * 6 - 3) - 1; + float G = 2 - abs(H * 6 - 2); + float B = 2 - abs(H * 6 - 4); + return saturate(float3(R,G,B)); +} + +float3 particle_type_to_color(uint type) { + float hue = (float)type / float(ParticleTypeMax); + return hue2rgb(hue); +} + +uint float_to_abgr(float3 rgb) { + rgb *= 255.0; + + uint r = rgb.x; + uint g = rgb.y; + uint b = rgb.z; + uint a = 255; + + return (a << 24) | (b << 16) | (g << 8) | r; +} \ No newline at end of file >From d666eb7999c43e2cd6ae9c0948a6e0380bb1d425 Mon Sep 17 00:00:00 2001 From: Helena Kotas <heko...@microsoft.com> Date: Tue, 27 Aug 2024 12:53:48 -0700 Subject: [PATCH 10/10] Remove accidentally added file --- particle_life.hlsl | 147 --------------------------------------------- 1 file changed, 147 deletions(-) delete mode 100644 particle_life.hlsl diff --git a/particle_life.hlsl b/particle_life.hlsl deleted file mode 100644 index 4cffbdb04e1b60..00000000000000 --- a/particle_life.hlsl +++ /dev/null @@ -1,147 +0,0 @@ -#define ROOT_SIGNATURE \ - "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT)," \ - "CBV(b0)," \ - "SRV(t0)," \ - "SRV(t1)," \ - "UAV(u0)," \ - "UAV(u1)" - - -cbuffer CONSTANTS : register(b0) { - uint ParticleTypeMax; - uint NumParticles; - float2 WorldSize; - float Friction; - float ForceMultipler; -} - -struct Rule { - float force; - float min_distance; - float max_distance; -}; - -struct Particle { - float2 position; - float2 velocity; - uint type; -}; - -struct Vertex { - float2 position; - uint color; -}; - -StructuredBuffer<Rule> Rules : register(t0); -StructuredBuffer<Particle> OldParticles : register(t1); -RWStructuredBuffer<Particle> NewParticles : register(u0); -RWStructuredBuffer<Vertex> Vertices : register(u1); - - -float3 particle_type_to_color(uint type); -uint float_to_abgr(float3 rgb); - - -[numthreads(32, 1, 1)] -void main(uint3 dispatch_thread_id : SV_DispatchThreadID) { - uint particle_id = dispatch_thread_id.x; - - Particle particle = OldParticles[particle_id]; - - // Accumulate forces - float2 force = float2(0,0); - float hit = 0; - - for (uint i = 0; i < NumParticles; ++i) { - if (i == particle_id) - continue; - - Particle other_particle = OldParticles[i]; - - Rule rule = Rules[particle.type * ParticleTypeMax + other_particle.type]; - - float2 direction = other_particle.position - particle.position; - - // wrapping - if (direction.x > WorldSize.x * 0.5f) - direction.x -= WorldSize.x; - if (direction.x < WorldSize.x * -0.5f) - direction.x += WorldSize.x; - if (direction.y > WorldSize.y * 0.5f) - direction.y -= WorldSize.y; - if (direction.y < WorldSize.y * -0.5f) - direction.y += WorldSize.y; - - // apply rule - float distance = length(direction); - direction = normalize(direction); - - if (distance < rule.min_distance) { - float repulsive_amount = abs(rule.force) * (1.0f - (distance / rule.min_distance)) * -3.0f; - force += direction * repulsive_amount; - } - - if (distance < rule.max_distance) { - float attract_amount = rule.force * (1.0f - (distance / rule.max_distance)); - force += direction * attract_amount; - hit += 0.01f; - } - } - - float2 velocity = particle.velocity; - velocity += force * ForceMultipler; - velocity *= Friction; - - particle.position = particle.position + velocity; - - if (particle.position.x < 0) - particle.position.x += WorldSize.x; - - if (particle.position.x > WorldSize.x) - particle.position.x -= WorldSize.x; - - if (particle.position.y < 0) - particle.position.y += WorldSize.y; - - if (particle.position.y > WorldSize.y) - particle.position.y -= WorldSize.y; - - - particle.velocity = velocity; - - Vertices[particle_id].position = particle.position; - - float3 color = particle_type_to_color(particle.type); - - color = lerp(color, color * 0.1f, 1-saturate(hit)); - - Vertices[particle_id].color = float_to_abgr(color); - - NewParticles[particle_id] = particle; -} - - - -// from https://chilliant.com/rgb2hsv.html -float3 hue2rgb(float H) { - float R = abs(H * 6 - 3) - 1; - float G = 2 - abs(H * 6 - 2); - float B = 2 - abs(H * 6 - 4); - return saturate(float3(R,G,B)); -} - -float3 particle_type_to_color(uint type) { - float hue = (float)type / float(ParticleTypeMax); - return hue2rgb(hue); -} - -uint float_to_abgr(float3 rgb) { - rgb *= 255.0; - - uint r = rgb.x; - uint g = rgb.y; - uint b = rgb.z; - uint a = 255; - - return (a << 24) | (b << 16) | (g << 8) | r; -} \ No newline at end of file _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits