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 <jbati...@microsoft.com> Date: Fri, 25 Oct 2024 12:33:05 -0700 Subject: [PATCH] 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@+1{{forward declaration of 'notComplete'}} +struct notComplete; +// expected-error@+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), ""); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits