Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -2665,7 +2665,6 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
bool isHLSLAttributedResourceType() const;
bool isHLSLIntangibleType()
const; // Any HLSL intangible type (builtin, array, class)

/// Determines if this type, which must satisfy
/// isObjCLifetimeType(), is implicitly __unsafe_unretained rather
/// than implicitly __strong.
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/TokenKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Sema/SemaHLSL.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
10 changes: 10 additions & 0 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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);
}
}

Expand Down
45 changes: 45 additions & 0 deletions clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2163,6 +2163,51 @@ 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];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could add an assert on the vector size or a check with llvm_unreachable when size is 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->getKind() == BuiltinType::Bool ||
BT->getKind() == BuiltinType::Enum)
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;
Expand Down
101 changes: 101 additions & 0 deletions clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatible.hlsl
Original file line number Diff line number Diff line change
@@ -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>), "");


Original file line number Diff line number Diff line change
@@ -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@+1{{forward declaration of 'notComplete'}}
struct notComplete;
// expected-error@+1{{incomplete type 'notComplete' where a complete type is required}}
_Static_assert(!__builtin_hlsl_is_typed_resource_element_compatible(notComplete), "");

Loading