Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
5 changes: 5 additions & 0 deletions clang/include/clang/AST/CXXRecordDeclDefinitionBits.def
Original file line number Diff line number Diff line change
Expand Up @@ -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
5 changes: 5 additions & 0 deletions clang/include/clang/AST/DeclCXX.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
9 changes: 8 additions & 1 deletion clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -2665,7 +2665,8 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
bool isHLSLAttributedResourceType() const;
bool isHLSLIntangibleType()
const; // Any HLSL intangible type (builtin, array, class)

bool isHLSLLineVectorLayoutCompatibleType()
const; // Any HLSL line vector layout compatible type
/// Determines if this type, which must satisfy
/// isObjCLifetimeType(), is implicitly __unsafe_unretained rather
/// than implicitly __strong.
Expand Down Expand Up @@ -8459,6 +8460,12 @@ inline bool Type::isHLSLBuiltinIntangibleType() const {
false;
}

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 isHLSLBuiltinIntangibleType() || isHLSLAttributedResourceType();
}
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_line_vector_layout_compatible, IsLineVectorLayoutCompatibleType, 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 IsLineVectorLayoutCompatibleType(QualType T1);

bool CheckCompatibleParameterABI(FunctionDecl *New, FunctionDecl *Old);

Expand Down
6 changes: 5 additions & 1 deletion clang/lib/AST/DeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}

Expand Down Expand Up @@ -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
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_IsLineVectorLayoutCompatibleType:
// 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_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);
}
}

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::IsLineVectorLayoutCompatibleType(clang::QualType QT) {
if (QT.isNull())
return false;

llvm::SmallVector<QualType, 16> 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;

// 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;
Expand Down
101 changes: 101 additions & 0 deletions clang/test/SemaHLSL/Types/Traits/IsLineVectorLayoutCompatibleType.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_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>), "");


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_line_vector_layout_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_line_vector_layout_compatible(notComplete), "");

Loading